Skip to content

Commit f006108

Browse files
committed
TL: update on post processing functions
1 parent 606872f commit f006108

File tree

1 file changed

+132
-86
lines changed
  • pySDC/playgrounds/dedalus/problems

1 file changed

+132
-86
lines changed

pySDC/playgrounds/dedalus/problems/rbc.py

Lines changed: 132 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,10 @@ def buildGrid(self, aspectRatio, meshRatio, sComm, mpiBlocks):
330330
baseSize = 32
331331

332332
Lx, Ly, Lz = int(aspectRatio), int(aspectRatio), 1
333-
Nx = Ny = int(baseSize*aspectRatio*meshRatio*self.resFactor)
334-
Nz = int(baseSize*self.resFactor)
333+
unitSize = baseSize*self.resFactor
334+
335+
Nx = Ny = int(aspectRatio*meshRatio*unitSize)
336+
Nz = int(unitSize)
335337
dealias = 3/2
336338
dtype = np.float64
337339

@@ -383,6 +385,8 @@ class OutputFiles():
383385
Utility class used to load and post-process solution
384386
writen with Dedalus HDF5 IO.
385387
"""
388+
VERBOSE = False
389+
386390
def __init__(self, folder):
387391
self.folder = folder
388392
fileNames = glob.glob(f"{self.folder}/*.h5")
@@ -515,8 +519,8 @@ def __iter__(self):
515519
yield range(i, min(i+self.maxSize*self.step, self.stop), self.step)
516520

517521

518-
def readFields(self, name, start=0, stop=None, step=1, verbose=False):
519-
if verbose: print(f"Reading {name} from hdf5 file {self.fileName}")
522+
def readFields(self, name, start=0, stop=None, step=1):
523+
if self.VERBOSE: print(f"Reading {name} from hdf5 file {self.fileName}")
520524
if name == "velocity":
521525
fData = self.vData
522526
elif name == "buoyancy":
@@ -527,29 +531,35 @@ def readFields(self, name, start=0, stop=None, step=1, verbose=False):
527531
raise ValueError(f"cannot read {name} from file")
528532
if stop is None:
529533
stop = self.nFields
530-
if verbose: print(f" -- field[{start}:{stop}:{step}]")
534+
if self.VERBOSE: print(f" -- field[{start}:{stop}:{step}]")
531535
data = fData[start:stop:step]
532-
if verbose: print(" -- done !")
536+
if self.VERBOSE: print(" -- done !")
533537
return data
534538

535539

536540
def getProfiles(self, which=["uRMS", "bRMS"],
537-
start=0, stop=None, step=1, batchSize=None,
538-
verbose=False):
541+
start=0, stop=None, step=1, batchSize=None):
542+
if stop is None:
543+
stop = self.nFields
539544
avgAxes = (0, 1) if self.dim==2 else (0, 1, 2)
540545
formula = {
541546
"u" : "u.sum(axis=1)",
542547
"uv": "u[:, -1]",
543548
"uh": "u[:, :-1].sum(axis=1)",
544549
"b": "b",
545-
"p": "p"
550+
"p": "p",
546551
}
552+
547553
if which == "all":
548554
which = [var+"Mean" for var in formula.keys()] \
549555
+ [var+"RMS" for var in formula.keys()]
556+
else:
557+
which = list(which)
558+
if "bRMS" in which and "bMean" not in which:
559+
which.append("bMean")
560+
if "pRMS" in which and "pMean" not in which:
561+
which.append("pMean")
550562
profiles = {name: np.zeros(self.nZ) for name in which}
551-
if stop is None:
552-
stop = self.nFields
553563

554564
nSamples = 0
555565
def addSamples(current, new, nNew):
@@ -558,93 +568,111 @@ def addSamples(current, new, nNew):
558568
current += new
559569
current /= (nSamples + nNew)
560570

571+
# Mean profiles
561572
for r in self.BatchRanges(start, stop, step, batchSize):
562573

563574
bSize = len(r)
564575

565576
# Read required data
566-
if set(["uRMS", "uvRMS", "uhRMS",
567-
"uMean", "uvMean", "uhMean"]).intersection(which):
568-
u = self.readFields("velocity", r.start, r.stop, r.step, verbose)
569-
if set(["bRMS", "bMean"]).intersection(which):
570-
b = self.readFields("buoyancy", r.start, r.stop, r.step, verbose)
571-
if set(["pRMS", "pMean"]).intersection(which):
572-
p = self.readFields("pressure", r.start, r.stop, r.step, verbose)
577+
if set(["uMean", "uvMean", "uhMean",
578+
"uRMS", "uvRMS", "uhRMS"]).intersection(which):
579+
u = self.readFields("velocity", r.start, r.stop, r.step)
580+
if set(["bMean"]).intersection(which):
581+
b = self.readFields("buoyancy", r.start, r.stop, r.step)
582+
if set(["pMean"]).intersection(which):
583+
p = self.readFields("pressure", r.start, r.stop, r.step)
573584

574585
# Mean profiles
575-
if "uMean" in which:
576-
uMean = u.sum(axis=1).mean(axis=avgAxes)
577-
addSamples(profiles["uMean"], uMean, bSize)
578-
if "uvMean" in which:
579-
uvMean = u[:, -1].mean(axis=avgAxes)
580-
addSamples(profiles["uvMean"], uvMean, bSize)
581-
if "uhMean" in which:
582-
uhMean = u[:, :-1].sum(axis=1).mean(axis=avgAxes)
583-
addSamples(profiles["uhMean"], uhMean, bSize)
584-
if "bMean" in which:
585-
bMean = b.mean(axis=avgAxes)
586-
addSamples(profiles["bMean"], bMean, bSize)
587-
if "pMean" in which:
588-
pMean = p.mean(axis=avgAxes)
589-
addSamples(profiles["pMean"], pMean, bSize)
586+
for name in which:
587+
if "Mean" in name:
588+
var = eval(formula[name[:-4]]).mean(axis=avgAxes)
589+
addSamples(profiles[name], var, bSize)
590590

591-
# RMS profiles
592-
# -- inplace power 2 first
593591
try: u **= 2
594592
except: pass
595-
try: b **= 2
596-
except: pass
597-
try: p **= 2
598-
except: pass
599593

600-
if "uRMS" in which:
601-
uRMS = u.sum(axis=1).mean(axis=avgAxes)
602-
addSamples(profiles["uRMS"], uRMS, bSize)
603-
if "uvRMS" in which:
604-
uvRMS = u[:, -1].mean(axis=avgAxes)
605-
addSamples(profiles["uvRMS"], uvRMS, bSize)
606-
if "uhRMS" in which:
607-
uhRMS = u[:, :-1].sum(axis=1).mean(axis=avgAxes)
608-
addSamples(profiles["uhRMS"], uhRMS, bSize)
594+
# RMS profiles
595+
for name in which:
596+
if "RMS" in name and name not in ["bRMS", "pRMS"]:
597+
var = eval(formula[name[:-3]]).mean(axis=avgAxes)
598+
addSamples(profiles[name], var, bSize)
599+
600+
nSamples += bSize
601+
602+
# bRMS and pRMS require precomputed mean
603+
nSamples = 0
604+
for r in self.BatchRanges(start, stop, step, batchSize):
605+
606+
bSize = len(r)
607+
609608
if "bRMS" in which:
609+
b = self.readFields("buoyancy", r.start, r.stop, r.step)
610+
b -= profiles["bMean"]
611+
b **= 2
610612
bRMS = b.mean(axis=avgAxes)
611613
addSamples(profiles["bRMS"], bRMS, bSize)
614+
612615
if "pRMS" in which:
616+
p = self.readFields("pressure", r.start, r.stop, r.step)
617+
p -= profiles["pMean"]
618+
p **= 2
613619
pRMS = p.mean(axis=avgAxes)
614620
addSamples(profiles["pRMS"], pRMS, bSize)
615621

616622
nSamples += bSize
617623

624+
# Square root after time averaging for RMS
618625
for name, val in profiles.items():
619626
if "RMS" in name:
620627
val **= 0.5
628+
621629
profiles["nSamples"] = nSamples
622630
return profiles
623631

632+
def getTimeSeries(self, which=["ke"], batchSize=None):
633+
634+
series = {name: [] for name in which}
635+
avgAxes = 1 if self.dim==2 else (1, 2)
636+
637+
Iz = LagrangeApproximation(self.z).getIntegrationMatrix([(0, 1)])
638+
639+
for r in self.BatchRanges(self.nFields, maxSize=batchSize):
640+
641+
if "ke" in which:
642+
u = self.readFields("velocity", r.start, r.stop, r.step)
643+
u **= 2
644+
ke = Iz @ u.sum(axis=1).mean(axis=avgAxes)[..., None]
645+
series["ke"].append(ke.ravel())
646+
647+
for key, val in series.items():
648+
series[key] = np.array(val).ravel()
624649

625-
def getLayersQuantities(self, iBeg=0, iEnd=None, step=1, verbose=False):
626-
uMean, _, bRMS = self.getMeanProfiles(
627-
bRMS=True, iBeg=iBeg, iEnd=iEnd, step=step, verbose=verbose)
628-
uMean = uMean.mean(axis=0)
629-
bRMS = bRMS.mean(axis=0)
650+
return series
630651

631-
z = self.z
632-
nFine = int(1e4)
633-
zFine = np.linspace(0, 1, num=nFine)
634-
P = LagrangeApproximation(z).getInterpolationMatrix(zFine)
635652

636-
uMeanFine = P @ uMean
637-
bRMSFine = P @ bRMS
653+
def getBoundaryLayers(self,
654+
which=["uRMS", "bRMS"], profiles=None,
655+
start=0, stop=None, step=1, batchSize=None):
638656

639-
approx = LagrangeApproximation(z)
657+
if which == "all":
658+
which = ["uRMS", "bRMS", "uhRMS"]
659+
else:
660+
which = list(which)
661+
deltas = {name: None for name in which}
662+
663+
if profiles is None:
664+
profiles = {}
665+
missing = set(which).difference(profiles.keys())
666+
profiles.update(self.getProfiles(missing, start, stop, step, batchSize))
640667

641-
xOptU = sco.minimize_scalar(lambda z: -approx(z, fValues=uMeanFine), bounds=[0, 0.5])
642-
xOptB = sco.minimize_scalar(lambda z: -approx(z, fValues=bRMS), bounds=[0, 0.5])
668+
approx = LagrangeApproximation(self.z)
643669

644-
deltaU = xOptU.x
645-
deltaT = xOptB.x
670+
for name in which:
671+
values = profiles[name]
672+
opt = sco.minimize_scalar(lambda z: -approx(z, fValues=values), bounds=[0, 0.5])
673+
deltas[name] = opt.x
646674

647-
return zFine, uMeanFine, bRMSFine, deltaU, deltaT
675+
return deltas
648676

649677

650678
@staticmethod
@@ -832,36 +860,54 @@ def toVTR(self, idxFormat="{:06d}"):
832860
template = f"{baseName}_{idxFormat}"
833861
coords = [self.x, self.y, self.z]
834862
varNames = ["velocity_x", "velocity_y", "velocity_z", "buoyancy", "pressure"]
835-
for i in range(np.cumsum(self.nFields)[0]):
836-
u = self.fields(i)
863+
for i in range(self.nFields):
864+
u = self.readFieldAt(i)
837865
writeToVTR(template.format(i), u, coords, varNames)
838866

839867

840868
if __name__ == "__main__":
841869
import matplotlib.pyplot as plt
842870

843-
dirName = "run_3D_A4_R1_M1"
871+
aspectRatio = 4 # Lx = Ly = A*Lz
872+
meshRatio = 0.5 # Nx/Lx = Ny/Ly = M*Nz/Lz
873+
resFactor = 1 # Nz = R*32
874+
875+
dirName = f"run_3D_A{aspectRatio}_M{meshRatio}_R{resFactor}"
844876

845877
problem = RBCProblem3D.runSimulation(
846878
dirName, 100, 1e-2/4, logEvery=20, dtWrite=1.0,
847-
aspectRatio=4, resFactor=1, meshRatio=1)
848-
849-
output = OutputFiles(dirName)
850-
profiles = output.getProfiles(which="all", verbose=True, batchSize=25)
851-
852-
for name, p in profiles.items():
853-
if "Mean" in name:
854-
plt.figure("Mean profiles")
855-
plt.plot(p, output.z, label=name)
856-
if "RMS" in name:
857-
plt.figure("RMS profiles")
858-
plt.plot(p, output.z, label=name)
859-
860-
for pType in ["Mean", "RMS"]:
861-
plt.figure(f"{pType} profiles")
862-
plt.legend()
863-
plt.xlabel("profile")
864-
plt.ylabel("z coord")
879+
aspectRatio=4, meshRatio=1, resFactor=1)
880+
881+
# OutputFiles.VERBOSE = True
882+
# output = OutputFiles(dirName)
883+
884+
# series = output.getTimeSeries()
885+
886+
# plt.figure("series")
887+
# plt.plot(output.times, series["ke"], label="ke")
888+
# plt.legend()
889+
890+
# profiles = output.getProfiles(which="all", batchSize=None, start=40)
891+
892+
# deltas = output.getBoundaryLayers(which="all", profiles=profiles)
893+
894+
# for name, p in profiles.items():
895+
# if "Mean" in name:
896+
# plt.figure("Mean profiles")
897+
# plt.plot(p, output.z, label=name)
898+
# if name in deltas:
899+
# plt.hlines(deltas[name], p.min(), p.max(), linestyles="--", colors="black")
900+
# if "RMS" in name:
901+
# plt.figure("RMS profiles")
902+
# plt.plot(p, output.z, label=name)
903+
# if name in deltas:
904+
# plt.hlines(deltas[name], p.min(), p.max(), linestyles="--", colors="black")
905+
906+
# for pType in ["Mean", "RMS"]:
907+
# plt.figure(f"{pType} profiles")
908+
# plt.legend()
909+
# plt.xlabel("profile")
910+
# plt.ylabel("z coord")
865911

866912

867913
# approx = LagrangeApproximation(output.z)

0 commit comments

Comments
 (0)