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 = pointData [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 :
@@ -107,6 +139,7 @@ def _appendDataToFile(vtkFile, cellData, pointData, fieldData=None):
107139# =================================
108140def imageToVTK (
109141 path ,
142+ start = (0 , 0 , 0 ),
110143 origin = (0.0 , 0.0 , 0.0 ),
111144 spacing = (1.0 , 1.0 , 1.0 ),
112145 cellData = None ,
@@ -115,11 +148,14 @@ def imageToVTK(
115148):
116149 """
117150 Export data values as a rectangular image.
118-
119151 Parameters
120152 ----------
121153 path : str
122154 name of the file without extension where data should be saved.
155+ start : tuple, optional
156+ start of the coordinates.
157+ Used in the distributed context where each process
158+ writes its own vtk file. Default is (0, 0, 0).
123159 origin : tuple, optional
124160 grid origin.
125161 The default is (0.0, 0.0, 0.0).
@@ -138,17 +174,15 @@ def imageToVTK(
138174 Arrays must have same dimension in each direction and
139175 they should be equal to the dimensions of the cell data plus one and
140176 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]).
177+ ([n +1,n+1,n+1],[n+1,n+1,n+1],[n+1,n+1,n+1]).
142178 The default is None.
143179 fieldData : dict, optional
144180 dictionary with variables associated with the field.
145181 Keys should be the names of the variable stored in each array.
146-
147182 Returns
148183 -------
149184 str
150185 Full path to saved file.
151-
152186 Notes
153187 -----
154188 At least, cellData or pointData must be present
@@ -157,7 +191,6 @@ def imageToVTK(
157191 assert cellData is not None or pointData is not None
158192
159193 # Extract dimensions
160- start = (0 , 0 , 0 )
161194 end = None
162195 if cellData is not None :
163196 keys = list (cellData .keys ())
@@ -188,10 +221,11 @@ def imageToVTK(
188221
189222
190223# ==============================================================================
191- def gridToVTK (path , x , y , z , cellData = None , pointData = None , fieldData = None ):
224+ def gridToVTK (
225+ path , x , y , z , start = (0 , 0 , 0 ), cellData = None , pointData = None , fieldData = None
226+ ):
192227 """
193- Write data values as a rectilinear or rectangular grid.
194-
228+ Write data values as a structured grid.
195229 Parameters
196230 ----------
197231 path : str
@@ -202,6 +236,10 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
202236 y coordinate axis.
203237 z : array-like
204238 z coordinate axis.
239+ start : tuple, optional
240+ start of the coordinates.
241+ Used in the distributed conwhere each process
242+ writes its own vtk file. Default is (0, 0, 0).
205243 cellData : dict, optional
206244 dictionary containing arrays with cell centered data.
207245 Keys should be the names of the data arrays.
@@ -216,12 +254,10 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
216254 fieldData : dict, optional
217255 dictionary with variables associated with the field.
218256 Keys should be the names of the variable stored in each array.
219-
220257 Returns
221258 -------
222259 str
223260 Full path to saved file.
224-
225261 Notes
226262 -----
227263 coordinates of the nodes of the grid. They can be 1D or 3D depending if
@@ -235,8 +271,6 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
235271 In both cases the arrays dimensions should be
236272 equal to the number of nodes of the grid.
237273 """
238- # Extract dimensions
239- start = (0 , 0 , 0 )
240274 nx = ny = nz = 0
241275
242276 if x .ndim == 1 and y .ndim == 1 and z .ndim == 1 :
@@ -249,13 +283,22 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
249283 isRect = False
250284 ftype = VtkStructuredGrid
251285 else :
252- assert False
253- end = (nx , ny , nz )
286+ raise ValueError (
287+ f"x, y and z should have ndim == 3 but they have ndim of { x .ndim } , { y .ndim } "
288+ f" and { z .ndim } respectively"
289+ )
290+
291+ # Write extent
292+ end = (start [0 ] + nx , start [1 ] + ny , start [2 ] + nz )
254293
294+ # Open File
255295 w = VtkFile (path , ftype )
296+
297+ # Open Grid part
256298 w .openGrid (start = start , end = end )
257299 w .openPiece (start = start , end = end )
258300
301+ # Add coordinates description
259302 if isRect :
260303 w .openElement ("Coordinates" )
261304 w .addData ("x_coordinates" , x )
@@ -267,16 +310,101 @@ def gridToVTK(path, x, y, z, cellData=None, pointData=None, fieldData=None):
267310 w .addData ("points" , (x , y , z ))
268311 w .closeElement ("Points" )
269312
313+ # Add data description
270314 _addDataToFile (w , cellData , pointData , fieldData )
315+
316+ # Close Grid part
271317 w .closePiece ()
272318 w .closeGrid ()
319+
273320 # Write coordinates
274321 if isRect :
275322 w .appendData (x ).appendData (y ).appendData (z )
276323 else :
277324 w .appendData ((x , y , z ))
278325 # Write data
279326 _appendDataToFile (w , cellData , pointData , fieldData )
327+
328+ # Close file
329+ w .save ()
330+
331+ return w .getFileName ()
332+
333+
334+ def writeParallelVTKGrid (
335+ path , coordsData , starts , ends , sources , ghostlevel = 0 , cellData = None , pointData = None
336+ ):
337+ """
338+ Writes a parallel vtk file from grid-like data:
339+ VTKStructuredGrid or VTKRectilinearGrid
340+
341+ Parameters
342+ ----------
343+ path : str
344+ name of the file without extension.
345+ coordsData : tuple
346+ 2-tuple (shape, dtype) where shape is the
347+ shape of the coordinates of the full mesh
348+ and dtype is the dtype of the coordinates.
349+ starts : list
350+ list of 3-tuple representing where each source file starts
351+ in each dimension
352+ source : list
353+ list of the relative paths of the source files where the actual data is found
354+ ghostlevel : int, optional
355+ Number of ghost-levels by which
356+ the extents in the individual source files overlap.
357+ pointData : dict
358+ dictionnary containing the information about the arrays
359+ containing node centered data.
360+ Keys shoud be the names of the arrays.
361+ Values are (dtype, number of components)
362+ cellData :
363+ dictionnary containing the information about the arrays
364+ containing cell centered data.
365+ Keys shoud be the names of the arrays.
366+ Values are (dtype, number of components)
367+ """
368+ # Check that every source as a start and an end
369+ assert len (starts ) == len (ends ) == len (sources )
370+
371+ # Get the extension + check that it's consistent accros all source files
372+ common_ext = sources [0 ].split ("." )[- 1 ]
373+ assert all (s .split ("." )[- 1 ] == common_ext for s in sources )
374+
375+ if common_ext == "vts" :
376+ ftype = VtkPStructuredGrid
377+ is_Rect = False
378+ elif common_ext == "vtr" :
379+ ftype = VtkPRectilinearGrid
380+ is_Rect = True
381+ else :
382+ raise ValueError ("This functions is meant to work only with " )
383+
384+ w = VtkParallelFile (path , ftype )
385+ start = (0 , 0 , 0 )
386+ (s_x , s_y , s_z ), dtype = coordsData
387+ end = s_x - 1 , s_y - 1 , s_z - 1
388+
389+ w .openGrid (start = start , end = end , ghostlevel = ghostlevel )
390+
391+ _addDataToParallelFile (w , cellData = cellData , pointData = pointData )
392+
393+ if is_Rect :
394+ w .openElement ("PCoordinates" )
395+ w .addHeader ("x_coordinates" , dtype = dtype , ncomp = 1 )
396+ w .addHeader ("y_coordinates" , dtype = dtype , ncomp = 1 )
397+ w .addHeader ("z_coordinates" , dtype = dtype , ncomp = 1 )
398+ w .closeElement ("PCoordinates" )
399+ else :
400+ w .openElement ("PPoints" )
401+ w .addHeader ("points" , dtype = dtype , ncomp = 3 )
402+ w .closeElement ("PPoints" )
403+
404+ for start_source , end_source , source in zip (starts , ends , sources ):
405+ w .addPiece (start_source , end_source , source )
406+
407+ w .closeGrid ()
280408 w .save ()
281409 return w .getFileName ()
282410
0 commit comments