2727import numpy as np
2828from .vtk import (
2929 VtkFile ,
30+ VtkParallelFile ,
3031 VtkUnstructuredGrid ,
3132 VtkImageData ,
3233 VtkRectilinearGrid ,
3334 VtkStructuredGrid ,
35+ VtkPImageData ,
36+ VtkPRectilinearGrid ,
37+ VtkPStructuredGrid ,
38+ VtkUnstructuredGrid ,
3439 VtkVertex ,
3540 VtkLine ,
3641 VtkPolyLine ,
@@ -81,6 +86,33 @@ def _addDataToFile(vtkFile, cellData, pointData, fieldData=None):
8186 vtkFile .closeData ("Field" )
8287
8388
89+ def _addDataToParallelFile (vtkParallelFile , cellData , pointData ):
90+ assert isinstance (vtkParallelFile , VtkParallelFile )
91+ # Point data
92+ if pointData :
93+ keys = list (pointData .keys ())
94+ # find first scalar and vector data key to set it as attribute
95+ scalars = next ((key for key in keys if pointData [key ][1 ] == 1 ), None )
96+ vectors = next ((key for key in keys if pointData [key ][1 ] == 3 ), None )
97+ vtkParallelFile .openData ("PPoint" , scalars = scalars , vectors = vectors )
98+ for key in keys :
99+ dtype , ncomp = pointData [key ]
100+ vtkParallelFile .addHeader (key , dtype = dtype , ncomp = ncomp )
101+ vtkParallelFile .closeData ("PPoint" )
102+
103+ # Cell data
104+ if cellData :
105+ keys = list (cellData .keys ())
106+ # find first scalar and vector data key to set it as attribute
107+ scalars = next ((key for key in keys if cellData [key ][1 ] == 1 ), None )
108+ vectors = next ((key for key in keys if cellData [key ][1 ] == 3 ), None )
109+ vtkParallelFile .openData ("PCell" , scalars = scalars , vectors = vectors )
110+ for key in keys :
111+ dtype , ncomp = cellData [key ]
112+ vtkParallelFile .addHeader (key , dtype = dtype , ncomp = ncomp )
113+ vtkParallelFile .closeData ("PCell" )
114+
115+
84116def _appendDataToFile (vtkFile , cellData , pointData , fieldData = None ):
85117 # Append data to binary section
86118 if pointData is not None :
@@ -112,6 +144,7 @@ def imageToVTK(
112144 cellData = None ,
113145 pointData = None ,
114146 fieldData = None ,
147+ start = (0 , 0 , 0 ),
115148):
116149 """
117150 Export data values as a rectangular image.
@@ -120,6 +153,10 @@ def imageToVTK(
120153 ----------
121154 path : str
122155 name of the file without extension where data should be saved.
156+ start : tuple, optional
157+ start of the coordinates.
158+ Used in the distributed context where each process
159+ writes its own vtk file. Default is (0, 0, 0).
123160 origin : tuple, optional
124161 grid origin.
125162 The default is (0.0, 0.0, 0.0).
@@ -138,7 +175,7 @@ def imageToVTK(
138175 Arrays must have same dimension in each direction and
139176 they should be equal to the dimensions of the cell data plus one and
140177 can contain scalar data ([n+1,n+1,n+1]) or
141- +1,n+1,n+1],[n+1,n+1,n+1],[n+1,n+1,n+1]).
178+ ([n +1,n+1,n+1],[n+1,n+1,n+1],[n+1,n+1,n+1]).
142179 The default is None.
143180 fieldData : dict, optional
144181 dictionary with variables associated with the field.
@@ -157,7 +194,6 @@ def imageToVTK(
157194 assert cellData is not None or pointData is not None
158195
159196 # Extract dimensions
160- start = (0 , 0 , 0 )
161197 end = None
162198 if cellData is not None :
163199 keys = list (cellData .keys ())
@@ -188,9 +224,11 @@ def imageToVTK(
188224
189225
190226# ==============================================================================
191- def gridToVTK (path , x , y , z , cellData = None , pointData = None , fieldData = None ):
227+ def gridToVTK (
228+ path , x , y , z , cellData = None , pointData = None , fieldData = None , start = (0 , 0 , 0 )
229+ ):
192230 """
193- Write data values as a rectilinear or rectangular grid.
231+ Write data values as a rectilinear or structured grid.
194232
195233 Parameters
196234 ----------
@@ -202,6 +240,10 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
202240 y coordinate axis.
203241 z : array-like
204242 z coordinate axis.
243+ start : tuple, optional
244+ start of the coordinates.
245+ Used in the distributed context where each process
246+ writes its own vtk file. Default is (0, 0, 0).
205247 cellData : dict, optional
206248 dictionary containing arrays with cell centered data.
207249 Keys should be the names of the data arrays.
@@ -216,12 +258,10 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
216258 fieldData : dict, optional
217259 dictionary with variables associated with the field.
218260 Keys should be the names of the variable stored in each array.
219-
220261 Returns
221262 -------
222263 str
223264 Full path to saved file.
224-
225265 Notes
226266 -----
227267 coordinates of the nodes of the grid. They can be 1D or 3D depending if
@@ -235,8 +275,6 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
235275 In both cases the arrays dimensions should be
236276 equal to the number of nodes of the grid.
237277 """
238- # Extract dimensions
239- start = (0 , 0 , 0 )
240278 nx = ny = nz = 0
241279
242280 if x .ndim == 1 and y .ndim == 1 and z .ndim == 1 :
@@ -249,13 +287,22 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
249287 isRect = False
250288 ftype = VtkStructuredGrid
251289 else :
252- assert False
253- end = (nx , ny , nz )
290+ raise ValueError (
291+ f"x, y and z should have ndim == 3 but they have ndim of { x .ndim } , { y .ndim } "
292+ f" and { z .ndim } respectively"
293+ )
254294
295+ # Write extent
296+ end = (start [0 ] + nx , start [1 ] + ny , start [2 ] + nz )
297+
298+ # Open File
255299 w = VtkFile (path , ftype )
300+
301+ # Open Grid part
256302 w .openGrid (start = start , end = end )
257303 w .openPiece (start = start , end = end )
258304
305+ # Add coordinates description
259306 if isRect :
260307 w .openElement ("Coordinates" )
261308 w .addData ("x_coordinates" , x )
@@ -267,16 +314,101 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
267314 w .addData ("points" , (x , y , z ))
268315 w .closeElement ("Points" )
269316
317+ # Add data description
270318 _addDataToFile (w , cellData , pointData , fieldData )
319+
320+ # Close Grid part
271321 w .closePiece ()
272322 w .closeGrid ()
323+
273324 # Write coordinates
274325 if isRect :
275326 w .appendData (x ).appendData (y ).appendData (z )
276327 else :
277328 w .appendData ((x , y , z ))
278329 # Write data
279330 _appendDataToFile (w , cellData , pointData , fieldData )
331+
332+ # Close file
333+ w .save ()
334+
335+ return w .getFileName ()
336+
337+
338+ def writeParallelVTKGrid (
339+ path , coordsData , starts , ends , sources , ghostlevel = 0 , cellData = None , pointData = None
340+ ):
341+ """
342+ Writes a parallel vtk file from grid-like data:
343+ VTKStructuredGrid or VTKRectilinearGrid
344+
345+ Parameters
346+ ----------
347+ path : str
348+ name of the file without extension.
349+ coordsData : tuple
350+ 2-tuple (shape, dtype) where shape is the
351+ shape of the coordinates of the full mesh
352+ and dtype is the dtype of the coordinates.
353+ starts : list
354+ list of 3-tuple representing where each source file starts
355+ in each dimension
356+ source : list
357+ list of the relative paths of the source files where the actual data is found
358+ ghostlevel : int, optional
359+ Number of ghost-levels by which
360+ the extents in the individual source files overlap.
361+ pointData : dict
362+ dictionnary containing the information about the arrays
363+ containing node centered data.
364+ Keys shoud be the names of the arrays.
365+ Values are (dtype, number of components)
366+ cellData :
367+ dictionnary containing the information about the arrays
368+ containing cell centered data.
369+ Keys shoud be the names of the arrays.
370+ Values are (dtype, number of components)
371+ """
372+ # Check that every source as a start and an end
373+ assert len (starts ) == len (ends ) == len (sources )
374+
375+ # Get the extension + check that it's consistent accros all source files
376+ common_ext = sources [0 ].split ("." )[- 1 ]
377+ assert all (s .split ("." )[- 1 ] == common_ext for s in sources )
378+
379+ if common_ext == "vts" :
380+ ftype = VtkPStructuredGrid
381+ is_Rect = False
382+ elif common_ext == "vtr" :
383+ ftype = VtkPRectilinearGrid
384+ is_Rect = True
385+ else :
386+ raise ValueError ("This functions is meant to work only with " )
387+
388+ w = VtkParallelFile (path , ftype )
389+ start = (0 , 0 , 0 )
390+ (s_x , s_y , s_z ), dtype = coordsData
391+ end = s_x - 1 , s_y - 1 , s_z - 1
392+
393+ w .openGrid (start = start , end = end , ghostlevel = ghostlevel )
394+
395+ _addDataToParallelFile (w , cellData = cellData , pointData = pointData )
396+
397+ if is_Rect :
398+ w .openElement ("PCoordinates" )
399+ w .addHeader ("x_coordinates" , dtype = dtype , ncomp = 1 )
400+ w .addHeader ("y_coordinates" , dtype = dtype , ncomp = 1 )
401+ w .addHeader ("z_coordinates" , dtype = dtype , ncomp = 1 )
402+ w .closeElement ("PCoordinates" )
403+ else :
404+ w .openElement ("PPoints" )
405+ w .addHeader ("points" , dtype = dtype , ncomp = 3 )
406+ w .closeElement ("PPoints" )
407+
408+ for start_source , end_source , source in zip (starts , ends , sources ):
409+ w .addPiece (start_source , end_source , source )
410+
411+ w .closeGrid ()
280412 w .save ()
281413 return w .getFileName ()
282414
0 commit comments