Skip to content

Commit a9607ef

Browse files
authored
Fix handling of SPH arrays and database changes between versions (#88)
* fix: Correctly read SPH data Reshapes complete SPH data array to allow for correct indexing. To deal with old and new database versions, which may or may not include strain rate, flags for strain and strain rate were separated, as `isphfg(9)` can be 6 or 12. * fix: Handle inconsistant SPH header between versions There was an undocumented DB change between old and new versions where isphfg(1) can be 10 or 11. Data flag handling was modified to handle this behaviour.
1 parent 7aa82fd commit a9607ef

File tree

1 file changed

+42
-35
lines changed

1 file changed

+42
-35
lines changed

src/lasso/dyna/d3plot.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,8 @@ class SphSectionInfo:
12851285
has_material_density: bool = False
12861286
has_internal_energy: bool = False
12871287
has_n_affecting_neighbors: bool = False
1288-
has_strain_and_strainrate: bool = False
1288+
has_strain: bool = False
1289+
has_strainrate: bool = False
12891290
has_true_strains: bool = False
12901291
has_mass: bool = False
12911292
n_sph_history_vars: int = 0
@@ -2157,7 +2158,15 @@ def _read_fluid_material_data(self):
21572158
LOGGER.debug("_read_fluid_material_data end at byte %d", self.geometry_section_size)
21582159

21592160
def _read_sph_element_data_flags(self):
2160-
"""Read the sph element data flags"""
2161+
"""Read the sph element data flags
2162+
2163+
The LS-DYNA database has some undocumented behaviour between older and newer
2164+
versions that impact how SPH header data is handled. The manual idnicates that
2165+
isphfg(1) should always be 11. However, in versions of LS-DYNA newer than R9,
2166+
isphfg(1) can be either 10 or 11 as history variables are handled differently.
2167+
Special handling was needed to ensure that old behaviour broken while handling
2168+
this undocumented change.
2169+
"""
21612170

21622171
if not self._buffer:
21632172
return
@@ -2193,17 +2202,16 @@ def _read_sph_element_data_flags(self):
21932202
self._sph_info.has_material_density = sph_header_data["isphfg6"] != 0
21942203
self._sph_info.has_internal_energy = sph_header_data["isphfg7"] != 0
21952204
self._sph_info.has_n_affecting_neighbors = sph_header_data["isphfg8"] != 0
2196-
self._sph_info.has_strain_and_strainrate = sph_header_data["isphfg9"] != 0
2205+
self._sph_info.has_strain = sph_header_data["isphfg9"] != 0
2206+
self._sph_info.has_strainrate = sph_header_data["isphfg9"] > 6
21972207
self._sph_info.has_true_strains = sph_header_data["isphfg9"] < 0
21982208
self._sph_info.has_mass = sph_header_data["isphfg10"] != 0
2199-
self._sph_info.n_sph_history_vars = sph_header_data["isphfg11"]
2200-
2201-
if self._sph_info.n_sph_array_length != 11:
2202-
msg = (
2203-
"Detected inconsistency: "
2204-
f"isphfg = {self._sph_info.n_sph_array_length} but must be 11."
2205-
)
2206-
raise RuntimeError(msg)
2209+
# If isphfg1 = 10, then there are no history variables by default and isphfg11
2210+
# is filled with junk data that causes issues calculating n_sph_vars below
2211+
if sph_header_data["isphfg1"] == 10:
2212+
self._sph_info.n_sph_history_vars = 0
2213+
else:
2214+
self._sph_info.n_sph_history_vars = sph_header_data["isphfg11"]
22072215

22082216
self._sph_info.n_sph_vars = (
22092217
sph_header_data["isphfg2"]
@@ -2215,7 +2223,7 @@ def _read_sph_element_data_flags(self):
22152223
+ sph_header_data["isphfg8"]
22162224
+ abs(sph_header_data["isphfg9"])
22172225
+ sph_header_data["isphfg10"]
2218-
+ sph_header_data["isphfg11"]
2226+
+ self._sph_info.n_sph_history_vars
22192227
+ 1
22202228
) # material number
22212229

@@ -5082,13 +5090,17 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
50825090

50835091
# extract data
50845092
try:
5085-
sph_data = state_data[:, var_index : var_index + n_particles * n_variables]
5093+
sph_data = state_data[:, var_index : var_index + n_particles * n_variables].reshape((
5094+
n_states,
5095+
n_particles,
5096+
n_variables,
5097+
))
50865098

50875099
i_var = 1
50885100

50895101
# deletion
50905102
try:
5091-
array_dict[ArrayType.sph_deletion] = sph_data[:, 0] < 0
5103+
array_dict[ArrayType.sph_deletion] = sph_data[:, :, 0] < 0
50925104
except Exception:
50935105
trb_msg = traceback.format_exc()
50945106
msg = "A failure in %s was caught:\n%s"
@@ -5097,7 +5109,7 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
50975109
# particle radius
50985110
if info.has_influence_radius:
50995111
try:
5100-
array_dict[ArrayType.sph_radius] = sph_data[:, i_var]
5112+
array_dict[ArrayType.sph_radius] = sph_data[:, :, i_var]
51015113
except Exception:
51025114
trb_msg = traceback.format_exc()
51035115
msg = "A failure in %s was caught:\n%s"
@@ -5108,7 +5120,7 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
51085120
# pressure
51095121
if info.has_particle_pressure:
51105122
try:
5111-
array_dict[ArrayType.sph_pressure] = sph_data[:, i_var]
5123+
array_dict[ArrayType.sph_pressure] = sph_data[:, :, i_var]
51125124
except Exception:
51135125
trb_msg = traceback.format_exc()
51145126
msg = "A failure in %s was caught:\n%s"
@@ -5119,20 +5131,18 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
51195131
# stress
51205132
if info.has_stresses:
51215133
try:
5122-
array_dict[ArrayType.sph_stress] = sph_data[
5123-
:, i_var : i_var + n_particles * 6
5124-
].reshape((n_states, n_particles, 6))
5134+
array_dict[ArrayType.sph_stress] = sph_data[:, :, i_var : i_var + 6]
51255135
except Exception:
51265136
trb_msg = traceback.format_exc()
51275137
msg = "A failure in %s was caught:\n%s"
51285138
LOGGER.warning(msg, "_read_states_sph, pressure", trb_msg)
51295139
finally:
5130-
i_var += 6 * n_particles
5140+
i_var += 6
51315141

51325142
# eff. plastic strain
51335143
if info.has_plastic_strain:
51345144
try:
5135-
array_dict[ArrayType.sph_effective_plastic_strain] = sph_data[:, i_var]
5145+
array_dict[ArrayType.sph_effective_plastic_strain] = sph_data[:, :, i_var]
51365146
except Exception:
51375147
trb_msg = traceback.format_exc()
51385148
msg = "A failure in %s was caught:\n%s"
@@ -5143,7 +5153,7 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
51435153
# density
51445154
if info.has_material_density:
51455155
try:
5146-
array_dict[ArrayType.sph_density] = sph_data[:, i_var]
5156+
array_dict[ArrayType.sph_density] = sph_data[:, :, i_var]
51475157
except Exception:
51485158
trb_msg = traceback.format_exc()
51495159
msg = "A failure in %s was caught:\n%s"
@@ -5154,7 +5164,7 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
51545164
# internal energy
51555165
if info.has_internal_energy:
51565166
try:
5157-
array_dict[ArrayType.sph_internal_energy] = sph_data[:, i_var]
5167+
array_dict[ArrayType.sph_internal_energy] = sph_data[:, :, i_var]
51585168
except Exception:
51595169
trb_msg = traceback.format_exc()
51605170
msg = "A failure in %s was caught:\n%s"
@@ -5165,42 +5175,39 @@ def _read_states_sph(self, state_data: np.ndarray, var_index: int, array_dict: d
51655175
# number of neighbors
51665176
if info.has_n_affecting_neighbors:
51675177
try:
5168-
array_dict[ArrayType.sph_n_neighbors] = sph_data[:, i_var]
5178+
array_dict[ArrayType.sph_n_neighbors] = sph_data[:, :, i_var]
51695179
except Exception:
51705180
trb_msg = traceback.format_exc()
51715181
msg = "A failure in %s was caught:\n%s"
51725182
LOGGER.warning(msg, "_read_states_sph, n_neighbors", trb_msg)
51735183
finally:
51745184
i_var += 1
51755185

5176-
# strain and strainrate
5177-
if info.has_strain_and_strainrate:
5186+
# strain
5187+
if info.has_strain:
51785188
try:
5179-
array_dict[ArrayType.sph_strain] = sph_data[
5180-
:, i_var : i_var + n_particles * 6
5181-
].reshape((n_states, n_particles, 6))
5189+
array_dict[ArrayType.sph_strain] = sph_data[:, :, i_var : i_var + 6]
51825190
except Exception:
51835191
trb_msg = traceback.format_exc()
51845192
msg = "A failure in %s was caught:\n%s"
51855193
LOGGER.warning(msg, "_read_states_sph, strain", trb_msg)
51865194
finally:
5187-
i_var += 6 * n_particles
5195+
i_var += 6
51885196

5197+
if info.has_strainrate:
51895198
try:
5190-
array_dict[ArrayType.sph_strainrate] = sph_data[
5191-
:, i_var : i_var + n_particles * 6
5192-
].reshape((n_states, n_particles, 6))
5199+
array_dict[ArrayType.sph_strainrate] = sph_data[:, :, i_var : i_var + 6]
51935200
except Exception:
51945201
trb_msg = traceback.format_exc()
51955202
msg = "A failure in %s was caught:\n%s"
51965203
LOGGER.warning(msg, "_read_states_sph, strainrate", trb_msg)
51975204
finally:
5198-
i_var += 6 * n_particles
5205+
i_var += 6
51995206

52005207
# mass
52015208
if info.has_mass:
52025209
try:
5203-
array_dict[ArrayType.sph_mass] = sph_data[:, i_var]
5210+
array_dict[ArrayType.sph_mass] = sph_data[:, :, i_var]
52045211
except Exception:
52055212
trb_msg = traceback.format_exc()
52065213
msg = "A failure in %s was caught:\n%s"

0 commit comments

Comments
 (0)