Skip to content

Commit 28a41f4

Browse files
committed
TL: finalized RBC run script
1 parent 739d0c6 commit 28a41f4

File tree

3 files changed

+51
-40
lines changed

3 files changed

+51
-40
lines changed

pySDC/playgrounds/dedalus/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
demos/*.png
33
problems/test_*
44
problems/run_*
5+
6+
scripts/*.sh
7+
scripts/run_*

pySDC/playgrounds/dedalus/problems/rbc.py

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
393407
class 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():

pySDC/playgrounds/dedalus/scripts/run_rbc.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
# -*- coding: utf-8 -*-
33
import argparse
44

5-
from pySDC.helpers.fieldsIO import FieldsIO
6-
from pySDC.playgrounds.dedalus.problems.rbc import RBCProblem2D, RBCProblem3D, OutputFiles
5+
from pySDC.playgrounds.dedalus.problems.rbc import RBCProblem2D, RBCProblem3D
76

87
parser = argparse.ArgumentParser(
98
description='Run RBC simulation using Dedalus',
@@ -25,10 +24,10 @@
2524
"--resFactor", "-rf", help="resolution factor, Nz = 64*rf (2D) or 32*rf (3D)",
2625
default=1, type=float)
2726
parser.add_argument(
28-
"--Rayleigh", "-ra", help="Rayleigh number",
27+
"--Rayleigh", "-Ra", help="Rayleigh number",
2928
default=1e7, type=float)
3029
parser.add_argument(
31-
"--Prandtl", "-pr", help="Prandtl number",
30+
"--Prandtl", "-Pr", help="Prandtl number",
3231
default=1, type=float)
3332
parser.add_argument(
3433
"--initField", "-if", help="path for the initial field",
@@ -47,7 +46,7 @@
4746
"--logEvery", "-l", help="log every [...] time-steps",
4847
default=100, type=int)
4948

50-
args = parser.parse_args(["test"])
49+
args = parser.parse_args()
5150
params = args.__dict__
5251

5352
dim = params.pop("dim")

0 commit comments

Comments
 (0)