@@ -176,7 +176,7 @@ def dpf_mesh_to_vtk_py(mesh, nodes, as_linear):
176176        Meshed Region to export to pyVista format 
177177
178178    nodes : dpf.Field 
179-         Field containing the nodes  of the mesh. 
179+         Field containing the node coordinates  of the mesh. 
180180
181181    as_linear : bool 
182182        Export quadratic surface elements as linear. 
@@ -189,9 +189,11 @@ def dpf_mesh_to_vtk_py(mesh, nodes, as_linear):
189189    etypes  =  mesh .elements .element_types_field .data 
190190    connectivity  =  mesh .elements .connectivities_field 
191191    if  nodes  is  None :
192-         nodes  =  mesh .nodes .coordinates_field .data 
192+         coordinates_field  =  mesh .nodes .coordinates_field 
193+         node_coordinates  =  coordinates_field .data 
193194    else :
194-         nodes  =  nodes .data 
195+         coordinates_field  =  nodes 
196+         node_coordinates  =  nodes .data 
195197
196198    elem_size  =  np .ediff1d (np .append (connectivity ._data_pointer , connectivity .shape ))
197199
@@ -207,22 +209,21 @@ def dpf_mesh_to_vtk_py(mesh, nodes, as_linear):
207209    insert_ind  =  np .cumsum (elem_size )
208210    insert_ind  =  np .hstack (([0 ], insert_ind ))[:- 1 ]
209211
210-     # Handle semiparabolic elements 
211-     nullmask  =  connectivity .data  ==  - 1 
212-     connectivity .data [nullmask ] =  0 
213-     if  nullmask .any ():
214-         nodes [0 ] =  np .nan 
212+     # if not as_linear: 
213+     #     # Pre-handle semi-parabolic elements 
214+     #     semi_mask = connectivity.data == -1 
215+     #     if semi_mask.any(): 
216+     #         # Modify -1 connectivity values 
217+     #         repeated_data_pointers = connectivity._data_pointer.repeat(repeats=elem_size) 
218+     #         connectivity.data[semi_mask] = connectivity.data[repeated_data_pointers[semi_mask]] 
215219
216-     # For each polyhedron, cell = [nCellFaces, nFace0pts, i, j, k, ..., nFace1pts, i, j, k, ...] 
217-     # polys_ind = insert_ind[polyhedron_mask] 
218-     # cells = np.take(cells, sorted(set(insert_ind)-set(polys_ind))) 
219220    # partition cells in vtk format 
220221    cells  =  np .insert (connectivity .data , insert_ind , elem_size )
221222
222223    # Check if polyhedrons are present 
223224    if  element_types .Polyhedron .value  in  etypes :
224225        cells  =  np .array (cells )
225-         nodes  =  np .array (nodes )
226+         nodes  =  np .array (node_coordinates )
226227        insert_ind  =  insert_ind  +  np .asarray (list (range (len (insert_ind ))))
227228        # Replace in cells values for polyhedron format 
228229        # [NValuesToFollow, 
@@ -252,45 +253,93 @@ def compute_offset():
252253        """Return the starting point of a cell in the cells array""" 
253254        return  insert_ind  +  np .arange (insert_ind .size )
254255
256+     cells_insert_ind  =  compute_offset ()
255257    # convert kAns to VTK cell type 
256258    offset  =  None 
257259    if  as_linear :
260+         # Map the vtk_cell_type to linear versions of the initial elements types 
258261        vtk_cell_type  =  VTK_LINEAR_MAPPING [etypes ]
259262
260-         # visualization bug within VTK with quadratic surf cells 
261-         ansquad8_mask  =  etypes  ==  6 
262-         if  np .any (ansquad8_mask ):  # kAnsQuad8 
263- 
264-             # simply copy the edge node indices to the midside points 
265-             offset  =  compute_offset ()
266-             cell_pos  =  offset [ansquad8_mask ]
267-             cells [cell_pos  +  5 ] =  cells [cell_pos  +  1 ]
268-             cells [cell_pos  +  6 ] =  cells [cell_pos  +  2 ]
269-             cells [cell_pos  +  7 ] =  cells [cell_pos  +  3 ]
270-             cells [cell_pos  +  8 ] =  cells [cell_pos  +  4 ]
271- 
272-         anstri6_mask  =  etypes  ==  4   # kAnsTri6 = 4 
273-         if  np .any (anstri6_mask ):
274-             if  offset  is  None :
275-                 offset  =  compute_offset ()
276-             cell_pos  =  offset [anstri6_mask ]
277-             cells [cell_pos  +  4 ] =  cells [cell_pos  +  1 ]
278-             cells [cell_pos  +  5 ] =  cells [cell_pos  +  2 ]
279-             cells [cell_pos  +  6 ] =  cells [cell_pos  +  3 ]
263+         # Create a global mask of connectivity values to take 
264+         mask  =  np .full (cells .shape , True )
265+ 
266+         # Get a mask of quad8 elements in etypes 
267+         quad8_mask  =  etypes  ==  6 
268+         # If any quad8 
269+         if  np .any (quad8_mask ):  # kAnsQuad8 
270+             # Get the starting indices of quad8 elements in cells 
271+             insert_ind_quad8  =  cells_insert_ind [quad8_mask ]
272+             # insert_ind_quad8 += np.arange(insert_ind_quad8.size) 
273+             mask [insert_ind_quad8  +  5 ] =  False 
274+             mask [insert_ind_quad8  +  6 ] =  False 
275+             mask [insert_ind_quad8  +  7 ] =  False 
276+             mask [insert_ind_quad8  +  8 ] =  False 
277+             cells [insert_ind_quad8 ] //=  2 
278+ 
279+         tri6_mask  =  etypes  ==  4   # kAnsTri6 = 4 
280+         if  np .any (tri6_mask ):
281+             insert_ind_tri6  =  cells_insert_ind [tri6_mask ]
282+             # insert_ind_tri6 += np.arange(insert_ind_tri6.size) 
283+             mask [insert_ind_tri6  +  4 ] =  False 
284+             mask [insert_ind_tri6  +  5 ] =  False 
285+             mask [insert_ind_tri6  +  6 ] =  False 
286+             cells [insert_ind_tri6 ] //=  2 
287+         cells  =  cells [mask ]
280288
281289    else :
282290        vtk_cell_type  =  VTK_MAPPING [etypes ]
283291
292+         # Handle semi-parabolic elements 
293+         semi_mask  =  cells  ==  - 1 
294+         if  semi_mask .any ():
295+             cells_insert_ind  =  compute_offset ()
296+             # Create a global mask of connectivity values to take 
297+             mask  =  np .full (cells .shape , True )
298+             # Build a map of size cells with repeated element beginning index 
299+             repeated_insert_ind  =  cells_insert_ind .repeat (repeats = elem_size  +  1 )
300+             # Apply the semi-mask to get a unique set of indices of semi-parabolic elements in cells 
301+             semi_indices_in_cells  =  np .array (list (set (repeated_insert_ind [semi_mask ])))
302+             semi_sizes  =  cells [semi_indices_in_cells ]
303+             semi_quad8  =  semi_sizes  ==  8 
304+             if  semi_quad8 .any ():
305+                 mask [semi_indices_in_cells [semi_quad8 ] +  5 ] =  False 
306+                 mask [semi_indices_in_cells [semi_quad8 ] +  6 ] =  False 
307+                 mask [semi_indices_in_cells [semi_quad8 ] +  7 ] =  False 
308+                 mask [semi_indices_in_cells [semi_quad8 ] +  8 ] =  False 
309+                 cells [semi_indices_in_cells [semi_quad8 ]] //=  2 
310+ 
311+                 quad8_mask  =  etypes  ==  6 
312+                 semi_quad8_mask  =  (cells [cells_insert_ind ] ==  4 ) &  quad8_mask 
313+                 vtk_cell_type [semi_quad8_mask ] =  VTK_LINEAR_MAPPING [6 ]
314+             semi_tri6  =  semi_sizes  ==  6 
315+             if  semi_tri6 .any ():
316+                 mask [semi_indices_in_cells [semi_tri6 ] +  4 ] =  False 
317+                 mask [semi_indices_in_cells [semi_tri6 ] +  5 ] =  False 
318+                 mask [semi_indices_in_cells [semi_tri6 ] +  6 ] =  False 
319+                 cells [semi_indices_in_cells [semi_tri6 ]] //=  2 
320+ 
321+                 tri6_mask  =  etypes  ==  4 
322+                 semi_tri6_mask  =  (cells [cells_insert_ind ] ==  3 ) &  tri6_mask 
323+                 vtk_cell_type [semi_tri6_mask ] =  VTK_LINEAR_MAPPING [4 ]
324+             # Update cells with the mask 
325+             cells  =  cells [mask ]
326+ 
284327    # different treatment depending on the version of vtk 
285328    if  VTK9 :
286329        # compute offset array when < VTK v9 
287-         return  pv .UnstructuredGrid (cells , vtk_cell_type , nodes )
330+         grid  =  pv .UnstructuredGrid (cells , vtk_cell_type , node_coordinates )
331+ 
332+         # Quick fix required to hold onto the data as PyVista does not make a copy. 
333+         # All of those now return DPFArrays 
334+         setattr (grid , "_dpf_cache" , [node_coordinates , coordinates_field ])
335+ 
336+         return  grid 
288337
289338    # might be computed when checking for VTK quadratic bug 
290339    if  offset  is  None :
291340        offset  =  compute_offset ()
292341
293-     return  pv .UnstructuredGrid (offset , cells , vtk_cell_type , nodes )
342+     return  pv .UnstructuredGrid (offset , cells , vtk_cell_type , node_coordinates )
294343
295344
296345def  dpf_mesh_to_vtk (mesh , nodes = None , as_linear = True ):
0 commit comments