@@ -30,6 +30,11 @@ class RBCProblem2D():
3030 BASE_RESOLUTION = 64
3131 """Base number of mesh points in z direction"""
3232
33+
34+ @staticmethod
35+ def log (msg ):
36+ if MPI_RANK == 0 : print (msg )
37+
3338 def __init__ (self , Rayleigh = 1e7 , Prandtl = 1 ,
3439 resFactor = 1 , aspectRatio = 4 , meshRatio = 1 ,
3540 sComm = COMM_WORLD , mpiBlocks = None , printSpaceDistr = False ,
@@ -43,9 +48,16 @@ def __init__(self, Rayleigh=1e7, Prandtl=1,
4348 "Pr" : Prandtl ,
4449 }
4550
51+ self .log (" -- building grid ..." )
4652 self .buildGrid (aspectRatio , meshRatio , sComm , mpiBlocks )
53+ self .log (f" -- { self .dim } D grid done !" )
54+
4755 if printSpaceDistr : self .printSpaceDistr ()
56+
57+ self .log (" -- building problem ..." )
4858 self .buildProblem ()
59+ self .log (" -- done !" )
60+
4961 self .initField (initField , seed )
5062
5163
@@ -101,7 +113,6 @@ def grids(self):
101113 return {c : b .local_grid (self .dist , scale = 1 )
102114 for c , b in zip (self .axes , self .bases )}
103115
104-
105116 @property
106117 def dim (self ):
107118 return len (self .bases )
@@ -159,25 +170,25 @@ def initField(self, initPath, seed):
159170 z , Lz = self .z , self .Lz
160171
161172 if initPath is None : # linear buoyancy with random noise
162- if MPI_RANK == 0 : print (" -- generating randomly perturbed initial field" )
173+ self . log (" -- generating randomly perturbed initial field ... " )
163174 b .fill_random ('g' , seed = seed , distribution = 'normal' , scale = 1e-3 ) # Random noise
164175 b ['g' ] *= z * (Lz - z ) # Damp noise at walls
165176 b ['g' ] += Lz - z # Add linear background
166177 else :
167178 if os .path .isdir (initPath ): # use OutputFiles format
168179 initPath = OutputFiles (initPath )
169- if MPI_RANK == 0 : print (" -- reading field from HDF5 file" )
180+ self . log (" -- reading field from HDF5 file ... " )
170181 uInit = initPath .file ['tasks' ]
171182 for name , field in self .fields .items ():
172183 localSlices = (slice (None ),) * len (field .tensorsig ) \
173184 + self .dist .grid_layout .slices (field .domain , field .scales )
174185 try :
175186 field ['g' ] = uInit [name ][(- 1 , * localSlices )]
176187 except KeyError :
177- # field not present in file, put zeros instead
188+ self . log ( f" -- { name } not present in file, putting zeros instead" )
178189 field ['g' ] = 0
179190 elif initPath .lower ().endswith (".pysdc" ):
180- if MPI_RANK == 0 : print (" -- reading field from pySDC file" )
191+ self . log (" -- reading field from pySDC file ... " )
181192 initPath = Rectilinear .fromFile (initPath )
182193 sFields = {
183194 "buoyancy" : self .dim ,
@@ -194,11 +205,11 @@ def initField(self, initPath, seed):
194205 try :
195206 field ['g' ] = uInit [sFields [name ]]
196207 except KeyError :
197- # field not present in file, put zeros instead
208+ self . log ( f" -- { name } not present in file, putting zeros instead" )
198209 field ['g' ] = 0
199210 else :
200211 raise ValueError (f"unknown type for initField ({ initPath } )" )
201- if MPI_RANK == 0 : print (" -- done !" )
212+ self . log (" -- done !" )
202213 self .fields0 = {name : field .copy () for name , field in self .fields .items ()}
203214
204215 @classmethod
@@ -207,6 +218,8 @@ def runSimulation(cls, runDir, tEnd, baseDt, tBeg=0, logEvery=100,
207218 timeScheme = "RK443" , timeParallel = False , groupTimeProcs = False ,
208219 ** pParams ):
209220
221+ cls .log (f"RBC simulation in { runDir } " )
222+
210223 if timeScheme == "RK443" :
211224 timeStepper = d3 .RK443
212225 elif timeScheme == "RK111" :
@@ -217,6 +230,7 @@ def runSimulation(cls, runDir, tEnd, baseDt, tBeg=0, logEvery=100,
217230 timeStepper = SDCIMEX
218231 else :
219232 raise NotImplementedError (f"{ timeStepper = } " )
233+ cls .log (f" -- selected time-stepper : { timeStepper } " )
220234
221235 if timeParallel :
222236 assert timeScheme == "SDC" , "need timeScheme=SDC for timeParallel"
@@ -228,6 +242,7 @@ def runSimulation(cls, runDir, tEnd, baseDt, tBeg=0, logEvery=100,
228242 timeScheme = SDCIMEX_MPI2
229243 else :
230244 raise NotImplementedError (f"{ timeParallel = } " )
245+ cls .log (f" -- activated PinT for SDC : { timeParallel } " )
231246
232247 p = cls (** pParams )
233248
@@ -239,22 +254,21 @@ def runSimulation(cls, runDir, tEnd, baseDt, tBeg=0, logEvery=100,
239254 p .infos .update (tEnd = tEnd , dt = dt , nSteps = nSteps )
240255
241256 if os .path .isfile (f"{ runDir } /01_finalized.txt" ):
242- if MPI_RANK == 0 :
243- print (" -- simulation already finalized, skipping !" )
257+ cls .log (" -- simulation already finalized, skipping !" )
244258 return p
245259 os .makedirs (runDir , exist_ok = True )
246260 p .infos .update (dirName = runDir )
247261
248262 # Solver
249- if MPI_RANK == 0 : print (" -- building dedalus solver ..." )
263+ cls . log (" -- building dedalus solver ..." )
250264 solver = p .problem .build_solver (timeStepper )
251265 solver .sim_time = tBeg
252266 solver .stop_sim_time = tEnd
253- if MPI_RANK == 0 : print (" -- finished building dedalus solver " )
267+ cls . log (" -- done ! " )
254268
255269 # Fields IO
256270 if dtWrite :
257- if MPI_RANK == 0 : print (" -- setup fields IO " )
271+ cls . log (" -- setting up fields output ... " )
258272 iterWrite = dtWrite / dt
259273 if int (iterWrite ) != round (iterWrite , ndigits = 3 ):
260274 raise ValueError (f"{ dtWrite = } is not divisible by { dt = } ({ iterWrite = } )" )
@@ -269,7 +283,7 @@ def runSimulation(cls, runDir, tEnd, baseDt, tBeg=0, logEvery=100,
269283 if writeVort :
270284 u = p .fields ["velocity" ]
271285 snapshots .add_task (- d3 .div (d3 .skew (u )), name = 'vorticity' )
272- if MPI_RANK == 0 : print (" -- done !" )
286+ cls . log (" -- done !" )
273287
274288
275289 if MPI_RANK == 0 :
@@ -292,6 +306,7 @@ def log(msg):
292306 if nSteps == 0 :
293307 return p
294308 try :
309+ cls .log (f" -- starting simulation (see { runDir } /simu.log) ..." )
295310 log ('Starting main loop' )
296311 solver .step (dt ) # don't count first time-step in timings
297312 log ('Finished first time-step' )
@@ -312,6 +327,7 @@ def log(msg):
312327 if MPI_RANK == 0 :
313328 with open (f"{ runDir } /01_finalized.txt" , "w" ) as f :
314329 f .write ("Done !" )
330+ cls .log (" -- done !" )
315331 except :
316332 log ('Exception raised, triggering end of main loop.' )
317333 raise
@@ -354,7 +370,7 @@ def buildGrid(self, aspectRatio, meshRatio, sComm, mpiBlocks):
354370 else :
355371 blocks = BlockDecomposition (nProcs , [Ny , Nz ])
356372 mpiBlocks = blocks .nBlocks [- 1 ::- 1 ]
357- if MPI_RANK == 0 : print (f" -- { mpiBlocks = } " )
373+ self . log (f" -- { mpiBlocks = } " )
358374
359375 coords = d3 .CartesianCoordinates ('x' , 'y' , 'z' )
360376 dist = d3 .Distributor (coords , dtype = dtype , mesh = mpiBlocks , comm = sComm )
@@ -388,8 +404,6 @@ def printSpaceDistr(self):
388404 MPI .COMM_WORLD .Barrier ()
389405
390406
391-
392-
393407class OutputFiles ():
394408 """
395409 Utility class used to load and post-process solution
@@ -444,10 +458,9 @@ def shape(self):
444458 elif self .dim == 3 :
445459 return (5 , self .nX , self .nY , self .nZ )
446460
447- def getK (self , kRes = 1 ) -> np .ndarray :
448- size = self .nX // 2
449- dk = 1 / kRes
450- return np .arange (0 , size , dk ) + 0.5
461+ @property
462+ def kappa (self ) -> np .ndarray :
463+ return np .arange (self .nX // 2 ) + 0.5
451464
452465 @property
453466 def vData (self ):
@@ -677,7 +690,7 @@ def getBoundaryLayers(self,
677690
678691 return deltas
679692
680- def getSpectrum (self , which = ["uv" , "uh" ], zVal = "all" , kRes = 1 ,
693+ def getSpectrum (self , which = ["uv" , "uh" ], zVal = "all" ,
681694 start = 0 , stop = None , step = 1 , batchSize = None ):
682695 if stop is None :
683696 stop = self .nFields
@@ -686,11 +699,8 @@ def getSpectrum(self, which=["uv", "uh"], zVal="all", kRes=1,
686699 else :
687700 which = list (which )
688701
689- if self .dim == 2 :
690- assert kRes == 1 , "cannot have kRes != 1 for 2D case"
691-
692- k = self .getK (kRes )
693- spectrum = {name : np .zeros (k .size ) for name in which }
702+ kappa = self .kappa
703+ spectrum = {name : np .zeros (kappa .size ) for name in which }
694704
695705 approx = LagrangeApproximation (self .z , weightComputation = "STABLE" )
696706 if zVal == "all" :
@@ -714,7 +724,8 @@ def getSpectrum(self, which=["uv", "uh"], zVal="all", kRes=1,
714724 field = u [:, :- 1 ]
715725 if name == "b" :
716726 field = self .readFields ("buoyancy" , r .start , r .stop , r .step )[:, None , ...]
717- field -= field .mean (axis = (2 , 3 ))[:, :, None , None ]
727+ avgDir = 2 if self .dim == 2 else (2 , 3 )
728+ field -= field .mean (axis = avgDir )[:, :, None , None ]
718729 # field.shape = (nT,nVar,nX[,nY],nZ)
719730
720731 if zVal != "all" :
@@ -742,15 +753,14 @@ def getSpectrum(self, which=["uv", "uh"], zVal="all", kRes=1,
742753 assert self .nX == self .nY , "nX != nY, that will be some weird spectrum"
743754 nT , nVar , nX , nY , nZ = field .shape
744755
745- size = k .size
746- dk = 1 / kRes
756+ size = kappa .size
747757
748758 # compute 2D mode disks
749759 k1D = np .fft .fftfreq (nX , 1 / nX )** 2
750760 kMod = k1D [:, None ] + k1D [None , :]
751761 kMod **= 0.5
752762
753- idx = kMod / dk
763+ idx = kMod . copy ()
754764 np .trunc (idx , out = idx )
755765 idx *= (kMod < size )
756766 idx -= (kMod >= size )
@@ -855,8 +865,8 @@ def toVTR(self, idxFormat="{:06d}"):
855865 # Rayleigh=Rayleigh,
856866 # aspectRatio=aspectRatio, meshRatio=meshRatio, resFactor=resFactor)
857867
858- dirName = "run_3D_A4_M0.5_R1_Ra1e5 "
859- # dirName = "run_3D_A4_M1_R1"
868+ dirName = "run_3D_A4_M0.5_R1_Ra1e6 "
869+ dirName = "run_3D_A4_M1_R1"
860870 # dirName = "run_M4_R2"
861871 OutputFiles .VERBOSE = True
862872 output = OutputFiles (dirName )
@@ -891,10 +901,9 @@ def toVTR(self, idxFormat="{:06d}"):
891901 plt .xlabel ("profile" )
892902 plt .ylabel ("z coord" )
893903
894- kRes = 1
895904 spectrum = output .getSpectrum (
896- which = ["b" ], zVal = "all" , start = 30 , stop = None , kRes = kRes )
897- kappa = output .getK ( kRes )
905+ which = ["b" ], zVal = "all" , start = 30 , stop = None , batchSize = 25 )
906+ kappa = output .kappa
898907
899908 plt .figure ("spectrum" )
900909 for name , vals in spectrum .items ():
0 commit comments