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 |