3838-----
3939🚀 :class:`Cart1D` and :class:`Cart2D` are compatible with a MPI-based cartesian decomposition.
4040See :class:`pySDC.tests.test_helpers.test_fieldsIO.writeFields_MPI` for an illustrative example.
41+
42+ Warning
43+ -------
44+ To use MPI collective writing, you need to call first the class methods :class:`Cart1D.initMPI`
45+ or :class:`Cart2D.initMPI` from the associated class (cf their docstring).
46+ Also, their associated `setHeader` methods **must be given the global grids coordinates**,
47+ wether code is run in parallel or not.
4148"""
4249import os
4350import numpy as np
@@ -82,6 +89,8 @@ class FieldsIO:
8289
8390 tSize = T_DTYPE ().itemsize
8491
92+ ALLOW_OVERWRITE = False
93+
8594 def __init__ (self , dtype , fileName ):
8695 """
8796 Parameters
@@ -91,7 +100,7 @@ def __init__(self, dtype, fileName):
91100 fileName : str
92101 File.
93102 """
94- assert dtype in DTYPES_AVAIL , f"dtype not available ( { dtype } ) "
103+ assert dtype in DTYPES_AVAIL , f"{ dtype = } not available"
95104 self .dtype = dtype
96105 self .fileName = fileName
97106 self .initialized = False
@@ -170,6 +179,11 @@ def initialize(self):
170179 assert self .header is not None , "header must be set before initializing FieldsIO"
171180 assert not self .initialized , "FieldsIO already initialized"
172181
182+ if not self .ALLOW_OVERWRITE :
183+ assert not os .path .isfile (
184+ self .fileName
185+ ), "file already exists, use FieldsIO.ALLOW_OVERWRITE = True to allow overwriting"
186+
173187 with open (self .fileName , "w+b" ) as f :
174188 self .hBase .tofile (f )
175189 for array in self .hInfos :
@@ -240,8 +254,8 @@ def nFields(self):
240254 """Number of fields currently stored in the binary file"""
241255 return int ((self .fileSize - self .hSize ) // (self .tSize + self .fSize ))
242256
243- def check (self , idx ):
244- """Utility method to check a positional index for a stored field"""
257+ def formatIndex (self , idx ):
258+ """Utility method to format a fields index to a positional integer (negative starts from last field index, like python lists) """
245259 nFields = self .nFields
246260 if idx < 0 :
247261 idx = nFields + idx
@@ -262,7 +276,7 @@ def times(self):
262276
263277 def time (self , idx ):
264278 """Time stored at a given field index"""
265- idx = self .check (idx )
279+ idx = self .formatIndex (idx )
266280 offset = self .hSize + idx * (self .tSize + self .fSize )
267281 with open (self .fileName , "rb" ) as f :
268282 t = np .fromfile (f , dtype = T_DTYPE , count = 1 , offset = offset )[0 ]
@@ -285,7 +299,7 @@ def readField(self, idx):
285299 field : np.ndarray
286300 Read fields in a numpy array.
287301 """
288- idx = self .check (idx )
302+ idx = self .formatIndex (idx )
289303 offset = self .hSize + idx * (self .tSize + self .fSize )
290304 with open (self .fileName , "rb" ) as f :
291305 f .seek (offset )
@@ -494,15 +508,20 @@ def MPI_FILE_CLOSE(self):
494508 def initialize (self ):
495509 """Initialize the binary file (write header) in MPI mode"""
496510 if self .MPI_ROOT :
497- super ().initialize ()
511+ try :
512+ super ().initialize ()
513+ except AssertionError as e :
514+ print (f"{ type (e ): {e }} " )
515+ self .comm .Abort ()
516+
498517 if self .MPI_ON :
499518 self .comm .Barrier () # Important, should not be removed !
500519 self .initialized = True
501520
502521 def addField (self , time , field ):
503522 """
504523 Append one field solution at the end of the file with one given time,
505- eventually using MPI.
524+ possibly using MPI.
506525
507526 Parameters
508527 ----------
@@ -538,7 +557,7 @@ def addField(self, time, field):
538557 def readField (self , idx ):
539558 """
540559 Read one field stored in the binary file, corresponding to the given
541- time index, eventually in MPI mode.
560+ time index, possibly in MPI mode.
542561
543562 Parameters
544563 ----------
@@ -558,7 +577,7 @@ def readField(self, idx):
558577 """
559578 if not self .MPI_ON :
560579 return super ().readField (idx )
561- idx = self .check (idx )
580+ idx = self .formatIndex (idx )
562581
563582 offset0 = self .hSize + idx * (self .fSize + self .tSize )
564583 with open (self .fileName , "rb" ) as f :
@@ -651,7 +670,7 @@ def setupMPI(cls, comm: MPI.Intracomm, iLocX, nLocX, iLocY, nLocY):
651670 def addField (self , time , field ):
652671 """
653672 Append one field solution at the end of the file with one given time,
654- eventually using MPI.
673+ possibly using MPI.
655674
656675 Parameters
657676 ----------
@@ -712,7 +731,7 @@ def readField(self, idx):
712731 """
713732 if not self .MPI_ON :
714733 return super ().readField (idx )
715- idx = self .check (idx )
734+ idx = self .formatIndex (idx )
716735
717736 offset0 = self .hSize + idx * (self .tSize + self .fSize )
718737 with open (self .fileName , "rb" ) as f :
0 commit comments