@@ -224,25 +224,26 @@ def extract_shell_facets(shells: pd.DataFrame, mapping):
224
224
"""
225
225
226
226
if len (shells ) == 0 :
227
- return []
228
-
229
- # extract only the node information
230
- # could keep in the future to separate the parts or elements
231
- shells = shells .drop (columns = ["eid" , "pid" ])
227
+ return np .empty ((0 ), dtype = int ), np .empty ((0 ), dtype = int ), np .empty ((0 ), dtype = int )
232
228
229
+ # extract the node information, element_ids and part_ids
233
230
facet_with_prefix = []
231
+ eid = []
232
+ pid = []
234
233
235
234
idx = 0
236
235
for row in shells .itertuples (index = False ):
237
- array = shell_facet_array (row )
236
+ array = shell_facet_array (row [ 2 :] )
238
237
facet_with_prefix .append (array )
238
+ eid .append (row [0 ])
239
+ pid .append (row [1 ])
239
240
idx += 1
240
241
242
+ # Convert list to np.ndarray
241
243
flat_facets = np .concatenate (facet_with_prefix , axis = 0 )
242
-
243
244
flat_facets_indexed = map_facet_nid_to_index (flat_facets , mapping )
244
245
245
- return flat_facets_indexed
246
+ return flat_facets_indexed , np . array ( eid ), np . array ( pid )
246
247
247
248
248
249
def extract_lines (beams : pd .DataFrame , mapping : typing .Dict [int , int ]) -> np .ndarray :
@@ -264,43 +265,63 @@ def extract_lines(beams: pd.DataFrame, mapping: typing.Dict[int, int]) -> np.nda
264
265
"""
265
266
# dont need to do this if there is no beams
266
267
if len (beams ) == 0 :
267
- return np .empty ((0 ), dtype = int )
268
-
269
- # extract only the node information
270
- # could keep in the future to separate the parts or elements
271
- beams = beams [["n1" , "n2" ]]
268
+ return np .empty ((0 ), dtype = int ), np .empty ((0 ), dtype = int ), np .empty ((0 ), dtype = int )
272
269
270
+ # extract the node information, element_ids and part_ids
273
271
line_with_prefix = []
272
+ eid = []
273
+ pid = []
274
274
275
275
for row in beams .itertuples (index = False ):
276
- line_with_prefix .append (line_array (row ))
276
+ line_with_prefix .append (line_array (row [2 :]))
277
+ eid .append (row [0 ])
278
+ pid .append (row [1 ])
277
279
280
+ # Convert list to np.ndarray
278
281
flat_lines = np .concatenate (line_with_prefix , axis = 0 )
279
-
280
282
flat_lines_indexed = map_facet_nid_to_index (flat_lines , mapping )
281
283
282
- return flat_lines_indexed
284
+ return flat_lines_indexed , np . array ( eid ), np . array ( pid )
283
285
284
286
285
287
def extract_solids (solids : pd .DataFrame , mapping : typing .Dict [int , int ]):
286
288
if len (solids ) == 0 :
287
- return []
289
+ return {}
288
290
289
- solids = solids .drop (columns = ["eid" , "pid" ])
291
+ solid_with_prefix = {
292
+ 8 : [[], [], []], # Hexa
293
+ 6 : [[], [], []], # Wedge
294
+ 5 : [[], [], []], # Pyramid
295
+ 4 : [[], [], []], # Tetra
296
+ }
290
297
291
- idx = 0
298
+ # extract the node information, element_ids and part_ids
299
+ for row in solids .itertuples (index = False ):
300
+ arr = np .array (row [2 :10 ])
301
+ temp_array , indices = np .unique (arr , return_index = True )
302
+ key = len (temp_array )
292
303
293
- solid_with_prefix = []
304
+ sorted_unique_indices = np .sort (indices )
305
+ temp_array = arr [sorted_unique_indices ]
294
306
295
- for row in solids .itertuples (index = False ):
296
- solid_with_prefix .append (solid_array (row ))
297
- idx += 1
307
+ if key == 6 : # convert node numbering to PyVista Style for Wedge
308
+ temp_array = temp_array [np .array ((0 , 1 , 4 , 3 , 2 , 5 ))]
309
+
310
+ solid_with_prefix [key ][0 ].append ([key , * temp_array ]) # connectivity
311
+ solid_with_prefix [key ][1 ].append (row [0 ]) # element_ids
312
+ solid_with_prefix [key ][2 ].append (row [1 ]) # part_ids
298
313
299
- flat_solids = np .concatenate (solid_with_prefix , axis = 0 )
314
+ # Convert list to np.ndarray
315
+ for key , value in solid_with_prefix .items ():
316
+ if value [0 ]:
317
+ flat_solids = np .concatenate (value [0 ], axis = 0 )
300
318
301
- flat_solids_indexed = map_facet_nid_to_index (flat_solids , mapping )
319
+ value [ 0 ] = map_facet_nid_to_index (flat_solids , mapping ) # connectivity
302
320
303
- return flat_solids_indexed
321
+ value [1 ] = np .array (value [1 ]) # element_ids
322
+ value [2 ] = np .array (value [2 ]) # part_ids
323
+
324
+ return solid_with_prefix
304
325
305
326
306
327
def get_pyvista ():
@@ -318,9 +339,14 @@ def get_polydata(deck: Deck, cwd=None):
318
339
pv = get_pyvista ()
319
340
320
341
# check kwargs for cwd. future more arguments to plot
321
- flat_deck = deck .expand (cwd )
322
- nodes_df , element_dict = merge_keywords (flat_deck )
342
+ # flatten deck
343
+ if cwd is not None :
344
+ flat_deck = deck .expand (cwd = cwd , recurse = True )
345
+ else :
346
+ flat_deck = deck .expand (recurse = True )
323
347
348
+ # get dataframes for each element types
349
+ nodes_df , element_dict = merge_keywords (flat_deck )
324
350
shells_df = element_dict ["SHELL" ]
325
351
beams_df = element_dict ["BEAM" ]
326
352
solids_df = element_dict ["SOLID" ]
@@ -332,16 +358,73 @@ def get_polydata(deck: Deck, cwd=None):
332
358
333
359
mapping = get_nid_to_index_mapping (nodes_df )
334
360
335
- facets = extract_shell_facets (shells_df , mapping )
336
- lines = extract_lines (beams_df , mapping )
337
- solids = extract_solids (solids_df , mapping )
338
- plot_data = pv .PolyData (nodes_list , [* facets , * solids ])
339
- if len (lines ) > 0 :
340
- plot_data .lines = lines
361
+ # get the node information, element_ids and part_ids
362
+ facets , shell_eids , shell_pids = extract_shell_facets (shells_df , mapping )
363
+ lines , line_eids , line_pids = extract_lines (beams_df , mapping )
364
+ solids_info = extract_solids (solids_df , mapping )
365
+
366
+ # celltype_dict for beam and shell
367
+ celltype_dict = {
368
+ pv .CellType .LINE : lines .reshape ([- 1 , 3 ])[:, 1 :],
369
+ pv .CellType .QUAD : facets .reshape ([- 1 , 5 ])[:, 1 :],
370
+ }
371
+
372
+ # dict of cell types for node counts
373
+ solid_celltype = {
374
+ 4 : pv .CellType .TETRA ,
375
+ 5 : pv .CellType .PYRAMID ,
376
+ 6 : pv .CellType .WEDGE ,
377
+ 8 : pv .CellType .HEXAHEDRON ,
378
+ }
379
+
380
+ # Update celltype_dict with solid elements
381
+ solids_pids = np .empty ((0 ), dtype = int )
382
+ solids_eids = np .empty ((0 ), dtype = int )
383
+
384
+ for n_points , elements in solids_info .items ():
385
+ if len (elements [0 ]) == 0 :
386
+ continue
387
+
388
+ temp_solids , temp_solids_eids , temp_solids_pids = elements
389
+
390
+ celltype_dict [solid_celltype [n_points ]] = temp_solids .reshape ([- 1 , n_points + 1 ])[:, 1 :]
391
+
392
+ # Update part_ids and element_ids info for solid elements
393
+ if len (solids_pids ) != 0 :
394
+ solids_pids = np .concatenate ((solids_pids , temp_solids_pids ), axis = 0 )
395
+ else :
396
+ solids_pids = temp_solids_pids
397
+
398
+ if len (solids_pids ) != 0 :
399
+ solids_eids = np .concatenate ((solids_eids , temp_solids_eids ), axis = 0 )
400
+ else :
401
+ solids_eids = temp_solids_eids
402
+
403
+ # Create UnstructuredGrid
404
+ plot_data = pv .UnstructuredGrid (celltype_dict , nodes_list )
405
+
406
+ # Mapping part_ids and element_ids
407
+ plot_data .cell_data ["part_ids" ] = np .concatenate ((line_pids , shell_pids , solids_pids ), axis = 0 )
408
+ plot_data .cell_data ["element_ids" ] = np .concatenate ((line_eids , shell_eids , solids_eids ), axis = 0 )
409
+
341
410
return plot_data
342
411
343
412
344
413
def plot_deck (deck , ** args ):
345
414
"""Plot the deck."""
415
+
416
+ # import this lazily (otherwise this adds over a second to the import time of pyDyna)
417
+ pv = get_pyvista ()
418
+
346
419
plot_data = get_polydata (deck , args .pop ("cwd" , "" ))
347
- return plot_data .plot (** args )
420
+
421
+ # set default color if both color and scalars are not specified
422
+ color = args .pop ("color" , None )
423
+ scalars = args .pop ("scalars" , None )
424
+
425
+ if scalars is not None :
426
+ return plot_data .plot (scalars = scalars , ** args ) # User specified scalars
427
+ elif color is not None :
428
+ return plot_data .plot (color = color , ** args ) # User specified color
429
+ else :
430
+ return plot_data .plot (color = pv .global_theme .color , ** args ) # Default color
0 commit comments