| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Physics::Ballistics::Terminal; |
|
2
|
1
|
|
|
1
|
|
145530
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
68
|
|
|
4
|
|
|
|
|
|
|
require Exporter; |
|
5
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
6
|
|
|
|
|
|
|
our @EXPORT = qw(anderson boxes heat_dop ke me2te me2ce me2cem odermatt pc pc_simple hits_score sigma average rndto r2d d2r poncelet te2me lethality hv2bhn bhn2hv hrc2bhn bhn2hrc psi2bhn bhn2psi); |
|
7
|
|
|
|
|
|
|
our $VERSION = '1.03'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
244
|
use Physics::Ballistics; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
44
|
|
|
10
|
1
|
|
|
1
|
|
12
|
use Math::Trig; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
5914
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Physics::Ballistics::Terminal -- Terminal ballistics formulae. |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=cut |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 ABSTRACT |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Terminal ballistics is the study of what happens when a projectile impacts |
|
21
|
|
|
|
|
|
|
its target. This module implements a variety of functions and mathematical |
|
22
|
|
|
|
|
|
|
formulae useful in the analysis and prediction of terminal ballistic effects. |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 TWO DOMAINS OF VELOCITY |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Some of these functions pertain to the "ballistic" domain, and others pertain |
|
27
|
|
|
|
|
|
|
to the "hypervelocity" domain. These refer to two different and somewhat |
|
28
|
|
|
|
|
|
|
ill-defined ranges of velocity. "Ballistic" velocity ranges from about 300 |
|
29
|
|
|
|
|
|
|
to 1100 meters per second, while "Hypervelocity" ranges from about 1100 meters |
|
30
|
|
|
|
|
|
|
per second to several tens of thousands of meters per second. |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Why does this matter? Because successful models of ballistic interactions |
|
33
|
|
|
|
|
|
|
are not accurate in the hypervelocity domain, and successful models of |
|
34
|
|
|
|
|
|
|
hypervelocty interactions are not accurate in the ballistic domain. Thus it |
|
35
|
|
|
|
|
|
|
is crucial to use the model which is valid for the velocity of interaction |
|
36
|
|
|
|
|
|
|
you are attempting to predict. |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Functions which are only valid in one domain or the other will be thus marked. |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 REGARDING BULLET DIAMETERS |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Some of these functions require the diameter of a projectile as a parameter. |
|
43
|
|
|
|
|
|
|
Please note that bullet diameters are usually different from the names of |
|
44
|
|
|
|
|
|
|
their calibers. NATO 5.56mm bullets are actually 5.70mm in diameter, while |
|
45
|
|
|
|
|
|
|
Russian 5.45mm bullets are actually 5.62mm. .308 caliber bullets really are |
|
46
|
|
|
|
|
|
|
0.308 inches in diameter (7.82mm), but .22 Long Rifle bullets are 0.222 |
|
47
|
|
|
|
|
|
|
inches across. Please do not make assumptions; check before plugging it in! |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head1 DEFINITIONS |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head2 DU |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
DU is short for "Depleted Uranium". This denotes any of a number of metallic |
|
54
|
|
|
|
|
|
|
alloys containing a high fraction of Uranium, the most common of which is |
|
55
|
|
|
|
|
|
|
99.25% Uranium and and 0.75% Titanium. This material is extremely dense and |
|
56
|
|
|
|
|
|
|
hard, and somewhat ductile, making it excellent for armor-piercing projectiles. |
|
57
|
|
|
|
|
|
|
Contrary to popular myth, DU projectiles are not "nuclear" and do not explode, |
|
58
|
|
|
|
|
|
|
though in the hypervelocity domain they can be pyrophoric. Nor is DU highly |
|
59
|
|
|
|
|
|
|
radioactive. It is, however, a heavy metal (like lead, mercury, and arsenic) |
|
60
|
|
|
|
|
|
|
and therefore toxic. |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 MILD STEEL |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
There are many thousands of steel formulations and treatments, resulting in |
|
65
|
|
|
|
|
|
|
myriad different strengths and hardnesses. "Mild Steel" is a general term |
|
66
|
|
|
|
|
|
|
for any of a number of inexpensive steels of moderate to low strength and |
|
67
|
|
|
|
|
|
|
hardness. The steels used in rebar, trench plates, automotive bodies, and |
|
68
|
|
|
|
|
|
|
other commodity and construction applications tend to be of this type. Mild |
|
69
|
|
|
|
|
|
|
steels are an inferior material for armor, providing only about 80% of the |
|
70
|
|
|
|
|
|
|
protection as an equivalent thickness of RHA. Mild steel is often used in |
|
71
|
|
|
|
|
|
|
military projectile cores (as in America's 7.62mm M80 "Ball") because it is |
|
72
|
|
|
|
|
|
|
cheap and much more ductile than hardened steels. This ductility makes it |
|
73
|
|
|
|
|
|
|
less likely to fracture while penetrating its target (whether the target is |
|
74
|
|
|
|
|
|
|
made of flesh or harder stuff). |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=head2 RHA |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
RHA is short for "Rolled Homogenous Armor". It is a commonly-used term for |
|
79
|
|
|
|
|
|
|
hardened steel armor material in general, or for armor steel which complies |
|
80
|
|
|
|
|
|
|
with the military specification MIL-A-12560. RHA is also a common standard |
|
81
|
|
|
|
|
|
|
material for normalizing depth of penetration. It is roughly equivalent to |
|
82
|
|
|
|
|
|
|
AISI 4340 steel in character, and AISI 4340 is often used in lieu of "real" |
|
83
|
|
|
|
|
|
|
RHA in laboratory experiments. |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Unless otherwise noted, return values representing a depth of penetration |
|
86
|
|
|
|
|
|
|
should be understood to represent depth of penetration into an RHA target. |
|
87
|
|
|
|
|
|
|
It is common for armor systems to represent their resistance to penetration |
|
88
|
|
|
|
|
|
|
in terms of RHA thickness. |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 WC |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
WC is short for "Tungsten Carbide". This is a technical ceramic of tungsten |
|
93
|
|
|
|
|
|
|
and carbon, a dense and hard material of relatively low expense. WC has seen |
|
94
|
|
|
|
|
|
|
prolific use in armor-piercing projectiles because high density and hardness |
|
95
|
|
|
|
|
|
|
are both desirable qualities in that role. Being a ceramic, however, it is |
|
96
|
|
|
|
|
|
|
also brittle, and thus vulnerable to modern composite armors, which use |
|
97
|
|
|
|
|
|
|
synergistic effects to break up projectiles and thus degrade their penetration |
|
98
|
|
|
|
|
|
|
capabilities. Thus, WC penetrators are less capable of penetrating composite |
|
99
|
|
|
|
|
|
|
armor systems than indicated by their RHA equivalence ratings (since their |
|
100
|
|
|
|
|
|
|
brittleness plays less of a role in limiting their penetration into monolithic |
|
101
|
|
|
|
|
|
|
steel targets). |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=head2 WHA |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
WHA is short for "Tungsten-Heavy Alloy". This denotes any of several metallic |
|
106
|
|
|
|
|
|
|
alloys containing a high fraction of Tungsten. Some formulations offer high |
|
107
|
|
|
|
|
|
|
density, hardness and resilience (such as 90% W / 7% Ni / 3% Fe) making them |
|
108
|
|
|
|
|
|
|
excellent materials for armor-piercing projectiles. Unlike WC, appropriate WHA |
|
109
|
|
|
|
|
|
|
formulations are not brittle, and are unlikely to break from passing through |
|
110
|
|
|
|
|
|
|
composite armor systems. |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=head1 ANNOTATIONS OF SOURCES |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
Regarding their source, these functions fall into three categories: Some are |
|
115
|
|
|
|
|
|
|
simple encodings of basic physics (like energy = 1/2 * mass * velocity**2), |
|
116
|
|
|
|
|
|
|
and these will not be cited. Others are from published works, such as books |
|
117
|
|
|
|
|
|
|
or trade journals, and these will be cited when possible. A few are products |
|
118
|
|
|
|
|
|
|
of my own efforts, and will be thus annotated. |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 OOP INTERFACE |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
A more integrated, object-oriented interface for these functions is under |
|
123
|
|
|
|
|
|
|
development. |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head2 anderson (length_cm, diam_cm, vel_kps, [penetrator_material,] [deg_angle,] [scaling_factor]) |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Attempts to estimate how deeply a long-rod projectile will penetrate into RHA (semi-infinite penetration). |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
This function is based on Anderson's _Accuracy of Perforation Equations_, less 11% correction per that paper's conclusions, and including adjustments from Lakowski for scale, material, and backsurface effects. |
|
132
|
|
|
|
|
|
|
qv: L |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
ONLY VALID IN HYPERVELOCITY DOMAIN. |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=over 4 |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
parameter: (float) penetrator length (in cm) |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
parameter: (float) penetrator diameter (in cm) |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
parameter: (float) penetrator velocity (in kilometers per second) |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
parameter: (float or string) OPTIONAL: penetrator material or material multiplier. (defaults to 1.0) Valid values are: |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=over 4 |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
* an integer, for custom material factors |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
* "steel": Hardened steel == 0.50 |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
* "wha": Tungsten-heavy alloy (NOT tungsten carbide) == 1.00 |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
* "wc": Tungsten Carbide == 0.72 |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
* "du": Depleted uranium alloy == 1.13 |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=back |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: angle of impact, 0 == perpendicular to target surface (in degrees, defaults to 0) |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: scaling effect, relative to M829A2 dimensions (unitless, defaults to 1.0) |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
returns: (float) Depth of penetration (in cm) |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=back |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=cut |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# Given attributes of a hypervelocity-domain long-rod penetrator, returns penetration into RHA, in cm. |
|
171
|
|
|
|
|
|
|
# Based on Anderson TN, from _Accuracy of Perforation Equations_, less 11% correction per that paper's conclusions, and including adjustments from Lakowski for scale, material, and backsurface effects, qv: http://tank-net.com/forums/index.php?showtopic=8332&pid=156211&mode=threaded&show=&st=& and http://63.99.108.76/forums/index.php?showtopic=10482&st=100 |
|
172
|
|
|
|
|
|
|
# NOTE: only valid in hypervelocity domain, above 1100 meters/second. |
|
173
|
|
|
|
|
|
|
sub anderson { |
|
174
|
3
|
|
|
3
|
1
|
1638
|
my ($len, $diam, $vel, $material, $deg_angle, $scaling) = @_; |
|
175
|
3
|
50
|
33
|
|
|
21
|
die("usage: pen_cm = anderson(length_cm, diam_cm, vel_kps, material, [ deg_angle ]") unless (defined($len) && defined($vel)); |
|
176
|
3
|
50
|
|
|
|
10
|
$scaling = 1.0 unless (defined($scaling)); |
|
177
|
3
|
50
|
|
|
|
8
|
$material = 1.0 unless (defined($material)); # 1.00 = WHA |
|
178
|
3
|
|
|
|
|
19
|
$material = lc($material); |
|
179
|
3
|
50
|
|
|
|
10
|
$material = 1.00 if ($material eq 'wha'); # Tungsten Heavy Alloy |
|
180
|
3
|
50
|
|
|
|
11
|
$material = 1.13 if ($material eq 'du'); # Depleted Uranium / Titanium Alloy |
|
181
|
3
|
50
|
|
|
|
8
|
$material = 1.20 if ($material eq 'duv'); # Depleted Uranium / Vanadium Alloy |
|
182
|
3
|
50
|
|
|
|
8
|
$material = 0.72 if ($material eq 'wc'); # Tungsten Carbide |
|
183
|
3
|
50
|
|
|
|
8
|
$material = 0.50 if ($material eq 'steel'); |
|
184
|
3
|
50
|
|
|
|
14
|
$material = 0.50 if ($material =~ /[^\d\.]/); |
|
185
|
3
|
50
|
|
|
|
9
|
$deg_angle = 0 unless (defined($deg_angle)); |
|
186
|
3
|
|
|
|
|
9
|
my $angle = pi * $deg_angle / 180; # convert degrees to radians |
|
187
|
3
|
|
|
|
|
13
|
my $log1 = log($len / $diam); |
|
188
|
3
|
|
|
|
|
10
|
my $baseline = (1.044 * $vel) - (0.194 * log($len / $diam)) - 0.212; |
|
189
|
3
|
|
|
|
|
10
|
my $scale_effect = 1 + ($diam / (13 * $scaling)); |
|
190
|
3
|
|
|
|
|
15
|
my $backsurface = $diam / cos($angle); |
|
191
|
3
|
|
|
|
|
9
|
my $base_pen = $baseline * $scale_effect * $len; |
|
192
|
3
|
|
|
|
|
10
|
my $penetration = $base_pen * $material; |
|
193
|
3
|
|
|
|
|
7
|
$penetration = $penetration + $backsurface; |
|
194
|
3
|
|
|
|
|
5
|
$penetration = $penetration * .89; # less 11% -- Anderson's own analysis concluded that this formula overpredicts penetration by about this much |
|
195
|
3
|
|
|
|
|
10
|
$penetration = int($penetration * 10 + 0.5) / 10; |
|
196
|
3
|
|
|
|
|
11
|
return $penetration; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head2 boxes (length, width, height, front thickness, back thickness, side thickness, top thickness, underside thickness, density) |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Calculates the volumes, mass, and volume-to-mass ratio of a hollow box of rectangular cross-sections. |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=over 4 |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
parameter: (float) interior distance from front to back (in cm) |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
parameter: (float) interior distance from left to right (in cm) |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
parameter: (float) interior distance from top to bottom (in cm) |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
parameter: (float) thickness of front wall (in cm) |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
parameter: (float) thickness of back wall (in cm) |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
parameter: (float) thickness of side walls (in cm) |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
parameter: (float) thickness of bottom wall (in cm) |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
parameter: (float) specific density of wall material (g/cc) |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
returns: |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=over 4 |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
* (float) interior volume (in cc) |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
* (float) exterior volume (in cc) |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
* (float) total wall mass (in grams) |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
* (float) ratio of interior volume to mass (cc/g) |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=back |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=back |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=cut |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub boxes { # params: length, width, height, thick / front, back, side, top, bottom, den |
|
240
|
1
|
|
|
1
|
1
|
548
|
my ($inx, $iny, $inz, $tf, $tb, $ts, $tt, $tu, $den) = @_; |
|
241
|
1
|
50
|
|
|
|
5
|
die("usage: boxes ( interior_x_cm, int_y, int_z, thickness_front_cm, thick_back, thick_side, thick_top, density ) = string") unless ( defined($inx) ); |
|
242
|
1
|
|
|
|
|
3
|
my ($inv, $ouv, $vdiff, $mass, $retval, $lbs, $rat); |
|
243
|
1
|
|
|
|
|
3
|
$inv = $inx * $iny * $inz; |
|
244
|
1
|
|
|
|
|
4
|
$ouv = ($inx + $tf + $tb) * ($iny + 2 * $ts) * ($inz + $tt + $tu); |
|
245
|
1
|
|
|
|
|
2
|
$vdiff = $ouv - $inv; |
|
246
|
1
|
|
|
|
|
3
|
$mass = $vdiff * $den; |
|
247
|
1
|
|
|
|
|
4
|
$rat = int($inv * 100 / $mass) / 100; |
|
248
|
|
|
|
|
|
|
# returns: interior volume in cc, exterior volume, difference between interior and exterior volumes, |
|
249
|
|
|
|
|
|
|
# mass in grams, mass in pounds, and ratio of interior volume to mass (cc/g) |
|
250
|
1
|
|
|
|
|
5
|
return ($inv, $ouv, $mass, $rat); |
|
251
|
|
|
|
|
|
|
} |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head2 heat_dop(diameter_mm, standoff_distance, [target_density,] [precision_bool], [target_hardness_bhn]) |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Attempts to predict the depth of penetration of a copper-lined conical shaped charge into steel. |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Based on Ogorkiewicz's book, _Design and Development of Fighting Vehicles_, and |
|
258
|
|
|
|
|
|
|
modified as per _Journal of Battlefield Technology_ Vol 1-1 pp 1. A copy of |
|
259
|
|
|
|
|
|
|
the JBT chart may be found at: |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
L |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
The author has modified this formula slightly to account for errors observed in |
|
264
|
|
|
|
|
|
|
Ogorkiewicz's results, relative to empirically derived results. |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
For better understanding of shaped charge penetration, please review: |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
L |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=over 4 |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
parameter: (float) cone diameter (in mm) |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
parameter: (float or str) standoff distance (multiple of cone diameter if float, else in mm, for instance "80.5mm") |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: density of target material (in g/cc, default is 7.86, the density of RHA) |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
parameter: (boolean) OPTIONAL: assume precision shaped charge (default is False) |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: hardness of target material (in BHN, default is 300, low in the range of RHA hardnesses) |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
returns: (int) depth of penetration (in mm) |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=back |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=cut |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# Copper-lined shaped charge depth of penetration, lifted from Ogorkiewicz's _Design and Development of Fighting Vehicles_, and modified as per _Journal of Battlefield Technology_ Vol 1-1 pp 1, copy of chart from that article can be found at: http://ciar.org/ttk/mbt/news/news.smm.ww2-armor-plate.de5bf54f.0110271532.871cbf@posting.google.com.txt |
|
289
|
|
|
|
|
|
|
# NOTE: does not take into account any advanced effects from composited targets. |
|
290
|
|
|
|
|
|
|
# NOTE: removed jet density parameter from argument list because liner ductility effects eclipse liner density in practice, and I don't want to factor liner ductility into this code right now. (eg: according to Ogorkiewicz, a steel liner would increase penetration, but in practice steel liners reduce penetration due to their relatively low ductility.) |
|
291
|
|
|
|
|
|
|
# NOTE: Ogorkiewicz's curve for nonprecision charges was a little low at optimal standoff and high elsewhere relative to the _JoBT_ article chart, so I split the difference. I suspect his precision charge curve is similarly a bit optimistic in favor of higher penetration, so take it with a grain of salt. |
|
292
|
|
|
|
|
|
|
sub heat_dop { |
|
293
|
3
|
|
|
3
|
1
|
3996
|
my ($diam, $soff, $aden, $prec, $hard) = @_; |
|
294
|
3
|
|
|
|
|
8
|
my $jden; |
|
295
|
3
|
|
|
|
|
6
|
my $pen = 0; |
|
296
|
3
|
50
|
|
|
|
11
|
die("usage: heat_dop (diameter_mm, standoff[mm], [targ-den], [precision], [hard])\nDiameter units is mm\nstandoff assumed cd's unless 'mm' is specified\ntarget density default is 7.86 (RHA)\nprecision default is 0 (non-precision), 1 for high precision\nhardness is BHN, default is 300 (ignore if not steel)\nReturns depth of penetration in mm") unless (defined ($soff)); |
|
297
|
3
|
|
100
|
|
|
13
|
$aden //= 7.86; |
|
298
|
3
|
|
50
|
|
|
17
|
$jden //= 8.96; |
|
299
|
3
|
|
100
|
|
|
13
|
$prec //= 0; |
|
300
|
3
|
|
50
|
|
|
14
|
$hard //= 300; |
|
301
|
|
|
|
|
|
|
# print (" aden=$aden jden=$jden prec=$prec hard=$hard\n"); |
|
302
|
3
|
|
|
|
|
7
|
my $MIN_DENSITY = 0.00000000001; |
|
303
|
3
|
50
|
|
|
|
10
|
$aden = $MIN_DENSITY if ($aden < $MIN_DENSITY); # avoid divide-by-zero error |
|
304
|
3
|
50
|
|
|
|
23
|
if ($soff =~ /(\d+)mm/) { $soff = $1 / $diam; } # normalize to factor of cone diameters |
|
|
0
|
|
|
|
|
0
|
|
|
305
|
|
|
|
|
|
|
# $soff *= ($hard / 300)**0.5; # I'm guessing here -- target hardness does appear to shift optimal standoff, but effects of nonoptimal standoff not quite proportional to this relation. -- zzapp, figure this out. |
|
306
|
3
|
100
|
|
|
|
11
|
if ($prec) { |
|
307
|
|
|
|
|
|
|
# precision shaped charge DoP curve looks something like this: |
|
308
|
1
|
50
|
|
|
|
8
|
if ($soff <= 1) { $pen = 3.0 + 1.500 * ($soff - 0); } |
|
|
0
|
50
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
309
|
1
|
|
|
|
|
4
|
elsif ($soff <= 3) { $pen = 4.5 + 0.350 * ($soff - 1); } |
|
310
|
0
|
|
|
|
|
0
|
elsif ($soff <= 6) { $pen = 5.2 + 0.100 * ($soff - 3); } |
|
311
|
0
|
|
|
|
|
0
|
elsif ($soff <= 9) { $pen = 5.5 - 0.033 * ($soff - 6); } |
|
312
|
0
|
|
|
|
|
0
|
else { $pen = 5.4 - (($soff - 9) / 4.117); } |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
else { |
|
315
|
|
|
|
|
|
|
# nonprecision shaped charge DoP curve looks something like this: |
|
316
|
2
|
50
|
|
|
|
13
|
if ($soff <= 1) { $pen = 3.00 + 1.200 * ($soff - 0); } |
|
|
0
|
50
|
|
|
|
0
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
0
|
elsif ($soff <= 2) { $pen = 4.20 + 0.150 * ($soff - 1); } |
|
318
|
2
|
|
|
|
|
8
|
elsif ($soff <= 3) { $pen = 4.35 - 0.150 * ($soff - 2); } |
|
319
|
0
|
|
|
|
|
0
|
elsif ($soff <= 4) { $pen = 4.20 - 0.400 * ($soff - 3); } |
|
320
|
0
|
|
|
|
|
0
|
elsif ($soff <= 7) { $pen = 4.00 - 0.550 * ($soff - 4); } |
|
321
|
0
|
|
|
|
|
0
|
elsif ($soff <= 10) { $pen = 2.35 - 0.170 * ($soff - 7); } |
|
322
|
0
|
|
|
|
|
0
|
else { $pen = 1.84 - (($soff - 10) / 7.95); } |
|
323
|
|
|
|
|
|
|
} |
|
324
|
3
|
|
|
|
|
17
|
$pen *= (($jden / $aden) / (8.96 / 7.86))**0.5; |
|
325
|
3
|
|
|
|
|
7
|
$pen *= $diam; |
|
326
|
|
|
|
|
|
|
# round off, this is *not* any kind of precise estimate! |
|
327
|
3
|
|
|
|
|
8
|
$pen = int($pen + 0.5); |
|
328
|
3
|
|
|
|
|
11
|
return $pen; # returns millimeters |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# ke: removed: use P::B::E::muzzle_energy() instead |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head2 me2te (mass_efficiency, density) |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Given the mass efficiency of a material, returns its thickness efficiency. |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
This function is used when comparing armor materials on the basis of their RHA |
|
338
|
|
|
|
|
|
|
equivalence. Mass efficiency is a factor of how much armor mass than RHA mass |
|
339
|
|
|
|
|
|
|
provides the same resistance to penetration. Conversely, thickness efficiency |
|
340
|
|
|
|
|
|
|
is a factor of how much less armor thickness than RHA thickness provides the |
|
341
|
|
|
|
|
|
|
same resistance to penetration. |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
For instance, if an armor material has a mass efficiency of 4.0, then only a |
|
344
|
|
|
|
|
|
|
quarter as much mass is needed to provide a given protection level compared to |
|
345
|
|
|
|
|
|
|
RHA of equivalent protection. A pound of the armor material provides the same |
|
346
|
|
|
|
|
|
|
protection as four pounds of RHA. |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Similarly, if an armor material has a thickness efficiency of 3.0, then only a |
|
349
|
|
|
|
|
|
|
third as much thickness is needed to provide a given protection level compared |
|
350
|
|
|
|
|
|
|
to RHA of equivalent protection. An inch of the armor material provides the |
|
351
|
|
|
|
|
|
|
same protection as three inches of RHA. |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
If the density of the armor material is known, me2te() and te2me() may be used |
|
354
|
|
|
|
|
|
|
to convert back and forth between mass efficiency or thickness efficiency, |
|
355
|
|
|
|
|
|
|
depending on which is known. |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=over 4 |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
parameter: (float) armor material mass efficiency (unitless, factor relative to RHA) |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
parameter: (float) armor material density (g/cc) |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
returns: (float) armor material thickness efficiency (unitless, factor relative to RHA) |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=back |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=cut |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub me2te { # given mass efficiency and density, returns thickness efficiency |
|
370
|
1
|
|
|
1
|
1
|
494
|
my ($me, $den) = @_; |
|
371
|
1
|
|
|
|
|
5
|
return $me * $den / 7.86; |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=head2 me2ce (mass_efficiency, cost_usd_per_pound) |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Given the mass efficiency of a material, returns its cost efficiency. |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
See the description of me2te() for more explanation. |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
This actually returns the cost efficiency relative to AISI 4340 steel, which is |
|
381
|
|
|
|
|
|
|
often used as a close approximation to RHA. The costs of actual MIL-A-12560 |
|
382
|
|
|
|
|
|
|
compliant steel are dominated by political factors, which are beyond the scope |
|
383
|
|
|
|
|
|
|
of this module. |
|
384
|
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=over 4 |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
parameter: (float) armor material mass efficiency (unitless, factor relative to RHA) |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
parameter: (float) armor material cost (USA dollars / pound) |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
returns: (float) armor material cost efficiency (unitless, factor relative to RHA) |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=back |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=cut |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
sub me2ce { # given mass efficiency and cost per pound, returns cost efficiency relative to AISI 4340 steel (which closely approximates characteristics of RHA). |
|
398
|
1
|
|
|
1
|
1
|
487
|
my ($me, $cost) = @_; |
|
399
|
|
|
|
|
|
|
# AISI 4340 steel is about $3.80/lb; qv https://www.metalsupermarkets.com/CART.ASPX?PRODUCTID=MR4340/9 |
|
400
|
1
|
|
|
|
|
5
|
return $me * 3.80 / $cost; |
|
401
|
|
|
|
|
|
|
} |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=head2 me2cem (mass_efficiency, cost_usd_per_pound) |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
Given the mass efficiency of a material, returns its cost efficiency relative to mild steel. |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
See the description of me2ce() for more explanation. |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=over 4 |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
parameter: (float) armor material mass efficiency (unitless, factor relative to RHA) |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
parameter: (float) armor material cost (USA dollars / pound) |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
returns: (float) armor material cost efficiency (unitless, factor relative to mild steel) |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=back |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=cut |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub me2cem { # given mass efficiency and cost per pound, returns cost efficiency relative to mild steel |
|
422
|
1
|
|
|
1
|
1
|
486
|
my ($me, $cost) = @_; |
|
423
|
1
|
|
|
|
|
3
|
my $mild_steel_cost = 0.40; # Mild Steel 1" Plate is about $0.40/lb |
|
424
|
1
|
|
|
|
|
3
|
my $mild_steel_me = 0.81; # Mild Steel 1" Plate has mass efficiency of about 0.81 |
|
425
|
1
|
|
|
|
|
5
|
return ($me * $mild_steel_cost) / ($cost * $mild_steel_me); |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head2 odermatt (length_cm, diam_cm, vel_mps, target_density, target_uts_kpsi, rod_density, deg_angle, kps_drop_per_km, range_km, target_thickness_cm, [tip_length_cm, kA1, kA2]) |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Attempts to estimate perforation limit for a long-rod projectile penetrating RHA. Produces more accurate results than Anderson, but also requires more hard-to-get information, and doesn't exactly measure the same thing (perforation limit, vs depth into semi-infinite target). |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
This function is based on Lanz and Odermatt's paper _Post Perforation Length & Velocity of KE Projectiles with single Oblique Targets_, published in the 15th International Symposium of Ballistics. |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
ONLY VALID IN HYPERVELOCITY DOMAIN. |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
Only valid for penetrator length/diameter ratios of 10.0 or higher, unless kA1 and kA2 are provided (which afaik can only be derived empirically, so good luck). |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=over 4 |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
parameter: (float) penetrator length (in cm) |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
parameter: (float) penetrator diameter (in cm) |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
parameter: (float) penetrator velocity (in meters per second) |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
parameter: (float) target density (in g/cc) |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
parameter: (float) target ultimate tensile strength (in kpsi) |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
parameter: (float) penetrator density (in g/cc) |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
parameter: (float) angle of impact (in degrees, 0 == perpendicular to target surface) |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
parameter: (float) target thickness (in cm) |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: penetrator tip length (in cm, defaults to three times penetrator diameter) |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: kA1 empirically discovered constant (only required for L/D < 10.0) |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
parameter: (float) OPTIONAL: kA2 empirically discovered constant (only required for L/D < 10.0) |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
returns: (float) Target's perforation limit (in cm) |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=back |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
=cut |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# Given attributes of a hypervelocity-domain long-rod penetrator and its target, returns limit of perforation depth, in cm. |
|
469
|
|
|
|
|
|
|
# Based on Odermatt's Perforation Limit Equation for long rod penetrators, valid for L:D of 10 or over. |
|
470
|
|
|
|
|
|
|
# 15th international symposium of ballistics - "Post Perforation Length & Velocity of KE Projectiles with Single Oblique Targets". |
|
471
|
|
|
|
|
|
|
# NOTE: only works for L:D of 10 or greater, unless kA1 and kA2 are defined. For smaller penetrators, use anderson or pc. |
|
472
|
|
|
|
|
|
|
# NOTE: only valid in hypervelocity domain, above 1100 meters/second. |
|
473
|
|
|
|
|
|
|
sub odermatt { |
|
474
|
1
|
|
|
1
|
1
|
509
|
my ($len, $diam, $vel, $pen_mat, $targ_mat, |
|
475
|
|
|
|
|
|
|
$penden, $deg_angle, $targthick, $tip_len, $targden, $targ_kpsi, $kA1, $kA2) = @_; |
|
476
|
1
|
0
|
0
|
|
|
8
|
die("Error: L:D of $len:$diam is outside this formula's domain\n") unless (($len / $diam >= 10) || (defined($kA1) && defined($kA2))); |
|
|
|
|
33
|
|
|
|
|
|
477
|
1
|
|
|
|
|
6
|
my %mat_to_den = ('du' => 18800, 'wha' => 17000, 'steel' => 7860); |
|
478
|
1
|
|
|
|
|
6
|
my %mat_to_a = ('du' => 0.825, 'wha' => 0.994, 'steel' => 1.104); |
|
479
|
1
|
|
|
|
|
5
|
my %mat_to_c0 = ('du' => 90.0, 'wha' => 134.5, 'steel' => 9874); # term 5 differs for steel, so const c given instead of c0 |
|
480
|
1
|
|
|
|
|
4
|
my %mat_to_c1 = ('du' => -0.0849, 'wha' => -0.148, 'steel' => 0); |
|
481
|
1
|
50
|
|
|
|
4
|
die("Error: Unsupported target material. Use one of: du wha steel\n") unless(defined($mat_to_a{$targ_mat})); |
|
482
|
1
|
50
|
|
|
|
5
|
die("Error: Unsupported penetrator material. Use one of: du wha steel\n") unless(defined($mat_to_c0{$pen_mat})); |
|
483
|
1
|
|
|
|
|
8
|
my $const_a = $mat_to_a{$targ_mat}; |
|
484
|
1
|
|
|
|
|
3
|
my $const_b0 = 0.283; |
|
485
|
1
|
|
|
|
|
3
|
my $const_b1 = 0.0656; |
|
486
|
1
|
|
|
|
|
3
|
my $const_c0 = $mat_to_c0{$pen_mat}; |
|
487
|
1
|
|
|
|
|
4
|
my $const_c1 = $mat_to_c1{$pen_mat}; |
|
488
|
|
|
|
|
|
|
# zzzappp |
|
489
|
1
|
|
|
|
|
4
|
my $targ_mpa = $targ_kpsi * 6.895; # converting kpsi to MPa |
|
490
|
1
|
|
|
|
|
4
|
my $targ_den_gm3 = $targden * 1000; # converting g/cc to kg/m3 |
|
491
|
1
|
|
|
|
|
3
|
my $pen_den_gm3 = $penden * 1000; # converting g/cc to kg/m3 |
|
492
|
1
|
|
|
|
|
3
|
my $diam_mm = $diam * 10; # cm to mm |
|
493
|
1
|
|
|
|
|
20
|
my $len_mm = $len * 10; # cm to mm |
|
494
|
1
|
|
|
|
|
3
|
my $targ_mm = $targthick * 10; # cm to mm |
|
495
|
1
|
|
50
|
|
|
8
|
$kA1 = $kA1 || 3.94; |
|
496
|
1
|
|
50
|
|
|
5
|
$kA2 = $kA2 || 11.20; |
|
497
|
1
|
|
33
|
|
|
5
|
$tip_len = $tip_len || $diam * 3; # if no tip length given, assume three diameters long |
|
498
|
1
|
|
|
|
|
3
|
$tip_len = $tip_len * 10; # cm to mm |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
# length to diameter ratio influence (valid for Lw/D of at least 10 -- if Lw/D is lower, use anderson): |
|
501
|
1
|
|
|
|
|
4
|
my $Lw = $len_mm - 2 * $tip_len / 3 - 1.5 * $diam_mm; # approximation of length of penetrator after replacing conical tip with cylinder of equal mass and diameter and reducing remaining length by 1.5 diameters |
|
502
|
|
|
|
|
|
|
# print "Lw= len_mm=$len_mm - 2 * tip_len=$tip_len / 3 - 1.5 * diam_mm=$diam_mm = $Lw\n"; |
|
503
|
1
|
|
|
|
|
8
|
my $LDtanh = Math::Trig::tanh(($Lw / $diam_mm) - 10); |
|
504
|
1
|
|
|
|
|
49
|
my $facA = 1 + $kA1 * $diam_mm / ($Lw * (1 - $LDtanh / $kA2)); |
|
505
|
|
|
|
|
|
|
# print "facA = 1 + kA1=$kA1 * diam_mm=$diam_mm / (Lw=$Lw * (1 - LDtanh=$LDtanh / kA2=$kA2)) = $facA\n"; |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# target obliquity: |
|
508
|
1
|
|
|
|
|
4
|
my $rad_angle = pi * $deg_angle / 180; # convert degrees to radians |
|
509
|
1
|
|
|
|
|
3
|
my $facB = 0; # target obliquity |
|
510
|
1
|
|
|
|
|
6
|
$facB = cos($rad_angle)**-0.225; |
|
511
|
|
|
|
|
|
|
# print "facB = cos(rad_angle=$rad_angle)**-0.225 = $facB\n"; |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# density ratio of penetrator to target |
|
514
|
1
|
|
|
|
|
4
|
my $facC = ($pen_den_gm3 / $targ_den_gm3)**0.5; |
|
515
|
|
|
|
|
|
|
# print "facC = (pen_den_gm3=$pen_den_gm3 / targ_den_gm3=$targ_den_gm3)**0.5 = $facC\n"; |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# material properties and impact velocity |
|
518
|
1
|
|
|
|
|
5
|
my $targMatFac = 22.1 + 0.01274 * $targ_mpa - 0.00000947 * $targ_mpa**2; |
|
519
|
|
|
|
|
|
|
# print "pen_den_gm3 = $pen_den_gm3 vel=$vel\n"; |
|
520
|
1
|
|
|
|
|
3
|
my $facD_N = -1 * $targMatFac * $targ_mpa; |
|
521
|
|
|
|
|
|
|
# print "facD_N = -1 * targMatFac=$targMatFac * targ_mpa=$targ_mpa = $facD_N\n"; |
|
522
|
1
|
|
|
|
|
2
|
my $facD_D = $pen_den_gm3 * $vel**2; |
|
523
|
|
|
|
|
|
|
# print "facD_D = pen_den_gm3=$pen_den_gm3 * vel=$vel**2 = $facD_D\n"; |
|
524
|
1
|
|
|
|
|
3
|
my $facD = exp($facD_N / $facD_D); |
|
525
|
|
|
|
|
|
|
# print "facD = exp(facD_N=$facD_N / facD_D=$facD_D) = $facD\n"; |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# print "len_mm=$len_mm facA(diam,len)=$facA facB(angle)=$facB facC(pden,tden)=$facC facD(targ_mpa,pden,vel)=$facD\n"; |
|
528
|
1
|
|
|
|
|
3
|
my $penetration_mm = $len_mm * $facA * $facB * $facC * $facD; |
|
529
|
1
|
|
|
|
|
4
|
my $penetration_cm = int($penetration_mm + 0.5) / 10; # rounding to nearest mm, then converting to cm |
|
530
|
1
|
|
|
|
|
6
|
return $penetration_cm; |
|
531
|
|
|
|
|
|
|
} |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
# This formula implementation is horribly broken; still trying to figure it out. |
|
534
|
|
|
|
|
|
|
# Given attributes of a hypervelocity-domain long-rod penetrator and its target, returns penetration into RHA, in cm. |
|
535
|
|
|
|
|
|
|
# based on Lanz/Odermatt depth of penetration equation for long rod penetrators, valid for L:D of 10 or over. |
|
536
|
|
|
|
|
|
|
# 15th international symposium of ballistics - "Post Perforation Length & Velocity of KE Projectiles with Single Oblique Targets". |
|
537
|
|
|
|
|
|
|
# NOTE: only works for L:D of 10 or greater, unless kA1 and kA2 are defined. For smaller penetrators, use anderson or pc. |
|
538
|
|
|
|
|
|
|
# NOTE: only valid in hypervelocity domain, above 1100 meters/second. |
|
539
|
|
|
|
|
|
|
sub lanz_odermatt_BROKEN { |
|
540
|
0
|
|
|
0
|
0
|
0
|
my ($len, $diam, $vel, $targden, $targ_kpsi, $penden, $deg_angle, $targthick, $tip_len, $kA1, $kA2) = @_; |
|
541
|
0
|
0
|
0
|
|
|
0
|
die("usage: pen_cm = odermatt (length_cm, diam_cm, vel_mps, target_den, target_uts_kpsi, pen_density, deg_angle, target_thick, [tip_length_cm, kA1, kA2 ]") unless (defined($len) && defined($targthick)); |
|
542
|
0
|
0
|
0
|
|
|
0
|
die("error, L:D of $len:$diam is outside this formula's domain\n") unless (($len / $diam >= 10) || (defined($kA1) && defined($kA2))); |
|
|
|
|
0
|
|
|
|
|
|
543
|
|
|
|
|
|
|
# print "len=$len, diam=$diam, vel=$vel, targden=$targden, targ_kpsi=$targ_kpsi, penden=$penden, deg_angle=$deg_angle, targthick=$targthick, tip_len=$tip_len\n"; |
|
544
|
0
|
|
|
|
|
0
|
my $targ_mpa = $targ_kpsi * 6.895; # converting kpsi to MPa |
|
545
|
0
|
|
|
|
|
0
|
my $targ_den_gm3 = $targden * 1000; # converting g/cc to kg/m3 |
|
546
|
0
|
|
|
|
|
0
|
my $pen_den_gm3 = $penden * 1000; # converting g/cc to kg/m3 |
|
547
|
0
|
|
|
|
|
0
|
my $diam_mm = $diam * 10; # cm to mm |
|
548
|
0
|
|
|
|
|
0
|
my $len_mm = $len * 10; # cm to mm |
|
549
|
0
|
|
|
|
|
0
|
my $targ_mm = $targthick * 10; # cm to mm |
|
550
|
0
|
|
0
|
|
|
0
|
$kA1 = $kA1 || 3.94; |
|
551
|
0
|
|
0
|
|
|
0
|
$kA2 = $kA2 || 11.20; |
|
552
|
0
|
|
0
|
|
|
0
|
$tip_len = $tip_len || $diam * 3; # if no tip length given, assume three diameters long |
|
553
|
0
|
|
|
|
|
0
|
$tip_len = $tip_len * 10; # cm to mm |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
# length to diameter ratio influence (valid for Lw/D of at least 10 -- if Lw/D is lower, use anderson): |
|
556
|
0
|
|
|
|
|
0
|
my $Lw = $len_mm - 2 * $tip_len / 3 - 1.5 * $diam_mm; # approximation of length of penetrator after replacing conical tip with cylinder of equal mass and diameter and reducing remaining length by 1.5 diameters |
|
557
|
0
|
|
|
|
|
0
|
print "Lw= len_mm=$len_mm - 2 * tip_len=$tip_len / 3 - 1.5 * diam_mm=$diam_mm = $Lw\n"; |
|
558
|
0
|
|
|
|
|
0
|
my $LDtanh = Math::Trig::tanh(($Lw / $diam_mm) - 10); |
|
559
|
0
|
|
|
|
|
0
|
my $facA = 1 + $kA1 * $diam_mm / ($Lw * (1 - $LDtanh / $kA2)); |
|
560
|
0
|
|
|
|
|
0
|
print "facA = 1 + kA1=$kA1 * diam_mm=$diam_mm / (Lw=$Lw * (1 - LDtanh=$LDtanh / kA2=$kA2)) = $facA\n"; |
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# target obliquity: |
|
563
|
0
|
|
|
|
|
0
|
my $rad_angle = pi * $deg_angle / 180; # convert degrees to radians |
|
564
|
0
|
|
|
|
|
0
|
my $facB = 0; # target obliquity |
|
565
|
0
|
|
|
|
|
0
|
$facB = cos($rad_angle)**-0.225; |
|
566
|
0
|
|
|
|
|
0
|
print "facB = cos(rad_angle=$rad_angle)**-0.225 = $facB\n"; |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
# density ratio of penetrator to target |
|
569
|
0
|
|
|
|
|
0
|
my $facC = ($pen_den_gm3 / $targ_den_gm3)**0.5; |
|
570
|
0
|
|
|
|
|
0
|
print "facC = (pen_den_gm3=$pen_den_gm3 / targ_den_gm3=$targ_den_gm3)**0.5 = $facC\n"; |
|
571
|
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
# material properties and impact velocity |
|
573
|
0
|
|
|
|
|
0
|
my $targMatFac = 22.1 + 0.01274 * $targ_mpa - 0.00000947 * $targ_mpa**2; |
|
574
|
0
|
|
|
|
|
0
|
print "pen_den_gm3 = $pen_den_gm3 vel=$vel\n"; |
|
575
|
0
|
|
|
|
|
0
|
my $facD_N = -1 * $targMatFac * $targ_mpa; |
|
576
|
0
|
|
|
|
|
0
|
print "facD_N = -1 * targMatFac=$targMatFac * targ_mpa=$targ_mpa = $facD_N\n"; |
|
577
|
0
|
|
|
|
|
0
|
my $facD_D = $pen_den_gm3 * $vel**2; |
|
578
|
0
|
|
|
|
|
0
|
print "facD_D = pen_den_gm3=$pen_den_gm3 * vel=$vel**2 = $facD_D\n"; |
|
579
|
0
|
|
|
|
|
0
|
my $facD = exp($facD_N / $facD_D); |
|
580
|
0
|
|
|
|
|
0
|
print "facD = exp(facD_N=$facD_N / facD_D=$facD_D) = $facD\n"; |
|
581
|
|
|
|
|
|
|
|
|
582
|
0
|
|
|
|
|
0
|
print "len_mm=$len_mm facA(diam,len)=$facA facB(angle)=$facB facC(pden,tden)=$facC facD(targ_mpa,pden,vel)=$facD\n"; |
|
583
|
0
|
|
|
|
|
0
|
my $penetration_mm = $len_mm * $facA * $facB * $facC * $facD; |
|
584
|
0
|
|
|
|
|
0
|
my $penetration_cm = int($penetration_mm + 0.5) / 10; # rounding to nearest mm, then converting to cm |
|
585
|
0
|
|
|
|
|
0
|
return $penetration_cm; |
|
586
|
|
|
|
|
|
|
} |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=head2 pc (mass_grains, velocity_fps, distance_feet, diameter_inches, bullet_shape_str, [target_material]) |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
Attempts to estimate how deeply a small-arms projectile will penetrate into a target. |
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Optimized for projectiles near 7.5mm in diameter, works okay for projectiles as small as 5mm or as large as 14mm. |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
This function attempts to account for effects of projectile wobble (yaw instability) and the different effects |
|
595
|
|
|
|
|
|
|
wobble has on different target materials. The bullet is assumed to stabilize eventually, the stabilization distance |
|
596
|
|
|
|
|
|
|
depending on projectile mass. This feature is a work-in-progress, and should be taken with generous salt. |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
This function is the original work of the author. |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
ONLY VALID IN BALLISTIC DOMAIN. |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
Not recommended for masses outside 55..450 grains range, |
|
603
|
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
Not recommended for velocities outside 1200..3500 feet per second. |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
Not recommended for unjacketed lead projectiles. |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=over 4 |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
parameter: (float) penetrator mass (in grains) |
|
611
|
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
parameter: (float) penetrator velocity (in feet per second) |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
parameter: (float) distance between muzzle and target (in feet) |
|
615
|
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
parameter: (float) penetrator diameter (in inches) |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
parameter: (string) penetrator type, describing very approximately the general shape and composition of the projectile. Valid values are: |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
=over 4 |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
* "hp": Hollowpoint, composed of thin brass lining over lead core. |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
* "sp": Softpoint (exposed lead tip), composed of thin brass lining over lead core. |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
* "bp": FMJ "ball", composed of thin brass lining over lead core. |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
* "ms": Mild steel core, with ogival nose shape. |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
* "sc": Hard steel core, with truncated-cone nose shape. |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
* "hc": Synonym for "sc". |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
* "tc": Tungsten-carbide core (not WHA), with truncated-cone nose shape. |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
* "wc": Synonym for "tc". |
|
637
|
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
* "wha": Tungsten heavy alloy core (eg, 90% W / 7% Ni / 3% Fe), with truncated-cone nose shape. |
|
639
|
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
* "du": Depleted uranium alloy core (99.25% U / 0.75% Ti), with truncated-cone nose shape. |
|
641
|
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
The hash table mapping these type strings to their numeric penetration factors is available as %Physics::Ballistics::Terminal::Penetrator_Types_H, for ease of reference and modification. |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=back |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
parameter: (OPTIONAL) (string) target material. Valid target materials are: |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=over 4 |
|
649
|
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
* "pine": Soft, green pine wood. |
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
* "sand": Loose-packed, dry sand. |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
* "brick": Typical firebrick, as often used in residential exterior wall construction. |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
* "cinder": Cinderblock, as often used in inexpensive non-residential exterior wall construction. |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
* "concrete": Reinforced concrete, poured-in-place. |
|
659
|
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
* "mild": Mild steel, as often used in civilian construction or automotive body manufacture. |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
* "hard": Hardened steel of at least 250BHN, akin to RHA. |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=back |
|
665
|
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
returns: (float) estimated depth of penetration (in mm), rounded to the nearest tenth of a mm. |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=back |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
=cut |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
my $pc_exponents_hr = { |
|
673
|
|
|
|
|
|
|
sand => 2.0, |
|
674
|
|
|
|
|
|
|
pine => 2.2, |
|
675
|
|
|
|
|
|
|
conc => 0.8, |
|
676
|
|
|
|
|
|
|
brick => 0.55, |
|
677
|
|
|
|
|
|
|
cind => 0.32, |
|
678
|
|
|
|
|
|
|
mild => 0.30 |
|
679
|
|
|
|
|
|
|
}; |
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
my $pc_k_hr = { |
|
682
|
|
|
|
|
|
|
sand => 650**$pc_exponents_hr->{'sand'}, |
|
683
|
|
|
|
|
|
|
pine => 650**$pc_exponents_hr->{'pine'}, |
|
684
|
|
|
|
|
|
|
conc => 650**$pc_exponents_hr->{'conc'}, |
|
685
|
|
|
|
|
|
|
brick => 650**$pc_exponents_hr->{'brick'}, |
|
686
|
|
|
|
|
|
|
cind => 650**$pc_exponents_hr->{'cind'}, |
|
687
|
|
|
|
|
|
|
mild => 650**$pc_exponents_hr->{'mild'} |
|
688
|
|
|
|
|
|
|
}; |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
sub stabilization_distance_meters { |
|
691
|
31
|
|
|
31
|
0
|
68
|
my ($grain) = @_; |
|
692
|
31
|
|
|
|
|
95
|
return int(($grain**0.333) * 37.8); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
sub penetration_curve_sand { |
|
696
|
4
|
|
|
4
|
0
|
11
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
697
|
4
|
|
|
|
|
11
|
my $dist_stable = stabilization_distance_meters($grain); |
|
698
|
4
|
|
|
|
|
9
|
my $resistance_factor = 60; |
|
699
|
4
|
100
|
|
|
|
13
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
700
|
1
|
|
|
|
|
4
|
my $e_sand = 2.7; |
|
701
|
1
|
|
|
|
|
3
|
my $dist_limit = $dist_stable ** $e_sand; |
|
702
|
1
|
|
|
|
|
6
|
my $wobble_penalty = 0.50 * (($dist_limit - $dist_ft**$e_sand)/$dist_limit)**0.75; |
|
703
|
1
|
|
|
|
|
12
|
return $resistance_factor * (1-$wobble_penalty); |
|
704
|
|
|
|
|
|
|
} |
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
sub penetration_curve_pine { |
|
707
|
5
|
|
|
5
|
0
|
14
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
708
|
5
|
|
|
|
|
13
|
my $dist_stable = stabilization_distance_meters($grain); |
|
709
|
5
|
|
|
|
|
11
|
my $resistance_factor = 305; # was 803 -- TTK 2015-04-02 |
|
710
|
5
|
100
|
|
|
|
20
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
711
|
1
|
|
|
|
|
3
|
my $e_pine = 2.6; |
|
712
|
1
|
|
|
|
|
7
|
my $dist_limit = $dist_stable ** $e_pine; |
|
713
|
1
|
|
|
|
|
8
|
my $wobble_penalty = 0.75 * (($dist_limit - $dist_ft**$e_pine)/$dist_limit)**0.75; |
|
714
|
1
|
|
|
|
|
5
|
return $resistance_factor * (1-$wobble_penalty); |
|
715
|
|
|
|
|
|
|
} |
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub penetration_curve_concrete { |
|
718
|
0
|
|
|
0
|
0
|
0
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
719
|
0
|
|
|
|
|
0
|
my $dist_stable = stabilization_distance_meters($grain); |
|
720
|
0
|
|
|
|
|
0
|
my $resistance_factor = 40; |
|
721
|
0
|
0
|
|
|
|
0
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
722
|
0
|
|
|
|
|
0
|
my $e_concrete = 0.80; |
|
723
|
0
|
|
|
|
|
0
|
my $dist_limit = $dist_stable ** $e_concrete; |
|
724
|
0
|
|
|
|
|
0
|
my $wobble_penalty = 0.75 * (($dist_limit - $dist_ft**$e_concrete)/$dist_limit); |
|
725
|
0
|
|
|
|
|
0
|
return $resistance_factor * (1-$wobble_penalty); |
|
726
|
|
|
|
|
|
|
} |
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
sub penetration_curve_brick { |
|
729
|
4
|
|
|
4
|
0
|
12
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
730
|
4
|
|
|
|
|
11
|
my $dist_stable = stabilization_distance_meters($grain); |
|
731
|
4
|
|
|
|
|
9
|
my $resistance_factor = 42; |
|
732
|
4
|
100
|
|
|
|
16
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
733
|
1
|
|
|
|
|
3
|
my $e_brick = 0.55; |
|
734
|
1
|
|
|
|
|
3
|
my $dist_limit = $dist_stable ** $e_brick; |
|
735
|
1
|
|
|
|
|
5
|
my $wobble_penalty = 0.30 * (($dist_limit - $dist_ft**$e_brick)/$dist_limit); |
|
736
|
1
|
|
|
|
|
5
|
return $resistance_factor * (1-$wobble_penalty); |
|
737
|
|
|
|
|
|
|
} |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
sub penetration_curve_cinder { |
|
740
|
4
|
|
|
4
|
0
|
10
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
741
|
4
|
|
|
|
|
12
|
my $dist_stable = stabilization_distance_meters($grain); |
|
742
|
4
|
|
|
|
|
9
|
my $resistance_factor = 55; # was 157 -- TTK 2015-04-02 |
|
743
|
4
|
100
|
|
|
|
15
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
744
|
1
|
|
|
|
|
2
|
my $e_cinder = 0.55; |
|
745
|
1
|
|
|
|
|
4
|
my $dist_limit = $dist_stable ** $e_cinder; |
|
746
|
1
|
|
|
|
|
4
|
my $wobble_penalty = 0.25 * (($dist_limit - $dist_ft**$e_cinder)/$dist_limit); |
|
747
|
1
|
|
|
|
|
4
|
return $resistance_factor * (1-$wobble_penalty); |
|
748
|
|
|
|
|
|
|
} |
|
749
|
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
sub penetration_curve_mild_steel { |
|
751
|
10
|
|
|
10
|
0
|
24
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
752
|
10
|
|
|
|
|
28
|
my $dist_stable = stabilization_distance_meters($grain); |
|
753
|
10
|
|
|
|
|
21
|
my $resistance_factor = 1.25; |
|
754
|
10
|
100
|
|
|
|
32
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
755
|
3
|
|
|
|
|
8
|
my $e_mild = 0.82; |
|
756
|
3
|
|
|
|
|
7
|
my $dist_limit = $dist_stable ** $e_mild; |
|
757
|
3
|
|
|
|
|
10
|
my $wobble_penalty = 0.65 * (($dist_limit - $dist_ft**$e_mild)/$dist_limit); |
|
758
|
3
|
|
|
|
|
11
|
return $resistance_factor * (1-$wobble_penalty); |
|
759
|
|
|
|
|
|
|
} |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
sub penetration_curve_hard_steel { |
|
762
|
4
|
|
|
4
|
0
|
11
|
my ($dist_ft, $pen_typ, $grain) = @_; |
|
763
|
4
|
|
|
|
|
10
|
my $dist_stable = stabilization_distance_meters($grain); |
|
764
|
4
|
|
|
|
|
14
|
my $resistance_factor = 1.0; |
|
765
|
4
|
100
|
|
|
|
14
|
return $resistance_factor if ($dist_ft >= $dist_stable); |
|
766
|
1
|
|
|
|
|
3
|
my $e_hard = 0.91; |
|
767
|
1
|
|
|
|
|
4
|
my $dist_limit = $dist_stable ** $e_hard; |
|
768
|
1
|
|
|
|
|
5
|
my $wobble_penalty = 0.65 * (($dist_limit - $dist_ft**$e_hard)/$dist_limit); |
|
769
|
1
|
|
|
|
|
4
|
return $resistance_factor * (1-$wobble_penalty); |
|
770
|
|
|
|
|
|
|
} |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
sub pc { |
|
773
|
31
|
|
|
31
|
1
|
15815
|
my ($grain, $vel_fps, $dist_ft, $diam, $pen_typ, $target_material, $te) = @_; |
|
774
|
31
|
50
|
|
|
|
106
|
die("mm = pc(grains, velocity_fps, distance_feet, diam_inches, [{hp,sp,bp,ms,hs,sc,wc,tc,wha,du},] [{pine, sand, brick, cinder, concrete, mild, hard},] [, Te])") unless (defined ($diam)); |
|
775
|
31
|
50
|
|
|
|
77
|
$te = 1 unless (defined ($te)); # thickness efficiency of target material, relative to normal case (eg, RHA) |
|
776
|
31
|
|
|
|
|
223
|
my %curve_h = ( |
|
777
|
|
|
|
|
|
|
"pine" => \&penetration_curve_pine, |
|
778
|
|
|
|
|
|
|
"sand" => \&penetration_curve_sand, |
|
779
|
|
|
|
|
|
|
"brick" => \&penetration_curve_brick, |
|
780
|
|
|
|
|
|
|
"cinder" => \&penetration_curve_cinder, |
|
781
|
|
|
|
|
|
|
"concrete" => \&penetration_curve_concrete, |
|
782
|
|
|
|
|
|
|
"mild" => \&penetration_curve_mild_steel, |
|
783
|
|
|
|
|
|
|
"hard" => \&penetration_curve_hard_steel, |
|
784
|
|
|
|
|
|
|
"rha" => \&penetration_curve_hard_steel |
|
785
|
|
|
|
|
|
|
); |
|
786
|
31
|
|
|
|
|
75
|
my $curve_cr = $curve_h{"hard"}; |
|
787
|
31
|
50
|
|
|
|
87
|
$curve_cr = $curve_h{$target_material} if (defined($curve_h{$target_material})); |
|
788
|
31
|
|
|
|
|
151
|
my $KED = ($grain ** 1.29) * (($vel_fps/1000) ** 1.51) / ($diam ** 1.05); # energy density, sorta (fits empirical data) |
|
789
|
31
|
|
|
|
|
53
|
my $pf = undef; |
|
790
|
|
|
|
|
|
|
# $KED *= $pf if (defined($pf = $Physics::Ballistics::Terminal::Penetrator_Types_H{$pen_typ})); |
|
791
|
31
|
|
|
|
|
50
|
my $material_independent_constant = 1750; # was 2785 -- TTK 2015-04-02 |
|
792
|
31
|
|
|
|
|
79
|
my $penetration_depth_mm = $KED *= $curve_cr->($dist_ft, $pen_typ, $grain) / $material_independent_constant; |
|
793
|
31
|
50
|
|
|
|
103
|
$penetration_depth_mm *= $pf if (defined($pf = $Physics::Ballistics::Terminal::Penetrator_Types_H{$pen_typ})); |
|
794
|
31
|
|
|
|
|
60
|
$penetration_depth_mm /= $te; # target material specific adjustment |
|
795
|
31
|
|
|
|
|
66
|
$penetration_depth_mm = int (($penetration_depth_mm * 10) + 0.5) / 10; # this still gives more precision than it deserves |
|
796
|
31
|
|
|
|
|
154
|
return $penetration_depth_mm; |
|
797
|
|
|
|
|
|
|
} |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
our %Penetrator_Types_H = ( |
|
800
|
|
|
|
|
|
|
'hp' => 0.775, # hollowpoint lead with gliding material jacket |
|
801
|
|
|
|
|
|
|
'sp' => 0.850, # softpoint lead with gliding material jacket |
|
802
|
|
|
|
|
|
|
'bp' => 1.050, # ballpoint lead with gliding material jacket |
|
803
|
|
|
|
|
|
|
'ms' => 1.500, # mild steel core AP |
|
804
|
|
|
|
|
|
|
'hs' => 1.800, # hard steel core AP |
|
805
|
|
|
|
|
|
|
'sc' => 1.800, # hard steel core AP |
|
806
|
|
|
|
|
|
|
'wc' => 2.700, # tungsten-carbide core AP (not WHA) |
|
807
|
|
|
|
|
|
|
'tc' => 2.700, # tungsten-carbide core AP (not WHA) |
|
808
|
|
|
|
|
|
|
'wha' => 2.900, # tungsten heavy alloy (WHA) core AP, guesstimate |
|
809
|
|
|
|
|
|
|
'du' => 3.500 # uranium/titanium alloy core AP |
|
810
|
|
|
|
|
|
|
); |
|
811
|
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=head2 pc_simple (mass_grains, velocity_fps, diameter_inches, shape_str) |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
Simple penetration calculator. Attempts to estimate how deeply a small-arms projectile |
|
815
|
|
|
|
|
|
|
will penetrate into RHA. Optimized for projectiles near 7.5mm in diameter, works okay |
|
816
|
|
|
|
|
|
|
for projectiles as small as 5mm or as large as 14mm. |
|
817
|
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
This function is the original work of the author. |
|
819
|
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
ONLY VALID IN BALLISTIC DOMAIN. |
|
821
|
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
Not recommended for masses outside 55..450 grains range, |
|
823
|
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
Not recommended for velocities outside 1200..3500 fps range, |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
Not recommended for unjacketed lead projectiles. |
|
827
|
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=over 4 |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
parameter: (float) penetrator mass (in grains) |
|
831
|
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
parameter: (float) penetrator velocity (in feet per second) |
|
833
|
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
parameter: (float) penetrator diameter (in inches) |
|
835
|
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
parameter: (string) penetrator type, describing very approximately the general shape and composition of the projectile. Valid values are: |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
=over 4 |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
* "hp": Hollowpoint, composed of thin brass lining over lead core. |
|
841
|
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
* "sp": Softpoint (exposed lead tip), composed of thin brass lining over lead core. |
|
843
|
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
* "bp": FMJ "ball", composed of thin brass lining over lead core. |
|
845
|
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
* "ms": Mild steel core, with ogival nose shape. |
|
847
|
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
* "sc": Hard steel core, with truncated-cone nose shape. |
|
849
|
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
* "hc": Synonym for "sc". |
|
851
|
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
* "tc": Tungsten-carbide core (not WHA), with truncated-cone nose shape. |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
* "wc": Synonym for "tc". |
|
855
|
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
* "wha": Tungsten heavy alloy core (eg, 90% W / 7% Ni / 3% Fe), with truncated-cone nose shape. |
|
857
|
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
* "du": Depleted uranium alloy core (99.25% U / 0.75% Ti), with truncated-cone nose shape. |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
The hash table mapping these type strings to their numeric penetration factors is available as %Physics::Ballistics::Terminal::Penetrator_Types_H, for ease of reference and modification. |
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=back |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
parameter: (OPTIONAL) (string or float) thickness efficiency of target material (as ratio to RHA). Defaults to 1.0 (target is RHA). |
|
865
|
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
returns: (float) estimated depth of penetration into RHA (in mm), rounded over to the nearest tenth of a mm. |
|
867
|
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
=back |
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
=cut |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
sub pc_simple { |
|
873
|
5
|
|
|
5
|
1
|
2440
|
my ($grain, $fps, $diam, $typ, $te) = @_; |
|
874
|
5
|
50
|
|
|
|
22
|
die("mm = pc(grains, velocity_fps, diam_inches, {hp,sp,bp,ms,hs,sc,wc,tc,wha,du} [, Te])") unless (defined ($diam)); |
|
875
|
5
|
50
|
|
|
|
12
|
$te = 1 unless (defined ($te)); # thickness efficiency of target material, relative to RHA |
|
876
|
5
|
|
|
|
|
12
|
$fps /= 1000; |
|
877
|
5
|
|
|
|
|
22
|
my $KED = ($grain ** 1.29) * ($fps ** 1.51) / ($diam ** 1.05); # energy density, sorta (fits empirical data) |
|
878
|
5
|
|
|
|
|
10
|
my $pf = undef; |
|
879
|
5
|
50
|
|
|
|
54
|
$KED *= $pf if (defined($pf = $Physics::Ballistics::Terminal::Penetrator_Types_H{$typ})); |
|
880
|
5
|
|
|
|
|
25
|
my $RHA = $KED / 2785; # estimated depth of penetration of RHA, in mm |
|
881
|
5
|
|
|
|
|
9
|
$RHA /= $te; # target material specific adjustment |
|
882
|
5
|
|
|
|
|
13
|
$RHA = int (($RHA * 10) + 0.5) / 10; # this still gives more precision than it deserves |
|
883
|
5
|
|
|
|
|
15
|
return $RHA; |
|
884
|
|
|
|
|
|
|
} |
|
885
|
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
=head2 hits_score (mass_grains, velocity_fps, diameter_inches) |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
Computes a projectile's Hornady Index of Terminal Standards (H.I.T.S.) score, an |
|
890
|
|
|
|
|
|
|
approximation of its lethality. |
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
Personally I think H.I.T.S. severely over-emphasizes bullet mass (the score is |
|
893
|
|
|
|
|
|
|
proportional to the SQUARE of the bullet mass, times velocity, divided by bullet |
|
894
|
|
|
|
|
|
|
sectional area). It is included here anyway because there are no really good |
|
895
|
|
|
|
|
|
|
lethality models, and many big-game hunters like H.I.T.S. (and it is possible |
|
896
|
|
|
|
|
|
|
that bullet mass really is that important when taking down very large animals). |
|
897
|
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
See also: |
|
899
|
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
L |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
L |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
L |
|
905
|
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=over 4 |
|
907
|
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
parameter: (float) projectile mass (in grains) |
|
909
|
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
parameter: (float) projectile velocity (in feet per second) |
|
911
|
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
parameter: (float) projectile diameter (in inches) |
|
913
|
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
returns: (integer) lethality (HITS score, qv table in L) |
|
915
|
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=back |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
=cut |
|
919
|
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
# HITS - Hornady Index of Terminal Standards formula: |
|
921
|
|
|
|
|
|
|
# (Bullet weight grains)^2*(Bullet velocity fps)/(700000*Bullet diameter inches^2) |
|
922
|
|
|
|
|
|
|
sub hits_score { |
|
923
|
1
|
|
|
1
|
1
|
502
|
my ($mass_grains, $vel_fps, $diameter_inches) = @_; |
|
924
|
1
|
50
|
|
|
|
5
|
die("index = hits_score(bullet_grains, bullet_fps, bullet_diameter_inches)") unless (defined($diameter_inches)); |
|
925
|
1
|
|
|
|
|
7
|
return int(($mass_grains**2) * $vel_fps / 700000 / ($diameter_inches**2) + 0.5) |
|
926
|
|
|
|
|
|
|
} |
|
927
|
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
# v = sigma(n1, n2, ...); |
|
930
|
|
|
|
|
|
|
# Returns the standard deviation of its inputs. qv: http://en.wikipedia.org/wiki/Standard_deviation#Identities_and_mathematical_properties |
|
931
|
|
|
|
|
|
|
sub sigma { |
|
932
|
1
|
|
|
1
|
0
|
801
|
my $n = scalar(@_); |
|
933
|
1
|
|
|
|
|
4
|
my $tot = 0; |
|
934
|
1
|
|
|
|
|
2
|
my $sqs = 0; |
|
935
|
1
|
|
|
|
|
2
|
my ($avg, $sig); |
|
936
|
1
|
|
|
|
|
3
|
foreach my $term (@_) { $tot += $term; } |
|
|
4
|
|
|
|
|
8
|
|
|
937
|
1
|
|
|
|
|
3
|
$avg = $tot / $n; |
|
938
|
1
|
|
|
|
|
4
|
foreach my $term (@_) { |
|
939
|
4
|
|
|
|
|
8
|
my $dif = abs($term - $avg); |
|
940
|
4
|
|
|
|
|
10
|
$sqs += $dif**2; |
|
941
|
|
|
|
|
|
|
} |
|
942
|
1
|
|
|
|
|
4
|
$sig = ($sqs / $n)**0.5; |
|
943
|
1
|
|
|
|
|
3
|
return $sig; |
|
944
|
|
|
|
|
|
|
} |
|
945
|
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
# v = average(n1, n2, ...); |
|
947
|
|
|
|
|
|
|
# Returns the simple arithmetic average of its inputs. qv: http://en.wikipedia.org/wiki/Arithmetic_mean |
|
948
|
|
|
|
|
|
|
sub average { |
|
949
|
1
|
|
|
1
|
0
|
521
|
my $n = scalar(@_); |
|
950
|
1
|
50
|
|
|
|
6
|
return 0 if ($n < 1); |
|
951
|
1
|
|
|
|
|
3
|
my $sum = 0; |
|
952
|
1
|
|
|
|
|
4
|
foreach my $x (@_) { $sum += $x; } |
|
|
4
|
|
|
|
|
8
|
|
|
953
|
1
|
|
|
|
|
4
|
return $sum / $n; |
|
954
|
|
|
|
|
|
|
} |
|
955
|
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
# v = rndto(x, n); |
|
957
|
|
|
|
|
|
|
# Round x over to n digits, appending sigfigs to the right of the decimal point as necessary when n < 0. |
|
958
|
|
|
|
|
|
|
# rndto(1234.567, 2) == 1200 |
|
959
|
|
|
|
|
|
|
# rndto(1234.567, 1) == 1230 |
|
960
|
|
|
|
|
|
|
# rndto(1234.567, -1) == 1234.6 |
|
961
|
|
|
|
|
|
|
# rndto(1234.567, -2) == 1234.57 |
|
962
|
|
|
|
|
|
|
# rndto(1234, -2) == 1234.00 |
|
963
|
|
|
|
|
|
|
sub rndto { |
|
964
|
5
|
|
|
5
|
0
|
3269
|
my ($x, $n) = @_; |
|
965
|
5
|
|
|
|
|
9
|
my ($ret); |
|
966
|
5
|
|
|
|
|
23
|
$ret = int(($x / (10**$n)) + 0.5) * (10**$n); |
|
967
|
5
|
100
|
|
|
|
19
|
return $ret unless ($n < 0); |
|
968
|
3
|
|
|
|
|
7
|
$n *= -1; |
|
969
|
3
|
100
|
|
|
|
44
|
return $ret . ("0" x ($n - length($1))) if ($ret =~ /\.(\d+)/); |
|
970
|
1
|
|
|
|
|
9
|
return "$ret." . ("0" x $n); |
|
971
|
|
|
|
|
|
|
} |
|
972
|
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
sub r2d { # Convert radians to degrees |
|
974
|
3
|
|
|
3
|
0
|
1449
|
return 360 * $_[0] / (2 * pi); |
|
975
|
|
|
|
|
|
|
} |
|
976
|
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
sub d2r { # Convert degrees to radians |
|
978
|
3
|
|
|
3
|
0
|
1412
|
return $_[0] * 2 * pi / 360; |
|
979
|
|
|
|
|
|
|
} |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
=head2 poncelet(diameter_mm, mass_grains, velocity_fps, target_shear_strength_psi, target_density) |
|
982
|
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
Jean-Victor Poncelet was one of the first to attempt mathematical models of |
|
984
|
|
|
|
|
|
|
depth of penetration. His formula, developed in the 19th century, attempts |
|
985
|
|
|
|
|
|
|
to predict the penetration of bullets into flesh-like materials. It is not |
|
986
|
|
|
|
|
|
|
very good, failing to take into account such factors as bullet nose shape, |
|
987
|
|
|
|
|
|
|
bullet tumbling within the target, and impacts with bone, horn, or cartilage. |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
ONLY VALID IN BALLISTIC DOMAIN. |
|
990
|
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
=over 4 |
|
992
|
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
parameter: (float) penetrator diameter (in mm) |
|
994
|
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
parameter: (float) penetrator mass (in grains) |
|
996
|
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
parameter: (float) penetrator velocity (in feet per second) |
|
998
|
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
parameter: (float) target material shearing strength (in PSI) |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
parameter: (float) target density (in g/cc) |
|
1002
|
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
returns: (int) depth of penetration (in mm) |
|
1004
|
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
=back |
|
1006
|
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
=cut |
|
1008
|
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
# Old, not very useful formula by Poncelet for predicting depth of penetration into flesh. |
|
1010
|
|
|
|
|
|
|
sub poncelet { |
|
1011
|
1
|
|
|
1
|
1
|
498
|
my ($cal, $mass, $vel, $c0, $c1, $debug) = @_; |
|
1012
|
1
|
50
|
|
|
|
5
|
die('usage: ponce (cal_mm, mass_grain, vel_fps, targ_shear_psi, targ_density) = pen_cm') unless(defined($c1)); |
|
1013
|
|
|
|
|
|
|
# c0 = Shearing strength |
|
1014
|
|
|
|
|
|
|
# c1 = Specific density (water = 1 = 1 g/cc) |
|
1015
|
1
|
|
|
|
|
4
|
$mass /= 15.43; # converting grains to grams |
|
1016
|
1
|
|
|
|
|
3
|
$vel /= 3.28; # converting ft/s to m/s |
|
1017
|
1
|
|
|
|
|
4
|
$c0 /= 145.04; # converting psi to MPa |
|
1018
|
1
|
50
|
|
|
|
5
|
if ($debug) { |
|
1019
|
0
|
|
|
|
|
0
|
print "# poncelet: mass g = $mass\n"; |
|
1020
|
0
|
|
|
|
|
0
|
print "# poncelet: vel m/s = $vel\n"; |
|
1021
|
0
|
|
|
|
|
0
|
print "# poncelet: shr MPa = $c0\n"; |
|
1022
|
|
|
|
|
|
|
} |
|
1023
|
1
|
|
|
|
|
3
|
my $term1_1 = 2 * 3.141592 * $c1; |
|
1024
|
1
|
|
|
|
|
3
|
my $term1_2 = $cal**2 / 4; |
|
1025
|
1
|
|
|
|
|
4
|
my $term1 = $mass / ($term1_1 * $term1_2); |
|
1026
|
1
|
|
|
|
|
5
|
my $term2_1 = ($c1 * $vel**2 + $c0) / $c0; |
|
1027
|
1
|
|
|
|
|
5
|
my $term2 = log($term2_1); |
|
1028
|
1
|
|
|
|
|
3
|
my $depth_cm = $term1 * $term2; |
|
1029
|
|
|
|
|
|
|
# my $depth_cm = ($mass / (2 * $c1 * 3.141592 * $cal**2 / 4)) * log(($c1 * $vel**2 + $c0) / $c0); |
|
1030
|
1
|
50
|
|
|
|
4
|
if ($debug) { |
|
1031
|
0
|
|
|
|
|
0
|
print "# poncelet: term1_1 = 2 * 3.141592 * den $c1 = $term1_1\n"; |
|
1032
|
0
|
|
|
|
|
0
|
print "# poncelet: term1_2 = cal^2 $cal**2 / 4 = $term1_2\n"; |
|
1033
|
0
|
|
|
|
|
0
|
print "# poncelet: term1 = mass g $mass / (term1_1 * term1_2) = $term1\n"; |
|
1034
|
0
|
|
|
|
|
0
|
print "# poncelet: term2_1 = den $c1 * vel^2 $vel**2 + shear $c0) / shear $c0 = $term2_1\n"; |
|
1035
|
0
|
|
|
|
|
0
|
print "# poncelet: term2 = log(term2_1) = $term2\n"; |
|
1036
|
0
|
|
|
|
|
0
|
print "# poncelet: depth_cm = term1 * term2 = $depth_cm\n"; |
|
1037
|
|
|
|
|
|
|
} |
|
1038
|
1
|
|
|
|
|
8
|
return int($depth_cm * 10 + 0.5); # converting cm to nearest mm, which is still way more precision than this deserves. |
|
1039
|
|
|
|
|
|
|
} |
|
1040
|
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
=head2 te2me (thickness_efficiency, density) |
|
1042
|
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
Given the mass efficiency of a material, returns its thickness efficiency. |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
See the description of me2te() for more explanation. |
|
1046
|
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
=over 4 |
|
1048
|
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
parameter: (float) armor material thickness efficiency (unitless, factor relative to RHA) |
|
1050
|
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
parameter: (float) armor material density (g/cc) |
|
1052
|
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
returns: (float) armor material mass efficiency (unitless, factor relative to RHA) |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
=back |
|
1056
|
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
=cut |
|
1058
|
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
sub te2me { # given thickness efficiency and density, returns mass efficiency |
|
1060
|
1
|
|
|
1
|
1
|
6
|
my ($te, $den) = @_; |
|
1061
|
1
|
|
|
|
|
8
|
return $te * 7.86 / $den; |
|
1062
|
|
|
|
|
|
|
} |
|
1063
|
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
=head2 lethality (grains, velocity_fps) |
|
1065
|
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
Approximates the lethality of a projectile impacting a living creature. |
|
1067
|
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
C and currently extremely simple. |
|
1069
|
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
Its parameters and output are likely to change in incompatible ways in future releases. |
|
1071
|
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
Note the caveats enumerated at L |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
This function assumes nontrivial tissue penetration occurs. For the moment it is based on observations of a very rough correlation between velocity and mass and permanent tissue cavity volume. |
|
1075
|
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
See also Fackler: L |
|
1077
|
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
=over 4 |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
parameter: (integer) projectile weight (in grains) |
|
1081
|
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
parameter: (integer) projectile velocity (in feet/second) |
|
1083
|
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
returns: (float) lethality relative to 5.56x45mm at point blank range. |
|
1085
|
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
=back |
|
1087
|
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
=cut |
|
1089
|
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
sub lethality { # given grains and fps, estimate lethality relative to 5.56x45mm by momentum method (simplest). |
|
1091
|
|
|
|
|
|
|
# TODO: improve on this to take length, width, tumble rate, and fragmentation into effect (permanent cavity volume method). |
|
1092
|
2
|
|
|
2
|
1
|
979
|
my ($grains, $fps) = @_; |
|
1093
|
2
|
50
|
33
|
|
|
16
|
die("m = lethality(grains, feet_per_second)") unless(defined($grains) && defined($fps)); |
|
1094
|
2
|
|
|
|
|
5
|
my $baseline_momentum = 63 * 3100; |
|
1095
|
2
|
|
|
|
|
5
|
my $posed_momentum = $grains * $fps; |
|
1096
|
2
|
|
|
|
|
5
|
my $relative_momentum = $posed_momentum / $baseline_momentum; |
|
1097
|
2
|
|
|
|
|
14
|
return int($relative_momentum * 100 + 0.5) / 100; |
|
1098
|
|
|
|
|
|
|
} |
|
1099
|
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
=head2 hv2bhn (hardness_vickers) |
|
1101
|
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
Given a Vickers hardness rating, approximates the equivalent Brinell Hardness Number (via 10/3000 WC method). |
|
1103
|
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
Vickers can be converted to other hardness ratings by first converting to BHN, and then converting from BHN to the desired hardness rating. |
|
1105
|
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
=over 4 |
|
1107
|
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
parameter: (integer) Vickers Hardness rating |
|
1109
|
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
returns: (float) Brinell Hardness Number (BHN) |
|
1111
|
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=back |
|
1113
|
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
=cut |
|
1115
|
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
sub hv2bhn { # very approximately converts hardness vickers to brinell hardness number (10/3000 WC method) |
|
1117
|
3
|
|
|
3
|
1
|
1389
|
my ($hv) = @_; |
|
1118
|
3
|
50
|
|
|
|
22
|
return undef if ($hv !~ /^(-?[0-9\.]+)/); |
|
1119
|
3
|
|
|
|
|
10
|
$hv = $1; |
|
1120
|
3
|
100
|
|
|
|
15
|
return ($hv * 0.92857) if ($hv < 701); |
|
1121
|
2
|
50
|
|
|
|
8
|
return ($hv * 0.70588 + 156) if ($hv < 826); |
|
1122
|
2
|
50
|
|
|
|
6
|
return ($hv * 0.56770 + 270) if ($hv < 851); |
|
1123
|
2
|
100
|
|
|
|
12
|
return ($hv * 0.34417 + 460) if ($hv < 1001); |
|
1124
|
1
|
50
|
|
|
|
5
|
return ($hv * 0.17210 + 632) if ($hv < 1201); |
|
1125
|
1
|
|
|
|
|
6
|
return ($hv * 0.08605 + 735); |
|
1126
|
|
|
|
|
|
|
} |
|
1127
|
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
=head2 bhn2hv (brinell_hardness_number) |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
Given a Brinell Hardness Number hardness rating (via 10/3000 WC method), approximates the equivalent Vickers Hardness rating. |
|
1131
|
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
=over 4 |
|
1133
|
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
parameter: (integer) Brinell Hardness Number (BHN) |
|
1135
|
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
returns: (float) Vickers Hardness rating |
|
1137
|
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=back |
|
1139
|
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
=cut |
|
1141
|
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
sub bhn2hv { # very approximately converts brinell hardness number (10/3000 WC method) to hardness vickers |
|
1143
|
3
|
|
|
3
|
1
|
1408
|
my ($bhn) = @_; |
|
1144
|
3
|
50
|
|
|
|
19
|
return undef if ($bhn !~ /^(-?[0-9\.]+)/); |
|
1145
|
3
|
|
|
|
|
8
|
$bhn = $1; |
|
1146
|
3
|
100
|
|
|
|
16
|
return (($bhn - 735) / 0.08605) if ($bhn > 838); |
|
1147
|
2
|
50
|
|
|
|
7
|
return (($bhn - 632) / 0.17210) if ($bhn > 804); |
|
1148
|
2
|
100
|
|
|
|
16
|
return (($bhn - 460) / 0.34417) if ($bhn > 752); |
|
1149
|
1
|
50
|
|
|
|
11
|
return (($bhn - 270) / 0.56770) if ($bhn > 738); |
|
1150
|
1
|
50
|
|
|
|
3
|
return (($bhn - 156) / 0.70588) if ($bhn > 650); |
|
1151
|
1
|
|
|
|
|
6
|
return ($bhn / 0.92857); |
|
1152
|
|
|
|
|
|
|
} |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=head2 hrc2bhn (rockwell_hardness_C) |
|
1155
|
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
Given a Rockwell Hardness C rating, approximates the equivalent Brinell Hardness Number (via 10/3000 WC method). |
|
1157
|
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
HRC can be converted to other hardness ratings by first converting to BHN, and then converting from BHN to the desired hardness rating. |
|
1159
|
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
=over 4 |
|
1161
|
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
parameter: (integer) Rockwell Hardness C, valid ONLY in the range 15..65. |
|
1163
|
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
returns: (float) Brinell Hardness Number (BHN) |
|
1165
|
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
=back |
|
1167
|
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
=cut |
|
1169
|
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
sub hrc2bhn { # very approximately converts rockwell hardness C to BHN (10/3000 WC) |
|
1171
|
|
|
|
|
|
|
# zzapp -- FIXME: Segment this curve to improve accuracy |
|
1172
|
|
|
|
|
|
|
# actual calculated absolute |
|
1173
|
|
|
|
|
|
|
# HRC BHN BHN error |
|
1174
|
|
|
|
|
|
|
# 20 228 228.833 0.833 |
|
1175
|
|
|
|
|
|
|
# 30 286 288.475 2.475 |
|
1176
|
|
|
|
|
|
|
# 40 371 366.717 -4.283 |
|
1177
|
|
|
|
|
|
|
# 50 482 482.458 0.458 |
|
1178
|
|
|
|
|
|
|
# 60 657 654.6 -2.400 |
|
1179
|
5
|
|
|
5
|
1
|
1914
|
my ($hrc) = @_; |
|
1180
|
5
|
100
|
|
|
|
21
|
return undef if ($hrc > 65); # error condition -- invalid range |
|
1181
|
4
|
100
|
|
|
|
15
|
return undef if ($hrc < 15); # error condition -- invalid range |
|
1182
|
3
|
|
|
|
|
15
|
my $bhn = 89.75 + (28.5125 * $hrc / 3) - (0.1905 * ($hrc**2)) + (0.00315 * ($hrc**3)); |
|
1183
|
3
|
|
|
|
|
15
|
return int(0.5 + $bhn); # eliminating illusion of accuracy |
|
1184
|
|
|
|
|
|
|
} |
|
1185
|
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
=head2 bhn2hrc (brinell_hardness_number) |
|
1187
|
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
Given a Brinell Hardness Number hardness rating (via 10/3000 WC method), approximates the equivalent Rockwell Hardness C rating. |
|
1189
|
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
Approximation is accurate to within 5% near the low end, 2% everywhere else. |
|
1191
|
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
=over 4 |
|
1193
|
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
parameter: (integer) Brinell Hardness Number (BHN), valid ONLY in the range 200..770 |
|
1195
|
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
returns: (float) Rockwell Hardness C rating |
|
1197
|
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
=back |
|
1199
|
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
=cut |
|
1201
|
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
sub bhn2hrc { # very approximately converts BHN (10/3000 WC) to rockwell hardness C |
|
1203
|
|
|
|
|
|
|
# reasonably pleased with the accuracy of this -- error is up to 5% near the low end, but less than 2% otherwise. |
|
1204
|
5
|
|
|
5
|
1
|
1458
|
my ($bhn) = @_; |
|
1205
|
5
|
100
|
|
|
|
20
|
return undef if ($bhn < 200); # out of bounds |
|
1206
|
4
|
100
|
|
|
|
14
|
return undef if ($bhn > 770); # out of bounds |
|
1207
|
3
|
|
|
|
|
18
|
my $hrc = -3 + ($bhn / 14) + ($bhn / 74)**2 - ($bhn / 168)**3; |
|
1208
|
3
|
50
|
|
|
|
10
|
$hrc -= 1 if ($bhn <= 215); |
|
1209
|
3
|
50
|
66
|
|
|
13
|
$hrc += 2 if ($bhn <= 436 && $bhn >= 254); |
|
1210
|
3
|
50
|
66
|
|
|
12
|
$hrc += 1 if ($bhn <= 402 && $bhn >= 279); |
|
1211
|
3
|
100
|
66
|
|
|
17
|
$hrc -= 2 if ($bhn <= 710 && $bhn >= 553); |
|
1212
|
3
|
|
|
|
|
13
|
return int($hrc); |
|
1213
|
|
|
|
|
|
|
} |
|
1214
|
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
=head2 psi2bhn (pounds_per_square_inch) |
|
1216
|
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
Given the ultimate tensile strength of a steel formulation in PSI, approximates the equivalent Brinell Hardness Number (via 10/3000 WC method). |
|
1218
|
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
Steel UTS PSI can be converted to other hardness ratings by first converting to BHN, and then converting from BHN to the desired hardness rating. |
|
1220
|
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
Approximation is accurate to within 2%. |
|
1222
|
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
See also: |
|
1224
|
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
L |
|
1226
|
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
L |
|
1228
|
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
=over 4 |
|
1230
|
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
parameter: (integer) Pounds per square inch |
|
1232
|
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
returns: (float) Brinell Hardness Number (BHN) |
|
1234
|
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
=back |
|
1236
|
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
=cut |
|
1238
|
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
sub psi2bhn { # very approximately converts steel uts psi to brinell hardness number |
|
1240
|
|
|
|
|
|
|
# source: http://www.monachos.gr/en/resources/hardness_conversion.asp |
|
1241
|
|
|
|
|
|
|
# qv alt: http://mdmetric.com/tech/hardness.htm |
|
1242
|
|
|
|
|
|
|
# this table provides approx 2% error in conversion |
|
1243
|
3
|
|
|
3
|
1
|
972
|
my ($psi) = @_; |
|
1244
|
3
|
50
|
|
|
|
27
|
return undef unless ($psi =~ /^(-?[0-9\.]+)/); |
|
1245
|
3
|
|
|
|
|
11
|
$psi = $1; |
|
1246
|
3
|
|
|
|
|
8
|
$psi /= 1000; |
|
1247
|
3
|
100
|
|
|
|
14
|
return ($psi / 0.500) if ($psi < 127); |
|
1248
|
2
|
50
|
|
|
|
7
|
return ($psi / 0.497) if ($psi < 140); |
|
1249
|
2
|
50
|
|
|
|
6
|
return ($psi / 0.487) if ($psi < 153); |
|
1250
|
2
|
50
|
|
|
|
5
|
return ($psi / 0.485) if ($psi < 166); |
|
1251
|
2
|
50
|
|
|
|
7
|
return ($psi / 0.486) if ($psi < 179); |
|
1252
|
2
|
50
|
|
|
|
6
|
return ($psi / 0.484) if ($psi < 192); |
|
1253
|
2
|
50
|
|
|
|
6
|
return ($psi / 0.483) if ($psi < 205); |
|
1254
|
2
|
50
|
|
|
|
6
|
return ($psi / 0.484) if ($psi < 218); |
|
1255
|
2
|
100
|
|
|
|
10
|
return ($psi / 0.489) if ($psi < 231); |
|
1256
|
1
|
50
|
|
|
|
5
|
return ($psi / 0.493) if ($psi < 257); |
|
1257
|
1
|
50
|
|
|
|
3
|
return ($psi / 0.494) if ($psi < 270); |
|
1258
|
1
|
50
|
|
|
|
17
|
return ($psi / 0.495) if ($psi < 283); |
|
1259
|
1
|
50
|
|
|
|
5
|
return ($psi / 0.497) if ($psi < 296); |
|
1260
|
1
|
50
|
|
|
|
3
|
return ($psi / 0.498) if ($psi < 322); |
|
1261
|
1
|
50
|
|
|
|
5
|
return ($psi / 0.499) if ($psi < 335); |
|
1262
|
1
|
50
|
|
|
|
3
|
return ($psi / 0.500) if ($psi < 348); |
|
1263
|
1
|
50
|
|
|
|
5
|
return ($psi / 0.501) if ($psi < 374); |
|
1264
|
1
|
50
|
|
|
|
9
|
return ($psi / 0.503) if ($psi < 387); |
|
1265
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.504) if ($psi < 400); |
|
1266
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.506) if ($psi < 426); |
|
1267
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.507) if ($psi < 439); |
|
1268
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.510) if ($psi < 452); |
|
1269
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.509) if ($psi < 478); |
|
1270
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.511) if ($psi < 491); |
|
1271
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.512) if ($psi < 504); |
|
1272
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.513) if ($psi < 530); |
|
1273
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.514) if ($psi < 595); |
|
1274
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.515) if ($psi < 621); |
|
1275
|
0
|
0
|
|
|
|
0
|
return ($psi / 0.516) if ($psi < 634); |
|
1276
|
0
|
|
|
|
|
0
|
return ($psi / 0.517); |
|
1277
|
|
|
|
|
|
|
} |
|
1278
|
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
=head2 bhn2psi (brinell_hardness_number) |
|
1280
|
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
Given a Brinell Hardness Number hardness rating (via 10/3000 WC method), approximates the equivalent steel ultimate tensile strength in pounds per square inch. |
|
1282
|
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
Approximation is accurate to within 2%. |
|
1284
|
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
See also: |
|
1286
|
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
L |
|
1288
|
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
L |
|
1290
|
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
=over 4 |
|
1292
|
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
parameter: (integer) Brinell Hardness Number (BHN) |
|
1294
|
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
returns: (float) Steel ultimate tensile strength (psi) |
|
1296
|
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
=back |
|
1298
|
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
=cut |
|
1300
|
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
sub bhn2psi { # very approximately converts brinell hardness number to steel uts psi |
|
1302
|
|
|
|
|
|
|
# source: http://www.monachos.gr/en/resources/hardness_conversion.asp |
|
1303
|
|
|
|
|
|
|
# qv alt: http://mdmetric.com/tech/hardness.htm |
|
1304
|
|
|
|
|
|
|
# this table provides 2% or less error in conversion |
|
1305
|
3
|
|
|
3
|
1
|
1444
|
my ($bhn) = @_; |
|
1306
|
3
|
50
|
|
|
|
21
|
return undef unless ($bhn =~ /^(-?[0-9\.]+)/); |
|
1307
|
3
|
|
|
|
|
7
|
$bhn = $1; |
|
1308
|
3
|
100
|
|
|
|
17
|
return ($bhn * 500) if ($bhn < 127); |
|
1309
|
2
|
50
|
|
|
|
6
|
return ($bhn * 496) if ($bhn < 131); |
|
1310
|
2
|
50
|
|
|
|
8
|
return ($bhn * 489) if ($bhn < 138); |
|
1311
|
2
|
50
|
|
|
|
11
|
return ($bhn * 497) if ($bhn < 144); |
|
1312
|
2
|
50
|
|
|
|
5
|
return ($bhn * 490) if ($bhn < 150); |
|
1313
|
2
|
50
|
|
|
|
6
|
return ($bhn * 487) if ($bhn < 157); |
|
1314
|
2
|
50
|
|
|
|
6
|
return ($bhn * 485) if ($bhn < 168); |
|
1315
|
2
|
50
|
|
|
|
5
|
return ($bhn * 488) if ($bhn < 171); |
|
1316
|
2
|
50
|
|
|
|
5
|
return ($bhn * 489) if ($bhn < 175); |
|
1317
|
2
|
50
|
|
|
|
10
|
return ($bhn * 486) if ($bhn < 184); |
|
1318
|
2
|
50
|
|
|
|
6
|
return ($bhn * 481) if ($bhn < 188); |
|
1319
|
2
|
50
|
|
|
|
6
|
return ($bhn * 484) if ($bhn < 193); |
|
1320
|
2
|
50
|
|
|
|
6
|
return ($bhn * 482) if ($bhn < 198); |
|
1321
|
2
|
50
|
|
|
|
6
|
return ($bhn * 488) if ($bhn < 202); |
|
1322
|
2
|
50
|
|
|
|
6
|
return ($bhn * 483) if ($bhn < 208); |
|
1323
|
2
|
50
|
|
|
|
6
|
return ($bhn * 481) if ($bhn < 213); |
|
1324
|
2
|
50
|
|
|
|
4
|
return ($bhn * 484) if ($bhn < 218); |
|
1325
|
2
|
50
|
|
|
|
6
|
return ($bhn * 485) if ($bhn < 230); |
|
1326
|
2
|
50
|
|
|
|
5
|
return ($bhn * 489) if ($bhn < 236); |
|
1327
|
2
|
50
|
|
|
|
9
|
return ($bhn * 490) if ($bhn < 242); |
|
1328
|
2
|
50
|
|
|
|
5
|
return ($bhn * 492) if ($bhn < 249); |
|
1329
|
2
|
50
|
|
|
|
8
|
return ($bhn * 494) if ($bhn < 256); |
|
1330
|
2
|
50
|
|
|
|
6
|
return ($bhn * 492) if ($bhn < 263); |
|
1331
|
2
|
50
|
|
|
|
8
|
return ($bhn * 494) if ($bhn < 270); |
|
1332
|
2
|
50
|
|
|
|
6
|
return ($bhn * 495) if ($bhn < 294); |
|
1333
|
2
|
50
|
|
|
|
5
|
return ($bhn * 497) if ($bhn < 303); |
|
1334
|
2
|
50
|
|
|
|
5
|
return ($bhn * 498) if ($bhn < 322); |
|
1335
|
2
|
50
|
|
|
|
6
|
return ($bhn * 501) if ($bhn < 332); |
|
1336
|
2
|
50
|
|
|
|
5
|
return ($bhn * 499) if ($bhn < 342); |
|
1337
|
2
|
100
|
|
|
|
9
|
return ($bhn * 500) if ($bhn < 353); |
|
1338
|
1
|
50
|
|
|
|
9
|
return ($bhn * 501) if ($bhn < 376); |
|
1339
|
1
|
50
|
|
|
|
15
|
return ($bhn * 503) if ($bhn < 389); |
|
1340
|
1
|
50
|
|
|
|
4
|
return ($bhn * 504) if ($bhn < 402); |
|
1341
|
1
|
50
|
|
|
|
4
|
return ($bhn * 506) if ($bhn < 430); |
|
1342
|
1
|
50
|
|
|
|
4
|
return ($bhn * 507) if ($bhn < 445); |
|
1343
|
1
|
50
|
|
|
|
4
|
return ($bhn * 510) if ($bhn < 462); |
|
1344
|
1
|
50
|
|
|
|
3
|
return ($bhn * 509) if ($bhn < 478); |
|
1345
|
1
|
50
|
|
|
|
3
|
return ($bhn * 511) if ($bhn < 496); |
|
1346
|
1
|
50
|
|
|
|
4
|
return ($bhn * 512) if ($bhn < 515); |
|
1347
|
1
|
50
|
|
|
|
5
|
return ($bhn * 513) if ($bhn < 535); |
|
1348
|
1
|
50
|
|
|
|
3
|
return ($bhn * 514) if ($bhn < 602); |
|
1349
|
1
|
50
|
|
|
|
4
|
return ($bhn * 515) if ($bhn < 628); |
|
1350
|
1
|
50
|
|
|
|
4
|
return ($bhn * 514) if ($bhn < 631); |
|
1351
|
1
|
50
|
|
|
|
8
|
return ($bhn * 516) if ($bhn < 639); |
|
1352
|
1
|
|
|
|
|
4
|
return ($bhn * 517); |
|
1353
|
|
|
|
|
|
|
} |
|
1354
|
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
1; |
|
1356
|
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
=head1 TODO |
|
1358
|
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
The pc function needs a lot of improvement. |
|
1360
|
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
Need a pc function for larger penetrators (for the ballistic domain, as anderson and odermatt suffices for hypervelocity domain). |
|
1362
|
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
The stabilization_distance_meters function should take projectile composition into account. |
|
1364
|
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
To be really useful the lethality function needs to take wobble, fragmentation and permanent wound cavity volume into account (per Fackler). |
|
1366
|
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
The hardness unit conversion functions should be based on Vickers, not Brinell, as Vickers has the wider valid range. |
|
1368
|
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
=cut |