From 1deecfe64a63de5770ad5deff3199c1242580e19 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:15:25 -0600 Subject: [PATCH 01/52] Add SwirlMixer class --- bird/preprocess/dynamic_mixer/mixer.py | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index 524ff43c..607ae9f4 100644 --- a/bird/preprocess/dynamic_mixer/mixer.py +++ b/bird/preprocess/dynamic_mixer/mixer.py @@ -93,3 +93,112 @@ def check_status(self, blocks=None): logger.info(f"\tbranch = {blocks}") self.ready = True + + +class SwirlMixer: + """Actuator-disk mixer with optional swirl, used by the ``ball`` source. + + Unlike :class:`Mixer` (the legacy ``pancake`` source), momentum is deposited + over a ball of physical radius ``R`` and the drive is set by a power number + ``Np`` and tip speed ``Vtip`` rather than a raw power. ``sigma`` is the swirl + fraction; ``sign`` is the axial push direction and ``swirl_sign`` the + (independent) rotation sense. + """ + + def __init__(self): + self.x = None + self.y = None + self.z = None + self.normal_dir = None + self.R = None # physical mixer radius [m] + self.Vtip = 1.5 # tip speed [m/s] + self.Np = 6.0 # power number [-] + self.sigma = 0.35 # swirl fraction [-] + self.power = None # mixer power P [W], only used when power=from_P + self.sign = None # axial push sign, "+" / "-" + self.swirl_sign = "+" # rotation sense, "+" / "-" + self.start_time = 1.0 + self.ready = False + + def _read_common(self, mixer_dict: dict) -> None: + """Read the per-mixer keys""" + if "Vtip" in mixer_dict: + self.Vtip = mixer_dict["Vtip"] + if "Np" in mixer_dict: + self.Np = mixer_dict["Np"] + if "sigma" in mixer_dict: + self.sigma = mixer_dict["sigma"] + if "power" in mixer_dict: + self.power = mixer_dict["power"] + if "sign" in mixer_dict: + self.sign = mixer_dict["sign"] + if "swirl_sign" in mixer_dict: + self.swirl_sign = mixer_dict["swirl_sign"] + if "start_time" in mixer_dict: + self.start_time = mixer_dict["start_time"] + + def update_from_expl_dict(self, mixer_dict: dict) -> None: + """Populate from an explicit mixer dict (absolute position and radius).""" + if "x" in mixer_dict: + self.x = mixer_dict["x"] + if "y" in mixer_dict: + self.y = mixer_dict["y"] + if "z" in mixer_dict: + self.z = mixer_dict["z"] + if "normal_dir" in mixer_dict: + self.normal_dir = mixer_dict["normal_dir"] + if "radius" in mixer_dict: + # explicit mode: radius is absolute [m] + self.R = mixer_dict["radius"] + self._read_common(mixer_dict) + self.check_status() + + def update_from_loop_dict(self, mixer_dict: dict, geom_dict: dict) -> None: + """Populate from a loop mixer dict. + + :param mixer_dict: mixer entry with ``branch_id``, ``frac_space`` and, + optionally, ``radius`` as a fraction of the branch cross-section. + :param geom_dict: output of ``from_block_rect_to_seg`` (``segments`` and + ``blocksize``). + """ + segment = geom_dict["segments"][mixer_dict["branch_id"]] + pos = segment["start"] + mixer_dict["frac_space"] * segment["conn"] + self.x = float(pos[0]) + self.y = float(pos[1]) + self.z = float(pos[2]) + self.normal_dir = segment["normal_dir"] + # radius is a fraction of the branch cross-section (as for spargers): + # R = frac * mean of the two block sizes transverse to the axis. + bx, by, bz = geom_dict["blocksize"] + transverse = {0: (by, bz), 1: (bx, bz), 2: (bx, by)}[self.normal_dir] + frac = mixer_dict.get("radius", 0.4) + self.R = frac * 0.5 * (transverse[0] + transverse[1]) + self._read_common(mixer_dict) + self.check_status(blocks=segment["blocks"]) + + def check_status(self, blocks=None) -> None: + """Log the resolved mixer and set ``ready`` if all fields are present.""" + if ( + self.x is None + or self.y is None + or self.z is None + or self.normal_dir is None + or self.R is None + or self.sign not in ("+", "-") + or self.swirl_sign not in ("+", "-") + ): + self.ready = False + else: + logger.info( + f"\n\tpos({self.x:.2g}, {self.y:.2g}, {self.z:.2g})" + + f"\n\tnormal_dir {self.normal_dir}" + + f"\n\tR {self.R:.2g}" + + f"\n\tVtip {self.Vtip:.2g}" + + f"\n\tNp {self.Np:.2g}" + + f"\n\tsigma {self.sigma:.2g}" + + f"\n\tsign {self.sign} swirl_sign {self.swirl_sign}" + + f"\n\tstart_time {self.start_time:.2g}" + ) + if blocks is not None: + logger.info(f"\tbranch = {blocks}") + self.ready = True From b9d3df293fa081f3c83f6cee79ee05f0ae688eee Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:23:23 -0600 Subject: [PATCH 02/52] rename to actuator class, swirl is decided later --- bird/preprocess/dynamic_mixer/mixer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index 607ae9f4..2a4ff555 100644 --- a/bird/preprocess/dynamic_mixer/mixer.py +++ b/bird/preprocess/dynamic_mixer/mixer.py @@ -95,7 +95,7 @@ def check_status(self, blocks=None): self.ready = True -class SwirlMixer: +class ActuatorMixer: """Actuator-disk mixer with optional swirl, used by the ``ball`` source. Unlike :class:`Mixer` (the legacy ``pancake`` source), momentum is deposited From 13ad8c3a2d73335383dba5710cd64d92bac0b4dc Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:35:33 -0600 Subject: [PATCH 03/52] ball-source fvModels writer --- bird/preprocess/dynamic_mixer/io_fvModels.py | 198 +++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index 414dfdf6..4e01d7d5 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -326,6 +326,204 @@ def write_mixer_force_sign(mixer, output_folder): f.write("\t\t}\n") +def write_preamble_ball(output_folder): + """Write the FoamFile header + codedSource preamble for the ``ball`` source. + + The Newton solve is inlined in each mixer block (see ``write_mixer_ball``), + so no external ``dynamicMix_util.H`` is needed. + """ + with open(os.path.join(output_folder, "fvModels"), "w+") as f: + f.write("FoamFile\n") + f.write("{\n") + f.write("\tversion 2.0;\n") + f.write("\tformat ascii;\n") + f.write("\tclass dictionary;\n") + f.write('\tlocation "constant";\n') + f.write("\tobject fvModels;\n") + f.write("}\n\n") + f.write("codedSource\n") + f.write("{\n") + f.write("\ttype\tcoded;\n") + f.write("\tselectionMode\tall;\n") + f.write("\tfield\tU.liquid;\n") + f.write("\tname\tsourceTime;\n\n") + f.write("\tcodeInclude\n") + f.write("\t#{\n") + f.write("\t\t#include \n") + f.write("\t\t#include \n") + f.write("\t#};\n\n") + f.write("\tcodeAddAlphaRhoSup\n") + f.write("\t#{\n") + f.write("\t\tconst Time& time = mesh().time();\n") + f.write("\t\tconst scalarField& V = mesh().V();\n") + f.write("\t\tvectorField& Usource = eqn.source();\n") + f.write("\t\tconst vectorField& C = mesh().C();\n") + f.write("\t\tconst volScalarField& rhoL =\n") + f.write( + '\t\t\tmesh().lookupObject("thermo:rho.liquid");\n' + ) + f.write("\t\tconst volScalarField& alphaL =\n") + f.write('\t\t\tmesh().lookupObject("alpha.liquid");\n') + f.write("\t\tconst volVectorField& UL =\n") + f.write('\t\t\tmesh().lookupObject("U.liquid");\n') + f.write("\t\tconst double pi = 3.14159265358979;\n") + + +def write_mixer_ball( + mixer, output_folder, power_mode="from_Np_Vtip", momentum_mode="axial" +): + """Append one ``ball`` mixer block to ``fvModels``. + + :param mixer: a ready :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`. + :param power_mode: ``"from_P"`` (drive by ``mixer.power``) or + ``"from_Np_Vtip"`` (drive by ``mixer.Np`` and ``mixer.Vtip``). + :param momentum_mode: ``"axial"`` (thrust only) or ``"axial_and_swirl"`` + (thrust + tangential source using ``mixer.sigma``). + """ + if power_mode not in ("from_P", "from_Np_Vtip"): + raise ValueError(f"unknown power_mode {power_mode!r}") + if momentum_mode not in ("axial", "axial_and_swirl"): + raise ValueError(f"unknown momentum_mode {momentum_mode!r}") + if power_mode == "from_P" and mixer.power is None: + raise ValueError("power_mode 'from_P' requires 'power' in the mixer") + + nd = int(mixer.normal_dir) + dn = ["dx", "dy", "dz"][nd] + # theta_hat = n_hat x r_hat, per axis: (component index, numerator expr) + tan = { + 0: [(1, "-dz"), (2, "dy")], + 1: [(0, "dz"), (2, "-dx")], + 2: [(0, "-dy"), (1, "dx")], + }[nd] + push_ax = "1.0" if mixer.sign == "+" else "-1.0" + push_th = "1.0" if mixer.swirl_sign == "+" else "-1.0" + swirl = momentum_mode == "axial_and_swirl" + + if power_mode == "from_P": + rhs = f"4.0*{mixer.power}/(rhoM*area)" + else: + rhs = f"16.0*{mixer.Np}*Vtip*Vtip*Vtip/pow(pi,4.0)" + swirl_F = f" + {mixer.sigma}*(V1+V2)*Vtip*Vtip" if swirl else "" + swirl_dF = f" + {mixer.sigma}*Vtip*Vtip" if swirl else "" + + with open(os.path.join(output_folder, "fvModels"), "a+") as f: + f.write("\t\t// ===== ball mixer =====\n") + f.write("\t\t{\n") + f.write(f"\t\t\tconst double Rmix = {mixer.R};\n") + f.write("\t\t\tconst double area = pi*Rmix*Rmix;\n") + f.write(f"\t\t\tconst double Vtip = {mixer.Vtip};\n") + if swirl: + f.write(f"\t\t\tconst double sigma = {mixer.sigma};\n") + f.write(f"\t\t\tconst double startT = {mixer.start_time};\n") + f.write( + f"\t\t\tconst double px = {mixer.x}, py = {mixer.y}, pz = {mixer.z};\n" + ) + f.write("\t\t\tif (time.value() > startT)\n") + f.write("\t\t\t{\n") + # --- sense V1 and rho over the upstream half-ball --- + f.write("\t\t\t\tscalar sV = 0.0, sVU = 0.0, sVrho = 0.0;\n") + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write(f"\t\t\t\t\tif (d2 <= Rmix*Rmix && {push_ax}*{dn} < 0.0)\n") + f.write("\t\t\t\t\t{\n") + f.write("\t\t\t\t\t\tconst double w = V[i]*alphaL[i];\n") + f.write(f"\t\t\t\t\t\tsV += w; sVU += w*UL[i][{nd}]; sVrho += w*rhoL[i];\n") + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t\treduce(sV, sumOp());\n") + f.write("\t\t\t\treduce(sVU, sumOp());\n") + f.write("\t\t\t\treduce(sVrho, sumOp());\n") + f.write(f"\t\t\t\tdouble V1 = (sV>1e-30) ? {push_ax}*(sVU/sV) : 0.0;\n") + f.write("\t\t\t\tif (V1 < 0.0) V1 = 0.0;\n") + f.write("\t\t\t\tconst double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0;\n") + # --- Newton solve for V2 --- + f.write(f"\t\t\t\tconst double rhs = {rhs};\n") + f.write( + "\t\t\t\tdouble V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs));\n" + ) + f.write("\t\t\t\tfor (int it = 0; it < 100; ++it)\n") + f.write("\t\t\t\t{\n") + f.write( + f"\t\t\t\t\tconst double F = (V2-V1)*(V2+V1)*(V2+V1){swirl_F} - rhs;\n" + ) + f.write( + f"\t\t\t\t\tconst double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1{swirl_dF};\n" + ) + f.write("\t\t\t\t\tconst double dV = F/dF;\n") + f.write("\t\t\t\t\tV2 -= dV;\n") + f.write("\t\t\t\t\tif (std::abs(dV) < 1e-10) break;\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t\tconst double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1);\n") + if swirl: + f.write( + "\t\t\t\tconst double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip;\n" + ) + # --- pass 1: normalisation sums over the ball --- + if swirl: + f.write("\t\t\t\tscalar Sax = 0.0, Sth = 0.0;\n") + else: + f.write("\t\t\t\tscalar Sax = 0.0;\n") + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write("\t\t\t\t\tif (d2 <= Rmix*Rmix)\n") + f.write("\t\t\t\t\t{\n") + f.write( + "\t\t\t\t\t\tconst double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i]));\n" + ) + f.write("\t\t\t\t\t\tconst double g = std::exp(-d2/(epsi*epsi));\n") + f.write("\t\t\t\t\t\tSax += alphaL[i]*g*V[i];\n") + if swirl: + f.write(f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n") + f.write("\t\t\t\t\t\tSth += alphaL[i]*g*rr*V[i];\n") + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t\treduce(Sax, sumOp());\n") + if swirl: + f.write("\t\t\t\treduce(Sth, sumOp());\n") + # --- pass 2: apply --- + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write("\t\t\t\t\tif (d2 <= Rmix*Rmix)\n") + f.write("\t\t\t\t\t{\n") + f.write( + "\t\t\t\t\t\tconst double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i]));\n" + ) + f.write("\t\t\t\t\t\tconst double g = std::exp(-d2/(epsi*epsi));\n") + f.write("\t\t\t\t\t\tif (Sax > 1e-30)\n") + f.write("\t\t\t\t\t\t{\n") + f.write("\t\t\t\t\t\t\tconst double fax = Tax/Sax*alphaL[i]*g;\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {push_ax}*fax*V[i];\n") + f.write("\t\t\t\t\t\t}\n") + if swirl: + f.write(f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n") + f.write("\t\t\t\t\t\tif (rr > 1e-3*Rmix && Sth > 1e-30)\n") + f.write("\t\t\t\t\t\t{\n") + f.write("\t\t\t\t\t\t\tconst double fth = Qsw/Sth*alphaL[i]*g;\n") + f.write( + f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] += {push_th}*fth*V[i]*(({tan[0][1]})/rr);\n" + ) + f.write( + f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] += {push_th}*fth*V[i]*(({tan[1][1]})/rr);\n" + ) + f.write("\t\t\t\t\t\t}\n") + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t}\n") + f.write("\t\t}\n") + + def write_end(output_folder): with open(os.path.join(output_folder, "fvModels"), "a+") as f: f.write("\t#};\n") From 8a712045cce1cc9f967943b1dda9d2eaff08f472 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:36:06 -0600 Subject: [PATCH 04/52] format --- bird/preprocess/dynamic_mixer/io_fvModels.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index 4e01d7d5..e2077c17 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -431,15 +431,21 @@ def write_mixer_ball( f.write(f"\t\t\t\t\tif (d2 <= Rmix*Rmix && {push_ax}*{dn} < 0.0)\n") f.write("\t\t\t\t\t{\n") f.write("\t\t\t\t\t\tconst double w = V[i]*alphaL[i];\n") - f.write(f"\t\t\t\t\t\tsV += w; sVU += w*UL[i][{nd}]; sVrho += w*rhoL[i];\n") + f.write( + f"\t\t\t\t\t\tsV += w; sVU += w*UL[i][{nd}]; sVrho += w*rhoL[i];\n" + ) f.write("\t\t\t\t\t}\n") f.write("\t\t\t\t}\n") f.write("\t\t\t\treduce(sV, sumOp());\n") f.write("\t\t\t\treduce(sVU, sumOp());\n") f.write("\t\t\t\treduce(sVrho, sumOp());\n") - f.write(f"\t\t\t\tdouble V1 = (sV>1e-30) ? {push_ax}*(sVU/sV) : 0.0;\n") + f.write( + f"\t\t\t\tdouble V1 = (sV>1e-30) ? {push_ax}*(sVU/sV) : 0.0;\n" + ) f.write("\t\t\t\tif (V1 < 0.0) V1 = 0.0;\n") - f.write("\t\t\t\tconst double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0;\n") + f.write( + "\t\t\t\tconst double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0;\n" + ) # --- Newton solve for V2 --- f.write(f"\t\t\t\tconst double rhs = {rhs};\n") f.write( @@ -481,7 +487,9 @@ def write_mixer_ball( f.write("\t\t\t\t\t\tconst double g = std::exp(-d2/(epsi*epsi));\n") f.write("\t\t\t\t\t\tSax += alphaL[i]*g*V[i];\n") if swirl: - f.write(f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n") + f.write( + f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n" + ) f.write("\t\t\t\t\t\tSth += alphaL[i]*g*rr*V[i];\n") f.write("\t\t\t\t\t}\n") f.write("\t\t\t\t}\n") @@ -507,7 +515,9 @@ def write_mixer_ball( f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {push_ax}*fax*V[i];\n") f.write("\t\t\t\t\t\t}\n") if swirl: - f.write(f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n") + f.write( + f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n" + ) f.write("\t\t\t\t\t\tif (rr > 1e-3*Rmix && Sth > 1e-30)\n") f.write("\t\t\t\t\t\t{\n") f.write("\t\t\t\t\t\t\tconst double fth = Qsw/Sth*alphaL[i]*g;\n") From 7f8e3e55b77be462dd9e1ce8989150f8aebc3096 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:43:35 -0600 Subject: [PATCH 05/52] machinery to call the right mixer --- .../dynamic_mixer/mixing_fvModels.py | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/bird/preprocess/dynamic_mixer/mixing_fvModels.py b/bird/preprocess/dynamic_mixer/mixing_fvModels.py index 6a4e99e6..1c23ca07 100644 --- a/bird/preprocess/dynamic_mixer/mixing_fvModels.py +++ b/bird/preprocess/dynamic_mixer/mixing_fvModels.py @@ -1,6 +1,6 @@ from bird.meshing.block_rect_mesh import from_block_rect_to_seg from bird.preprocess.dynamic_mixer.io_fvModels import * -from bird.preprocess.dynamic_mixer.mixer import Mixer +from bird.preprocess.dynamic_mixer.mixer import ActuatorMixer, Mixer def check_input(input_dict): @@ -26,6 +26,12 @@ def check_input(input_dict): def write_fvModel(input_dict, output_folder=".", force_sign=False): + # Switch on the volumetric source: "ball" (new, exact-conservation + # actuator-disk) vs "pancake" (legacy, default). The legacy path below is + # left byte-for-byte unchanged. + if input_dict.get("volumetric_source", "pancake") == "ball": + write_fvModel_ball(input_dict, output_folder=output_folder) + return mix_type = check_input(input_dict) write_preamble(output_folder) if "loop" in mix_type: @@ -51,3 +57,28 @@ def write_fvModel(input_dict, output_folder=".", force_sign=False): write_mixer(mixer, output_folder) write_end(output_folder) + + +def write_fvModel_ball(input_dict, output_folder="."): + """Write the ``ball`` (actuator-disk) fvModels. + + Reads the top-level ``power`` (``from_P`` / ``from_Np_Vtip``) and + ``momentum_source`` (``axial`` / ``axial_and_swirl``) modes; both default to + the new full model. Each mixer is an + :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`. + """ + mix_type = check_input(input_dict) + power_mode = input_dict.get("power", "from_Np_Vtip") + momentum_mode = input_dict.get("momentum_source", "axial_and_swirl") + write_preamble_ball(output_folder) + if "loop" in mix_type: + geom_dict = from_block_rect_to_seg(input_dict["Geometry"]) + for imix, mtype in enumerate(mix_type): + mixer = ActuatorMixer() + if mtype == "expl": + mixer.update_from_expl_dict(input_dict["mixers"][imix]) + elif mtype == "loop": + mixer.update_from_loop_dict(input_dict["mixers"][imix], geom_dict) + if mixer.ready: + write_mixer_ball(mixer, output_folder, power_mode, momentum_mode) + write_end(output_folder) From b6681fdda23e5be8f612e0d9596831a0794f1c6f Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:51:40 -0600 Subject: [PATCH 06/52] new tutorial for the new mixer --- .github/workflows/ci.yml | 7 +- .../loop_reactor_mixing_swirl/0.orig/CO2.gas | 47 + .../0.orig/CO2.liquid | 42 + .../loop_reactor_mixing_swirl/0.orig/H2.gas | 47 + .../0.orig/H2.liquid | 42 + .../loop_reactor_mixing_swirl/0.orig/N2.gas | 47 + .../loop_reactor_mixing_swirl/0.orig/T.gas | 46 + .../loop_reactor_mixing_swirl/0.orig/T.liquid | 45 + .../loop_reactor_mixing_swirl/0.orig/U.gas | 47 + .../loop_reactor_mixing_swirl/0.orig/U.liquid | 46 + .../0.orig/Ydefault.gas | 42 + .../0.orig/Ydefault.liquid | 42 + .../0.orig/alpha.gas | 43 + .../0.orig/alpha.liquid | 40 + .../0.orig/alphat.gas | 46 + .../0.orig/alphat.liquid | 44 + .../0.orig/epsilon.gas | 48 + .../0.orig/epsilon.liquid | 43 + .../loop_reactor_mixing_swirl/0.orig/f.gas | 41 + .../loop_reactor_mixing_swirl/0.orig/k.gas | 43 + .../loop_reactor_mixing_swirl/0.orig/k.liquid | 44 + .../loop_reactor_mixing_swirl/0.orig/nut.gas | 48 + .../0.orig/nut.liquid | 43 + .../loop_reactor_mixing_swirl/0.orig/p | 39 + .../loop_reactor_mixing_swirl/0.orig/p_rgh | 43 + .../loop_reactor_mixing_swirl/Allclean | 24 + .../loop_reactor_mixing_swirl/README.md | 27 + .../loop_reactor_mixing_swirl/computeQOI.sh | 13 + .../constant/fvModels | 353 ++++++ .../loop_reactor_mixing_swirl/constant/g | 21 + .../constant/globalVars | 83 ++ .../constant/globalVars_temp | 83 ++ .../constant/momentumTransport.gas | 26 + .../constant/momentumTransport.liquid | 27 + .../constant/phaseProperties | 261 ++++ .../constant/phaseProperties_constantd | 261 ++++ .../constant/phaseProperties_pbe | 295 +++++ .../constant/thermophysicalProperties.gas | 142 +++ .../constant/thermophysicalProperties.liquid | 108 ++ .../loop_reactor_mixing_swirl/get_qoi.py | 199 ++++ .../loop_reactor_mixing_swirl/presteps.sh | 81 ++ .../loop_reactor_mixing_swirl/read_history.py | 104 ++ .../loop_reactor_mixing_swirl/run.sh | 72 ++ .../loop_reactor_mixing_swirl/script | 14 + .../loop_reactor_mixing_swirl/script_post | 10 + .../system/blockMeshDict | 1050 +++++++++++++++++ .../system/controlDict | 66 ++ .../system/decomposeParDict | 30 + .../system/fvConstraints | 56 + .../system/fvSchemes | 70 ++ .../system/fvSolution | 120 ++ .../system/inlets_outlets.json | 177 +++ .../system/mesh.json | 26 + .../system/mixers.json | 175 +++ .../system/setFieldsDict | 37 + .../writeGlobalVars.py | 42 + tutorial_cases/runall.sh | 6 +- 57 files changed, 5122 insertions(+), 2 deletions(-) create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/N2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/f.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/p create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/0.orig/p_rgh create mode 100755 tutorial_cases/loop_reactor_mixing_swirl/Allclean create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/README.md create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/computeQOI.sh create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/g create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars_temp create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_constantd create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_pbe create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/get_qoi.py create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/presteps.sh create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/read_history.py create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/run.sh create mode 100755 tutorial_cases/loop_reactor_mixing_swirl/script create mode 100755 tutorial_cases/loop_reactor_mixing_swirl/script_post create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/blockMeshDict create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/controlDict create mode 100755 tutorial_cases/loop_reactor_mixing_swirl/system/decomposeParDict create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/fvConstraints create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/fvSchemes create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/fvSolution create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/inlets_outlets.json create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/mesh.json create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/mixers.json create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/system/setFieldsDict create mode 100644 tutorial_cases/loop_reactor_mixing_swirl/writeGlobalVars.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5247c979..d8efcf29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -245,7 +245,12 @@ jobs: - name: Run mixing loop reactor tutorial run: | cd tutorial_cases/loop_reactor_mixing - bash run.sh + bash run.sh + cd ../../ + - name: Run mixing loop reactor with swirl tutorial + run: | + cd tutorial_cases/loop_reactor_mixing_swirl + bash run.sh cd ../../ - name: Run airlift reactor tutorial run: | diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.gas new file mode 100644 index 00000000..e4165b1a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_CO2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_CO2; + //value $f_CO2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.liquid new file mode 100644 index 00000000..4b8ea6a0 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/CO2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.gas new file mode 100644 index 00000000..9f66b2d2 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_H2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_H2; + //value $f_H2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.liquid new file mode 100644 index 00000000..65ae8d34 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/H2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/N2.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/N2.gas new file mode 100644 index 00000000..c1d7225f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/N2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_N2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_N2; + //value $f_N2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.gas new file mode 100644 index 00000000..1202c340 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value $internalField; + } + + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.liquid new file mode 100644 index 00000000..d6c1836a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/T.liquid @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + inlet + { + type fixedValue; + value $internalField; + } + defaultFaces + { + type zeroGradient; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.gas new file mode 100644 index 00000000..e696566f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0.0 0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateGas; + //rho thermo:rho.gas; + //value $internalField; + type fixedValue; + value uniform (0 $uGasPhase 0); + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + defaultFaces + { + type slip; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.liquid new file mode 100644 index 00000000..1879e020 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/U.liquid @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0 0 0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateLiq; + //rho thermo:rho.liquid; + //value $internalField; + type fixedValue; + value uniform (0 0 0); + } + outlet + { + type noSlip; + } + defaultFaces + { + type noSlip; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.gas new file mode 100644 index 00000000..fba2945d --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.gas @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid new file mode 100644 index 00000000..a5108564 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.gas new file mode 100644 index 00000000..1e303fbe --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $alphaGas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaGas; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1; + value uniform 1; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.liquid new file mode 100644 index 00000000..5c92070b --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alpha.liquid @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaLiq; + } + outlet + { + type fixedValue; + value uniform 0; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.gas new file mode 100644 index 00000000..b867958f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type calculated; + value $internalField; + //type compressible::alphatWallFunction; + //Prt 0.85; + //value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.liquid new file mode 100644 index 00000000..2569c3ee --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/alphat.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.gas new file mode 100644 index 00000000..707a1cda --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object epsilon.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $eps_inlet_gas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $eps_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + //type epsilonWallFunction; + //value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.liquid new file mode 100644 index 00000000..0a4236fd --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/epsilon.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object epsilon.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $eps_inlet_liq; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $eps_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type epsilonWallFunction; + value $internalField; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/f.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/f.gas new file mode 100644 index 00000000..76ee77a9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/f.gas @@ -0,0 +1,41 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object f.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; //$internalField; // + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.gas new file mode 100644 index 00000000..4a3d44ca --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_gas; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.liquid new file mode 100644 index 00000000..cde8f6c1 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/k.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_liq; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.gas b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.gas new file mode 100644 index 00000000..ba16dd4c --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-8; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + //type nutkWallFunction; + //value $internalField; + type calculated; + value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.liquid b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.liquid new file mode 100644 index 00000000..1442e07f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/nut.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p new file mode 100644 index 00000000..b3a295fb --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p @@ -0,0 +1,39 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + defaultFaces + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p_rgh b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p_rgh new file mode 100644 index 00000000..88ee7d80 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/0.orig/p_rgh @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + rho thermo:rho.gas; + value $internalField; + } + defaultFaces + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/Allclean b/tutorial_cases/loop_reactor_mixing_swirl/Allclean new file mode 100755 index 00000000..dc2f77db --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/Allclean @@ -0,0 +1,24 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +if [ -n "$WM_PROJECT_DIR" ]; then + . $WM_PROJECT_DIR/bin/tools/CleanFunctions + cleanCase +else + echo "WARNING: could not run cleanCase, OpenFOAM env not found" +fi + +# Remove 0 +[ -d "0" ] && rm -rf 0 + +# rm -f constant/triSurface/*.eMesh +# [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" +[ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" +[ -d "dynamicCode" ] && rm -rf "dynamicCode" +[ -d "processor*" ] && rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/tutorial_cases/loop_reactor_mixing_swirl/README.md b/tutorial_cases/loop_reactor_mixing_swirl/README.md new file mode 100644 index 00000000..794e422d --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/README.md @@ -0,0 +1,27 @@ +### Loop reactor with actuator-disk mixers (with swirl) + +Same 608 m3 loop reactor as `loop_reactor_mixing`, but the 4 mixers use the +new `ball` actuator-disk momentum source instead of the legacy `pancake` one. + +The model is selected by three top-level keys in `system/mixers.json`: + +- `"volumetric_source": "ball"` — momentum deposited over a ball of radius `R` + (a fraction of the branch cross-section), with exact momentum/torque + conservation. +- `"power": "from_Np_Vtip"` — the mixer power is derived from the power + number `Np` and tip speed `Vtip` (rather than a prescribed `P`). +- `"momentum_source": "axial_and_swirl"` — adds a tangential (swirl) source on + top of the axial thrust, set by the swirl fraction `sigma`. + +Per-mixer inputs: `radius` (fraction of the branch cross-section, as for the +spargers), `Vtip` [m/s], `Np`, `sigma`, `sign` (axial push) and `swirl_sign` +(rotation sense). With `Np = 6` and `Vtip = 1.5` m/s the derived power is +~3.2 kW per mixer at this scale. + +Unlike `loop_reactor_mixing`, no `constant/dynamicMix_util.H` is needed: the +Newton solve for the post-mixer velocity is inlined in the generated +`constant/fvModels`. + +Single core exec + +1. `bash run.sh` diff --git a/tutorial_cases/loop_reactor_mixing_swirl/computeQOI.sh b/tutorial_cases/loop_reactor_mixing_swirl/computeQOI.sh new file mode 100644 index 00000000..3756ed7f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/computeQOI.sh @@ -0,0 +1,13 @@ +if [ ! -f qoi.txt ]; then + # Reconstruct if needed + source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc + reconstructPar -newTimes + module load anaconda3/2023 + conda activate /projects/gas2fuels/conda_env/bird + python read_history.py -cr .. -cn local -df data + python get_qoi.py + conda deactivate +else + echo "WARNING: QOI already computed" +fi + diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels b/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels new file mode 100644 index 00000000..8bad277c --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels @@ -0,0 +1,353 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include + #include + #}; + + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + const double pi = 3.14159265358979; + // ===== ball mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Vtip = 1.5; + const double sigma = 0.35; + const double startT = 3; + const double px = 11.32226290810711, py = 1.3807637692813548, pz = 1.3807637692813548; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 16.0*6*Vtip*Vtip*Vtip/pow(pi,4.0); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dx)*(dx)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][0] += 1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + } + } + } + } + } + // ===== ball mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Vtip = 1.5; + const double sigma = 0.35; + const double startT = 3; + const double px = 16.293012477519987, py = 1.3807637692813548, pz = 1.3807637692813548; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 16.0*6*Vtip*Vtip*Vtip/pow(pi,4.0); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dx)*(dx)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][0] += 1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + } + } + } + } + } + // ===== ball mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Vtip = 1.5; + const double sigma = 0.35; + const double startT = 3; + const double px = 21.263762046932865, py = 1.3807637692813548, pz = 1.3807637692813548; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 16.0*6*Vtip*Vtip*Vtip/pow(pi,4.0); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dx)*(dx)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][0] += 1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + } + } + } + } + } + // ===== ball mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Vtip = 1.5; + const double sigma = 0.35; + const double startT = 3; + const double px = 16.293012477519987, py = 1.3807637692813548, pz = 12.426873923532193; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 16.0*6*Vtip*Vtip*Vtip/pow(pi,4.0); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dx)*(dx)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][0] += -1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + } + } + } + } + } + #}; +}; diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/g b/tutorial_cases/loop_reactor_mixing_swirl/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars b/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars new file mode 100644 index 00000000..c0dce472 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 0.4; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA 15.8621; +liqVol 608.198; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars_temp b/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars_temp new file mode 100644 index 00000000..dfddd649 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/globalVars_temp @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 0.4; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA ; +liqVol ; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.gas b/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.gas new file mode 100644 index 00000000..ca916714 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; +RAS +{ + model mixtureKEpsilon; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.liquid b/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.liquid new file mode 100644 index 00000000..2063de0d --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model mixtureKEpsilon; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_constantd b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_constantd new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_pbe b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_pbe new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/phaseProperties_pbe @@ -0,0 +1,295 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangePopulationBalanceMultiphaseSystem; + +phases (gas liquid); + +populationBalances (bubbles); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel velocityGroup; + + velocityGroupCoeffs + { + populationBalance bubbles; + + shapeModel spherical; + + sizeGroups + ( + f1 {dSph 1.4e-3; value 0.0;} + f2 {dSph 1.8e-3; value 0.0;} + f3 {dSph 2.2e-3; value 0.0;} + f4 {dSph 2.6e-3; value 0.0;} + f5 {dSph 3e-3; value 1.0;} + f6 {dSph 3.4e-3; value 0.0;} + f7 {dSph 3.8e-3; value 0.0;} + f8 {dSph 4.2e-3; value 0.0;} + f9 {dSph 4.6e-3; value 0.0;} + f10 {dSph 5.0e-3; value 0.0;} + ); + } + + residualAlpha 1e-6; + + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + ( + LehrMilliesMewes{ + efficiency 4.695; + uCrit 0.08; + alphaMax 0.6; + } + ); + + binaryBreakupModels + (); + + breakupModels + ( + Laakkonen { + efficiency 13.83; + daughterSizeDistributionModel Laakkonen; + } + + ); + + driftModels + ( + densityChange{} + ); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas b/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..11b1c4b9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas @@ -0,0 +1,142 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + H2 + CO2 + N2 +); + +defaultSpecie N2; + +CO2 +{ + specie + { + molWeight 44.00995; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.85746029 0.00441437026 -2.21481404e-06 5.23490188e-10 -4.72084164e-14 -48759.166 2.27163806 ); + lowCpCoeffs ( 2.35677352 0.00898459677 -7.12356269e-06 2.45919022e-09 -1.43699548e-13 -48371.9697 9.90105222 ); + } + transport + { + As 1.572e-06; + Ts 240; + } + elements + { + C 1; + O 2; + } +} + +water +{ + specie + { + molWeight 18.01534; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.03399249 0.00217691804 -1.64072518e-07 -9.7041987e-11 1.68200992e-14 -30004.2971 4.9667701 ); + lowCpCoeffs ( 4.19864056 -0.0020364341 6.52040211e-06 -5.48797062e-09 1.77197817e-12 -30293.7267 -0.849032208 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + H 2; + O 1; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.3372792 -4.94024731e-05 4.99456778e-07 -1.79566394e-10 2.00255376e-14 -950.158922 -3.20502331 ); + lowCpCoeffs ( 2.34433112 0.00798052075 -1.9478151e-05 2.01572094e-08 -7.37611761e-12 -917.935173 0.683010238 ); + } + transport + { + As 6.362e-07; + Ts 72; + } + elements + { + H 2; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid b/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..d324ec51 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid @@ -0,0 +1,108 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + CO2 + water + H2 +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +CO2 +{ + specie + { + molWeight 44.00995; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrCO2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07;//-9402451; + } + transport + { + mu $muMixLiq; + Pr $PrH2; + } +} + + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/get_qoi.py b/tutorial_cases/loop_reactor_mixing_swirl/get_qoi.py new file mode 100644 index 00000000..7f3897ed --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/get_qoi.py @@ -0,0 +1,199 @@ +import json +import os +import pickle as pkl + +import matplotlib as mpl +import numpy as np +from prettyPlot.plotting import * +from scipy.optimize import curve_fit + + +def get_sim_folds(path): + folds = os.listdir(path) + sim_folds = [] + for fold in folds: + if fold.startswith("loop"): + sim_folds.append(fold) + return sim_folds + + +def func(t, cstar, kla): + t = t + t0 = 0 + c0 = 0 + return (cstar - c0) * (1 - np.exp(-kla * (t - t0))) + c0 + + +def get_vl(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("liqVol"): + vol = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read liqVol = {vol}m3") + return vol + + +def get_vvm(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("VVM"): + vvm = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read VVM = {vvm} [-]") + return vvm + + +def get_As(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("inletA"): + As = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read As = {As}m2") + return As + + +def get_pmix(verb=False): + with open("system/mixers.json", "r+") as f: + data = json.load(f) + mixer_list = data["mixers"] + pmix = 0 + for mix in mixer_list: + pmix += mix["power"] / 1000 + if verb: + print(f"Read Mixing power = {pmix}kW") + return pmix + + +def get_lh(verb=False): + filename = os.path.join("system", "setFieldsDict") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if "box (-1.0 -1.0 -1.0)" in line: + height = float(line.split("(")[2].split()[1]) + break + if verb: + print(f"Read Height = {height}m") + return height + + +def get_pinj(vvm, Vl, As, lh): + rhog = 1.25 # kg /m3 + Vg = Vl * vvm / (60 * As * 1) # m/s + Ptank = 101325 # Pa + # Ptank = 0 # Pa + rhoL = 1000 # kg / m3 + Pl = 101325 + rhoL * 9.8 * lh # Pa + # W + P1 = rhog * As * Vg**3 + # W + P2 = (Pl - Ptank) * As * Vg + # kg /s + MF = rhog * Vg * As + # kwh / kg + e_m = (P1 + P2) / (3600 * 1000 * MF) + + # returns kW + return (P1 + P2) * 1e-3 + + +def get_qoi(kla_co2, cs_co2, kla_h2, cs_h2, verb=False): + vvm = get_vvm(verb) + As = get_As(verb) + V_l = get_vl(verb) + liqh = get_lh(verb) + P_inj = get_pinj(vvm, V_l, As, liqh) + P_mix = get_pmix(verb) + + qoi_kla_co2 = kla_co2 * cs_co2 * V_l * 0.04401 + qoi_kla_h2 = kla_h2 * cs_h2 * V_l * 0.002016 + + qoi_co2 = qoi_kla_co2 / (P_mix / 3600 + P_inj / 3600) + qoi_h2 = qoi_kla_h2 / (P_mix / 3600 + P_inj / 3600) + return qoi_co2 * qoi_h2, qoi_kla_co2 * qoi_kla_h2 + + +def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): + qoi = [] + qoi_kla = [] + for i in range(len(kla_co2)): + if i == 0: + verb = True + else: + verb = False + qoi_tmp, qoi_kla_tmp = get_qoi( + kla_co2[i], cs_co2[i], kla_h2[i], cs_h2[i], verb + ) + qoi.append(qoi_tmp) + qoi_kla.append(qoi_kla_tmp) + qoi = np.array(qoi) + qoi_kla = np.array(qoi_kla) + return np.mean(qoi), np.std(qoi), np.mean(qoi_kla), np.std(qoi_kla) + + +os.makedirs("Figures", exist_ok=True) + +dataFolder = "data" +fold = "local" + +nuq = 100 +# mean_cstar_co2 = np.random.uniform(12.6, 13.3, nuq) +# mean_cstar_h2 = np.random.uniform(0.902, 0.96, nuq) +mean_cstar_co2 = np.random.uniform(14, 16.9, nuq) +mean_cstar_h2 = np.random.uniform(1.04, 1.19, nuq) + + +tmp_cs_h2 = [] +tmp_cs_co2 = [] +tmp_kla_h2 = [] +tmp_kla_co2 = [] +cs_co2 = mean_cstar_co2 +cs_h2 = mean_cstar_h2 + +a = np.load(os.path.join(dataFolder, fold, "conv.npz")) +endindex = -1 +if ( + "c_h2" in a + and "c_co2" in a + and len(a["time"][:endindex] > 0) + and (a["time"][:endindex][-1] > 95) +): + for i in range(nuq): + fitparamsH2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_h2"][:endindex]), + bounds=[(cs_h2[i] - 1e-6, 0), (cs_h2[i] + 1e-6, 1)], + ) + fitparamsCO2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_co2"][:endindex]), + bounds=[(cs_co2[i] - 1e-6, 0), (cs_co2[i] + 1e-6, 1)], + ) + tmp_kla_co2.append(fitparamsCO2[1]) + tmp_kla_h2.append(fitparamsH2[1]) + tmp_cs_h2.append(cs_h2[i]) + tmp_cs_co2.append(cs_co2[i]) + +qoi_m, qoi_s, qoi_kla_m, qoi_kla_s = get_qoi_uq( + tmp_kla_co2, tmp_cs_co2, tmp_kla_h2, tmp_cs_h2 +) + + +with open("qoi.txt", "w+") as f: + f.write(f"{qoi_m},{qoi_s}\n") + +with open("qoi_kla.txt", "w+") as f: + f.write(f"{qoi_kla_m},{qoi_kla_s}\n") diff --git a/tutorial_cases/loop_reactor_mixing_swirl/presteps.sh b/tutorial_cases/loop_reactor_mixing_swirl/presteps.sh new file mode 100644 index 00000000..bfcff75f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/presteps.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Clean case +module load conda +conda activate /projects/gas2fuels/conda_env/bird +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +# Define what to do on error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +# Generate blockmeshDict +python /projects/gas2fuels/BioReactorDesign/applications/write_block_rect_mesh.py -i system/mesh.json -o system +#python ../../../applications/write_block_rect_mesh.py -i system/mesh.json -o system + +# Generate boundary stl +python /projects/gas2fuels/BioReactorDesign/applications/write_stl_patch.py -i system/inlets_outlets.json +#python ../../../applications/write_stl_patch.py -i system/inlets_outlets.json + +# Generate mixers +python /projects/gas2fuels/BioReactorDesign/applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant +#python ../../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant + +# Generate species thermo properties +python /projects/gas2fuels/BioReactorDesign//applications/write_species_thermo_prop.py -cf . + +echo PRESTEP 2 +# Mesh gen +blockMesh -dict system/blockMeshDict + +# Inlet BC +surfaceToPatch -tol 1e-3 inlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/inlets\.stl/inlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + +# Outlet BC +surfaceToPatch -tol 1e-3 outlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/outlets\.stl/outlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + + +# Scale +transformPoints "scale=(2.7615275385627096 2.7615275385627096 2.7615275385627096)" + + +# setup IC +cp -r 0.orig 0 +setFields + +# Setup mass flow rate +# Get inlet area +postProcess -func 'patchIntegrate(patch="inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_pbe constant/phaseProperties + +conda deactivate + +if [ -f qoi.txt ]; then + rm qoi.txt +fi +if [ -f data/local/conv.npz ]; then + rm data/local/conv.npz +fi + diff --git a/tutorial_cases/loop_reactor_mixing_swirl/read_history.py b/tutorial_cases/loop_reactor_mixing_swirl/read_history.py new file mode 100644 index 00000000..c27eae94 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/read_history.py @@ -0,0 +1,104 @@ +import argparse +import os +import sys + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.postprocess.post_quantities import * +from bird.utilities.ofio import * + +parser = argparse.ArgumentParser(description="Convergence of GH") +parser.add_argument( + "-cn", + "--case_name", + type=str, + metavar="", + required=True, + help="Case name", +) +parser.add_argument( + "-df", + "--data_folder", + type=str, + metavar="", + required=False, + help="data folder name", + default="data", +) + +args, unknown = parser.parse_known_args() + + +case_root = "." # "../" +case_name = args.case_name # "12_hole_sparger_snappyRefine_700rpm_opt_coeff" +case_path = "." +dataFolder = args.data_folder + +if os.path.isfile(os.path.join(dataFolder, case_name, "conv.npz")): + sys.exit("WARNING: History already created, Skipping") + +time_float_sorted, time_str_sorted = get_case_times( + case_path, remove_zero=True +) +cell_centers, _ = read_cell_centers(".") +nCells = len(cell_centers) + + +co2_history = np.zeros(len(time_str_sorted)) +c_co2_history = np.zeros(len(time_str_sorted)) +h2_history = np.zeros(len(time_str_sorted)) +c_h2_history = np.zeros(len(time_str_sorted)) +gh_history = np.zeros(len(time_str_sorted)) +liqvol_history = np.zeros(len(time_str_sorted)) +print(f"case_path = {case_path}") +field_dict = {} +for itime, time in enumerate(time_float_sorted): + time_folder = time_str_sorted[itime] + print(f"\tTime : {time_folder}") + if not field_dict == {}: + new_field_dict = {} + if "V" in field_dict: + new_field_dict["V"] = field_dict["V"] + field_dict = new_field_dict + gh_history[itime], field_dict = compute_gas_holdup( + case_path, + time_str_sorted[itime], + field_dict=field_dict, + ) + co2_history[itime], field_dict = compute_ave_y_liq( + case_path, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + h2_history[itime], field_dict = compute_ave_y_liq( + case_path, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + c_co2_history[itime], field_dict = compute_ave_conc_liq( + case_path, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + c_h2_history[itime], field_dict = compute_ave_conc_liq( + case_path, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + +os.makedirs(dataFolder, exist_ok=True) +os.makedirs(os.path.join(dataFolder, case_name), exist_ok=True) +np.savez( + os.path.join(dataFolder, case_name, "conv.npz"), + time=np.array(time_float_sorted), + gh=gh_history, + co2=co2_history, + h2=h2_history, + c_h2=c_h2_history, + c_co2=c_co2_history, +) diff --git a/tutorial_cases/loop_reactor_mixing_swirl/run.sh b/tutorial_cases/loop_reactor_mixing_swirl/run.sh new file mode 100644 index 00000000..25251599 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/run.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Clean case +#module load anaconda3/2023 +#conda activate /projects/gas2fuels/conda_env/bird +#source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +# Define what to do on error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +# Generate blockmeshDict +python ../../applications/write_block_rect_mesh.py -i system/mesh.json -o system + +# Generate boundary stl +python ../../applications/write_stl_patch.py -i system/inlets_outlets.json + +# Generate mixers +python ../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant + +# Generate species thermo properties +python ../../applications/write_species_thermo_prop.py -cf . + +echo PRESTEP 2 +# Mesh gen +blockMesh -dict system/blockMeshDict + +# Inlet BC +surfaceToPatch -tol 1e-3 inlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/inlets\.stl/inlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + +# Outlet BC +surfaceToPatch -tol 1e-3 outlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/outlets\.stl/outlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + + +# Scale +transformPoints "scale=(2.7615275385627096 2.7615275385627096 2.7615275385627096)" + + +# setup IC +cp -r 0.orig 0 +setFields + +# Setup mass flow rate +# Get inlet area +postProcess -func 'patchIntegrate(patch="inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_pbe constant/phaseProperties + +#conda deactivate + +echo RUN +birdmultiphaseEulerFoam diff --git a/tutorial_cases/loop_reactor_mixing_swirl/script b/tutorial_cases/loop_reactor_mixing_swirl/script new file mode 100755 index 00000000..efe675ff --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/script @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=07:59:00 +#SBATCH --account=co2snow + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes diff --git a/tutorial_cases/loop_reactor_mixing_swirl/script_post b/tutorial_cases/loop_reactor_mixing_swirl/script_post new file mode 100755 index 00000000..aabbc33e --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/script_post @@ -0,0 +1,10 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=00:59:00 +#SBATCH --account=co2snow + +bash computeQOI.sh diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/blockMeshDict b/tutorial_cases/loop_reactor_mixing_swirl/system/blockMeshDict new file mode 100644 index 00000000..0bb60950 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/blockMeshDict @@ -0,0 +1,1050 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1.0; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +vertices +( +( 0.0 0.0 0.0) +( 1.0 0.0 0.0) +( 2.0 0.0 0.0) +( 3.0 0.0 0.0) +( 4.0 0.0 0.0) +( 5.0 0.0 0.0) +( 6.0 0.0 0.0) +( 7.0 0.0 0.0) +( 8.0 0.0 0.0) +( 9.0 0.0 0.0) +( 10.0 0.0 0.0) +( 0.0 1.0 0.0) +( 1.0 1.0 0.0) +( 2.0 1.0 0.0) +( 3.0 1.0 0.0) +( 4.0 1.0 0.0) +( 5.0 1.0 0.0) +( 6.0 1.0 0.0) +( 7.0 1.0 0.0) +( 8.0 1.0 0.0) +( 9.0 1.0 0.0) +( 10.0 1.0 0.0) +( 0.0 2.0 0.0) +( 1.0 2.0 0.0) +( 2.0 2.0 0.0) +( 3.0 2.0 0.0) +( 4.0 2.0 0.0) +( 5.0 2.0 0.0) +( 6.0 2.0 0.0) +( 7.0 2.0 0.0) +( 8.0 2.0 0.0) +( 9.0 2.0 0.0) +( 10.0 2.0 0.0) +( 0.0 3.0 0.0) +( 1.0 3.0 0.0) +( 2.0 3.0 0.0) +( 3.0 3.0 0.0) +( 4.0 3.0 0.0) +( 5.0 3.0 0.0) +( 6.0 3.0 0.0) +( 7.0 3.0 0.0) +( 8.0 3.0 0.0) +( 9.0 3.0 0.0) +( 10.0 3.0 0.0) +( 0.0 4.0 0.0) +( 1.0 4.0 0.0) +( 2.0 4.0 0.0) +( 3.0 4.0 0.0) +( 4.0 4.0 0.0) +( 5.0 4.0 0.0) +( 6.0 4.0 0.0) +( 7.0 4.0 0.0) +( 8.0 4.0 0.0) +( 9.0 4.0 0.0) +( 10.0 4.0 0.0) +( 0.0 5.0 0.0) +( 1.0 5.0 0.0) +( 2.0 5.0 0.0) +( 3.0 5.0 0.0) +( 4.0 5.0 0.0) +( 5.0 5.0 0.0) +( 6.0 5.0 0.0) +( 7.0 5.0 0.0) +( 8.0 5.0 0.0) +( 9.0 5.0 0.0) +( 10.0 5.0 0.0) +( 0.0 6.0 0.0) +( 1.0 6.0 0.0) +( 2.0 6.0 0.0) +( 3.0 6.0 0.0) +( 4.0 6.0 0.0) +( 5.0 6.0 0.0) +( 6.0 6.0 0.0) +( 7.0 6.0 0.0) +( 8.0 6.0 0.0) +( 9.0 6.0 0.0) +( 10.0 6.0 0.0) +( 0.0 7.0 0.0) +( 1.0 7.0 0.0) +( 2.0 7.0 0.0) +( 3.0 7.0 0.0) +( 4.0 7.0 0.0) +( 5.0 7.0 0.0) +( 6.0 7.0 0.0) +( 7.0 7.0 0.0) +( 8.0 7.0 0.0) +( 9.0 7.0 0.0) +( 10.0 7.0 0.0) +( 0.0 8.0 0.0) +( 1.0 8.0 0.0) +( 2.0 8.0 0.0) +( 3.0 8.0 0.0) +( 4.0 8.0 0.0) +( 5.0 8.0 0.0) +( 6.0 8.0 0.0) +( 7.0 8.0 0.0) +( 8.0 8.0 0.0) +( 9.0 8.0 0.0) +( 10.0 8.0 0.0) +( 0.0 9.0 0.0) +( 1.0 9.0 0.0) +( 2.0 9.0 0.0) +( 3.0 9.0 0.0) +( 4.0 9.0 0.0) +( 5.0 9.0 0.0) +( 6.0 9.0 0.0) +( 7.0 9.0 0.0) +( 8.0 9.0 0.0) +( 9.0 9.0 0.0) +( 10.0 9.0 0.0) +( 0.0 10.0 0.0) +( 1.0 10.0 0.0) +( 2.0 10.0 0.0) +( 3.0 10.0 0.0) +( 4.0 10.0 0.0) +( 5.0 10.0 0.0) +( 6.0 10.0 0.0) +( 7.0 10.0 0.0) +( 8.0 10.0 0.0) +( 9.0 10.0 0.0) +( 10.0 10.0 0.0) +( 0.0 11.0 0.0) +( 1.0 11.0 0.0) +( 2.0 11.0 0.0) +( 3.0 11.0 0.0) +( 4.0 11.0 0.0) +( 5.0 11.0 0.0) +( 6.0 11.0 0.0) +( 7.0 11.0 0.0) +( 8.0 11.0 0.0) +( 9.0 11.0 0.0) +( 10.0 11.0 0.0) +( 0.0 0.0 1.0) +( 1.0 0.0 1.0) +( 2.0 0.0 1.0) +( 3.0 0.0 1.0) +( 4.0 0.0 1.0) +( 5.0 0.0 1.0) +( 6.0 0.0 1.0) +( 7.0 0.0 1.0) +( 8.0 0.0 1.0) +( 9.0 0.0 1.0) +( 10.0 0.0 1.0) +( 0.0 1.0 1.0) +( 1.0 1.0 1.0) +( 2.0 1.0 1.0) +( 3.0 1.0 1.0) +( 4.0 1.0 1.0) +( 5.0 1.0 1.0) +( 6.0 1.0 1.0) +( 7.0 1.0 1.0) +( 8.0 1.0 1.0) +( 9.0 1.0 1.0) +( 10.0 1.0 1.0) +( 0.0 2.0 1.0) +( 1.0 2.0 1.0) +( 2.0 2.0 1.0) +( 3.0 2.0 1.0) +( 4.0 2.0 1.0) +( 5.0 2.0 1.0) +( 6.0 2.0 1.0) +( 7.0 2.0 1.0) +( 8.0 2.0 1.0) +( 9.0 2.0 1.0) +( 10.0 2.0 1.0) +( 0.0 3.0 1.0) +( 1.0 3.0 1.0) +( 2.0 3.0 1.0) +( 3.0 3.0 1.0) +( 4.0 3.0 1.0) +( 5.0 3.0 1.0) +( 6.0 3.0 1.0) +( 7.0 3.0 1.0) +( 8.0 3.0 1.0) +( 9.0 3.0 1.0) +( 10.0 3.0 1.0) +( 0.0 4.0 1.0) +( 1.0 4.0 1.0) +( 2.0 4.0 1.0) +( 3.0 4.0 1.0) +( 4.0 4.0 1.0) +( 5.0 4.0 1.0) +( 6.0 4.0 1.0) +( 7.0 4.0 1.0) +( 8.0 4.0 1.0) +( 9.0 4.0 1.0) +( 10.0 4.0 1.0) +( 0.0 5.0 1.0) +( 1.0 5.0 1.0) +( 2.0 5.0 1.0) +( 3.0 5.0 1.0) +( 4.0 5.0 1.0) +( 5.0 5.0 1.0) +( 6.0 5.0 1.0) +( 7.0 5.0 1.0) +( 8.0 5.0 1.0) +( 9.0 5.0 1.0) +( 10.0 5.0 1.0) +( 0.0 6.0 1.0) +( 1.0 6.0 1.0) +( 2.0 6.0 1.0) +( 3.0 6.0 1.0) +( 4.0 6.0 1.0) +( 5.0 6.0 1.0) +( 6.0 6.0 1.0) +( 7.0 6.0 1.0) +( 8.0 6.0 1.0) +( 9.0 6.0 1.0) +( 10.0 6.0 1.0) +( 0.0 7.0 1.0) +( 1.0 7.0 1.0) +( 2.0 7.0 1.0) +( 3.0 7.0 1.0) +( 4.0 7.0 1.0) +( 5.0 7.0 1.0) +( 6.0 7.0 1.0) +( 7.0 7.0 1.0) +( 8.0 7.0 1.0) +( 9.0 7.0 1.0) +( 10.0 7.0 1.0) +( 0.0 8.0 1.0) +( 1.0 8.0 1.0) +( 2.0 8.0 1.0) +( 3.0 8.0 1.0) +( 4.0 8.0 1.0) +( 5.0 8.0 1.0) +( 6.0 8.0 1.0) +( 7.0 8.0 1.0) +( 8.0 8.0 1.0) +( 9.0 8.0 1.0) +( 10.0 8.0 1.0) +( 0.0 9.0 1.0) +( 1.0 9.0 1.0) +( 2.0 9.0 1.0) +( 3.0 9.0 1.0) +( 4.0 9.0 1.0) +( 5.0 9.0 1.0) +( 6.0 9.0 1.0) +( 7.0 9.0 1.0) +( 8.0 9.0 1.0) +( 9.0 9.0 1.0) +( 10.0 9.0 1.0) +( 0.0 10.0 1.0) +( 1.0 10.0 1.0) +( 2.0 10.0 1.0) +( 3.0 10.0 1.0) +( 4.0 10.0 1.0) +( 5.0 10.0 1.0) +( 6.0 10.0 1.0) +( 7.0 10.0 1.0) +( 8.0 10.0 1.0) +( 9.0 10.0 1.0) +( 10.0 10.0 1.0) +( 0.0 11.0 1.0) +( 1.0 11.0 1.0) +( 2.0 11.0 1.0) +( 3.0 11.0 1.0) +( 4.0 11.0 1.0) +( 5.0 11.0 1.0) +( 6.0 11.0 1.0) +( 7.0 11.0 1.0) +( 8.0 11.0 1.0) +( 9.0 11.0 1.0) +( 10.0 11.0 1.0) +( 0.0 0.0 2.0) +( 1.0 0.0 2.0) +( 2.0 0.0 2.0) +( 3.0 0.0 2.0) +( 4.0 0.0 2.0) +( 5.0 0.0 2.0) +( 6.0 0.0 2.0) +( 7.0 0.0 2.0) +( 8.0 0.0 2.0) +( 9.0 0.0 2.0) +( 10.0 0.0 2.0) +( 0.0 1.0 2.0) +( 1.0 1.0 2.0) +( 2.0 1.0 2.0) +( 3.0 1.0 2.0) +( 4.0 1.0 2.0) +( 5.0 1.0 2.0) +( 6.0 1.0 2.0) +( 7.0 1.0 2.0) +( 8.0 1.0 2.0) +( 9.0 1.0 2.0) +( 10.0 1.0 2.0) +( 0.0 2.0 2.0) +( 1.0 2.0 2.0) +( 2.0 2.0 2.0) +( 3.0 2.0 2.0) +( 4.0 2.0 2.0) +( 5.0 2.0 2.0) +( 6.0 2.0 2.0) +( 7.0 2.0 2.0) +( 8.0 2.0 2.0) +( 9.0 2.0 2.0) +( 10.0 2.0 2.0) +( 0.0 3.0 2.0) +( 1.0 3.0 2.0) +( 2.0 3.0 2.0) +( 3.0 3.0 2.0) +( 4.0 3.0 2.0) +( 5.0 3.0 2.0) +( 6.0 3.0 2.0) +( 7.0 3.0 2.0) +( 8.0 3.0 2.0) +( 9.0 3.0 2.0) +( 10.0 3.0 2.0) +( 0.0 4.0 2.0) +( 1.0 4.0 2.0) +( 2.0 4.0 2.0) +( 3.0 4.0 2.0) +( 4.0 4.0 2.0) +( 5.0 4.0 2.0) +( 6.0 4.0 2.0) +( 7.0 4.0 2.0) +( 8.0 4.0 2.0) +( 9.0 4.0 2.0) +( 10.0 4.0 2.0) +( 0.0 5.0 2.0) +( 1.0 5.0 2.0) +( 2.0 5.0 2.0) +( 3.0 5.0 2.0) +( 4.0 5.0 2.0) +( 5.0 5.0 2.0) +( 6.0 5.0 2.0) +( 7.0 5.0 2.0) +( 8.0 5.0 2.0) +( 9.0 5.0 2.0) +( 10.0 5.0 2.0) +( 0.0 6.0 2.0) +( 1.0 6.0 2.0) +( 2.0 6.0 2.0) +( 3.0 6.0 2.0) +( 4.0 6.0 2.0) +( 5.0 6.0 2.0) +( 6.0 6.0 2.0) +( 7.0 6.0 2.0) +( 8.0 6.0 2.0) +( 9.0 6.0 2.0) +( 10.0 6.0 2.0) +( 0.0 7.0 2.0) +( 1.0 7.0 2.0) +( 2.0 7.0 2.0) +( 3.0 7.0 2.0) +( 4.0 7.0 2.0) +( 5.0 7.0 2.0) +( 6.0 7.0 2.0) +( 7.0 7.0 2.0) +( 8.0 7.0 2.0) +( 9.0 7.0 2.0) +( 10.0 7.0 2.0) +( 0.0 8.0 2.0) +( 1.0 8.0 2.0) +( 2.0 8.0 2.0) +( 3.0 8.0 2.0) +( 4.0 8.0 2.0) +( 5.0 8.0 2.0) +( 6.0 8.0 2.0) +( 7.0 8.0 2.0) +( 8.0 8.0 2.0) +( 9.0 8.0 2.0) +( 10.0 8.0 2.0) +( 0.0 9.0 2.0) +( 1.0 9.0 2.0) +( 2.0 9.0 2.0) +( 3.0 9.0 2.0) +( 4.0 9.0 2.0) +( 5.0 9.0 2.0) +( 6.0 9.0 2.0) +( 7.0 9.0 2.0) +( 8.0 9.0 2.0) +( 9.0 9.0 2.0) +( 10.0 9.0 2.0) +( 0.0 10.0 2.0) +( 1.0 10.0 2.0) +( 2.0 10.0 2.0) +( 3.0 10.0 2.0) +( 4.0 10.0 2.0) +( 5.0 10.0 2.0) +( 6.0 10.0 2.0) +( 7.0 10.0 2.0) +( 8.0 10.0 2.0) +( 9.0 10.0 2.0) +( 10.0 10.0 2.0) +( 0.0 11.0 2.0) +( 1.0 11.0 2.0) +( 2.0 11.0 2.0) +( 3.0 11.0 2.0) +( 4.0 11.0 2.0) +( 5.0 11.0 2.0) +( 6.0 11.0 2.0) +( 7.0 11.0 2.0) +( 8.0 11.0 2.0) +( 9.0 11.0 2.0) +( 10.0 11.0 2.0) +( 0.0 0.0 3.0) +( 1.0 0.0 3.0) +( 2.0 0.0 3.0) +( 3.0 0.0 3.0) +( 4.0 0.0 3.0) +( 5.0 0.0 3.0) +( 6.0 0.0 3.0) +( 7.0 0.0 3.0) +( 8.0 0.0 3.0) +( 9.0 0.0 3.0) +( 10.0 0.0 3.0) +( 0.0 1.0 3.0) +( 1.0 1.0 3.0) +( 2.0 1.0 3.0) +( 3.0 1.0 3.0) +( 4.0 1.0 3.0) +( 5.0 1.0 3.0) +( 6.0 1.0 3.0) +( 7.0 1.0 3.0) +( 8.0 1.0 3.0) +( 9.0 1.0 3.0) +( 10.0 1.0 3.0) +( 0.0 2.0 3.0) +( 1.0 2.0 3.0) +( 2.0 2.0 3.0) +( 3.0 2.0 3.0) +( 4.0 2.0 3.0) +( 5.0 2.0 3.0) +( 6.0 2.0 3.0) +( 7.0 2.0 3.0) +( 8.0 2.0 3.0) +( 9.0 2.0 3.0) +( 10.0 2.0 3.0) +( 0.0 3.0 3.0) +( 1.0 3.0 3.0) +( 2.0 3.0 3.0) +( 3.0 3.0 3.0) +( 4.0 3.0 3.0) +( 5.0 3.0 3.0) +( 6.0 3.0 3.0) +( 7.0 3.0 3.0) +( 8.0 3.0 3.0) +( 9.0 3.0 3.0) +( 10.0 3.0 3.0) +( 0.0 4.0 3.0) +( 1.0 4.0 3.0) +( 2.0 4.0 3.0) +( 3.0 4.0 3.0) +( 4.0 4.0 3.0) +( 5.0 4.0 3.0) +( 6.0 4.0 3.0) +( 7.0 4.0 3.0) +( 8.0 4.0 3.0) +( 9.0 4.0 3.0) +( 10.0 4.0 3.0) +( 0.0 5.0 3.0) +( 1.0 5.0 3.0) +( 2.0 5.0 3.0) +( 3.0 5.0 3.0) +( 4.0 5.0 3.0) +( 5.0 5.0 3.0) +( 6.0 5.0 3.0) +( 7.0 5.0 3.0) +( 8.0 5.0 3.0) +( 9.0 5.0 3.0) +( 10.0 5.0 3.0) +( 0.0 6.0 3.0) +( 1.0 6.0 3.0) +( 2.0 6.0 3.0) +( 3.0 6.0 3.0) +( 4.0 6.0 3.0) +( 5.0 6.0 3.0) +( 6.0 6.0 3.0) +( 7.0 6.0 3.0) +( 8.0 6.0 3.0) +( 9.0 6.0 3.0) +( 10.0 6.0 3.0) +( 0.0 7.0 3.0) +( 1.0 7.0 3.0) +( 2.0 7.0 3.0) +( 3.0 7.0 3.0) +( 4.0 7.0 3.0) +( 5.0 7.0 3.0) +( 6.0 7.0 3.0) +( 7.0 7.0 3.0) +( 8.0 7.0 3.0) +( 9.0 7.0 3.0) +( 10.0 7.0 3.0) +( 0.0 8.0 3.0) +( 1.0 8.0 3.0) +( 2.0 8.0 3.0) +( 3.0 8.0 3.0) +( 4.0 8.0 3.0) +( 5.0 8.0 3.0) +( 6.0 8.0 3.0) +( 7.0 8.0 3.0) +( 8.0 8.0 3.0) +( 9.0 8.0 3.0) +( 10.0 8.0 3.0) +( 0.0 9.0 3.0) +( 1.0 9.0 3.0) +( 2.0 9.0 3.0) +( 3.0 9.0 3.0) +( 4.0 9.0 3.0) +( 5.0 9.0 3.0) +( 6.0 9.0 3.0) +( 7.0 9.0 3.0) +( 8.0 9.0 3.0) +( 9.0 9.0 3.0) +( 10.0 9.0 3.0) +( 0.0 10.0 3.0) +( 1.0 10.0 3.0) +( 2.0 10.0 3.0) +( 3.0 10.0 3.0) +( 4.0 10.0 3.0) +( 5.0 10.0 3.0) +( 6.0 10.0 3.0) +( 7.0 10.0 3.0) +( 8.0 10.0 3.0) +( 9.0 10.0 3.0) +( 10.0 10.0 3.0) +( 0.0 11.0 3.0) +( 1.0 11.0 3.0) +( 2.0 11.0 3.0) +( 3.0 11.0 3.0) +( 4.0 11.0 3.0) +( 5.0 11.0 3.0) +( 6.0 11.0 3.0) +( 7.0 11.0 3.0) +( 8.0 11.0 3.0) +( 9.0 11.0 3.0) +( 10.0 11.0 3.0) +( 0.0 0.0 4.0) +( 1.0 0.0 4.0) +( 2.0 0.0 4.0) +( 3.0 0.0 4.0) +( 4.0 0.0 4.0) +( 5.0 0.0 4.0) +( 6.0 0.0 4.0) +( 7.0 0.0 4.0) +( 8.0 0.0 4.0) +( 9.0 0.0 4.0) +( 10.0 0.0 4.0) +( 0.0 1.0 4.0) +( 1.0 1.0 4.0) +( 2.0 1.0 4.0) +( 3.0 1.0 4.0) +( 4.0 1.0 4.0) +( 5.0 1.0 4.0) +( 6.0 1.0 4.0) +( 7.0 1.0 4.0) +( 8.0 1.0 4.0) +( 9.0 1.0 4.0) +( 10.0 1.0 4.0) +( 0.0 2.0 4.0) +( 1.0 2.0 4.0) +( 2.0 2.0 4.0) +( 3.0 2.0 4.0) +( 4.0 2.0 4.0) +( 5.0 2.0 4.0) +( 6.0 2.0 4.0) +( 7.0 2.0 4.0) +( 8.0 2.0 4.0) +( 9.0 2.0 4.0) +( 10.0 2.0 4.0) +( 0.0 3.0 4.0) +( 1.0 3.0 4.0) +( 2.0 3.0 4.0) +( 3.0 3.0 4.0) +( 4.0 3.0 4.0) +( 5.0 3.0 4.0) +( 6.0 3.0 4.0) +( 7.0 3.0 4.0) +( 8.0 3.0 4.0) +( 9.0 3.0 4.0) +( 10.0 3.0 4.0) +( 0.0 4.0 4.0) +( 1.0 4.0 4.0) +( 2.0 4.0 4.0) +( 3.0 4.0 4.0) +( 4.0 4.0 4.0) +( 5.0 4.0 4.0) +( 6.0 4.0 4.0) +( 7.0 4.0 4.0) +( 8.0 4.0 4.0) +( 9.0 4.0 4.0) +( 10.0 4.0 4.0) +( 0.0 5.0 4.0) +( 1.0 5.0 4.0) +( 2.0 5.0 4.0) +( 3.0 5.0 4.0) +( 4.0 5.0 4.0) +( 5.0 5.0 4.0) +( 6.0 5.0 4.0) +( 7.0 5.0 4.0) +( 8.0 5.0 4.0) +( 9.0 5.0 4.0) +( 10.0 5.0 4.0) +( 0.0 6.0 4.0) +( 1.0 6.0 4.0) +( 2.0 6.0 4.0) +( 3.0 6.0 4.0) +( 4.0 6.0 4.0) +( 5.0 6.0 4.0) +( 6.0 6.0 4.0) +( 7.0 6.0 4.0) +( 8.0 6.0 4.0) +( 9.0 6.0 4.0) +( 10.0 6.0 4.0) +( 0.0 7.0 4.0) +( 1.0 7.0 4.0) +( 2.0 7.0 4.0) +( 3.0 7.0 4.0) +( 4.0 7.0 4.0) +( 5.0 7.0 4.0) +( 6.0 7.0 4.0) +( 7.0 7.0 4.0) +( 8.0 7.0 4.0) +( 9.0 7.0 4.0) +( 10.0 7.0 4.0) +( 0.0 8.0 4.0) +( 1.0 8.0 4.0) +( 2.0 8.0 4.0) +( 3.0 8.0 4.0) +( 4.0 8.0 4.0) +( 5.0 8.0 4.0) +( 6.0 8.0 4.0) +( 7.0 8.0 4.0) +( 8.0 8.0 4.0) +( 9.0 8.0 4.0) +( 10.0 8.0 4.0) +( 0.0 9.0 4.0) +( 1.0 9.0 4.0) +( 2.0 9.0 4.0) +( 3.0 9.0 4.0) +( 4.0 9.0 4.0) +( 5.0 9.0 4.0) +( 6.0 9.0 4.0) +( 7.0 9.0 4.0) +( 8.0 9.0 4.0) +( 9.0 9.0 4.0) +( 10.0 9.0 4.0) +( 0.0 10.0 4.0) +( 1.0 10.0 4.0) +( 2.0 10.0 4.0) +( 3.0 10.0 4.0) +( 4.0 10.0 4.0) +( 5.0 10.0 4.0) +( 6.0 10.0 4.0) +( 7.0 10.0 4.0) +( 8.0 10.0 4.0) +( 9.0 10.0 4.0) +( 10.0 10.0 4.0) +( 0.0 11.0 4.0) +( 1.0 11.0 4.0) +( 2.0 11.0 4.0) +( 3.0 11.0 4.0) +( 4.0 11.0 4.0) +( 5.0 11.0 4.0) +( 6.0 11.0 4.0) +( 7.0 11.0 4.0) +( 8.0 11.0 4.0) +( 9.0 11.0 4.0) +( 10.0 11.0 4.0) +( 0.0 0.0 5.0) +( 1.0 0.0 5.0) +( 2.0 0.0 5.0) +( 3.0 0.0 5.0) +( 4.0 0.0 5.0) +( 5.0 0.0 5.0) +( 6.0 0.0 5.0) +( 7.0 0.0 5.0) +( 8.0 0.0 5.0) +( 9.0 0.0 5.0) +( 10.0 0.0 5.0) +( 0.0 1.0 5.0) +( 1.0 1.0 5.0) +( 2.0 1.0 5.0) +( 3.0 1.0 5.0) +( 4.0 1.0 5.0) +( 5.0 1.0 5.0) +( 6.0 1.0 5.0) +( 7.0 1.0 5.0) +( 8.0 1.0 5.0) +( 9.0 1.0 5.0) +( 10.0 1.0 5.0) +( 0.0 2.0 5.0) +( 1.0 2.0 5.0) +( 2.0 2.0 5.0) +( 3.0 2.0 5.0) +( 4.0 2.0 5.0) +( 5.0 2.0 5.0) +( 6.0 2.0 5.0) +( 7.0 2.0 5.0) +( 8.0 2.0 5.0) +( 9.0 2.0 5.0) +( 10.0 2.0 5.0) +( 0.0 3.0 5.0) +( 1.0 3.0 5.0) +( 2.0 3.0 5.0) +( 3.0 3.0 5.0) +( 4.0 3.0 5.0) +( 5.0 3.0 5.0) +( 6.0 3.0 5.0) +( 7.0 3.0 5.0) +( 8.0 3.0 5.0) +( 9.0 3.0 5.0) +( 10.0 3.0 5.0) +( 0.0 4.0 5.0) +( 1.0 4.0 5.0) +( 2.0 4.0 5.0) +( 3.0 4.0 5.0) +( 4.0 4.0 5.0) +( 5.0 4.0 5.0) +( 6.0 4.0 5.0) +( 7.0 4.0 5.0) +( 8.0 4.0 5.0) +( 9.0 4.0 5.0) +( 10.0 4.0 5.0) +( 0.0 5.0 5.0) +( 1.0 5.0 5.0) +( 2.0 5.0 5.0) +( 3.0 5.0 5.0) +( 4.0 5.0 5.0) +( 5.0 5.0 5.0) +( 6.0 5.0 5.0) +( 7.0 5.0 5.0) +( 8.0 5.0 5.0) +( 9.0 5.0 5.0) +( 10.0 5.0 5.0) +( 0.0 6.0 5.0) +( 1.0 6.0 5.0) +( 2.0 6.0 5.0) +( 3.0 6.0 5.0) +( 4.0 6.0 5.0) +( 5.0 6.0 5.0) +( 6.0 6.0 5.0) +( 7.0 6.0 5.0) +( 8.0 6.0 5.0) +( 9.0 6.0 5.0) +( 10.0 6.0 5.0) +( 0.0 7.0 5.0) +( 1.0 7.0 5.0) +( 2.0 7.0 5.0) +( 3.0 7.0 5.0) +( 4.0 7.0 5.0) +( 5.0 7.0 5.0) +( 6.0 7.0 5.0) +( 7.0 7.0 5.0) +( 8.0 7.0 5.0) +( 9.0 7.0 5.0) +( 10.0 7.0 5.0) +( 0.0 8.0 5.0) +( 1.0 8.0 5.0) +( 2.0 8.0 5.0) +( 3.0 8.0 5.0) +( 4.0 8.0 5.0) +( 5.0 8.0 5.0) +( 6.0 8.0 5.0) +( 7.0 8.0 5.0) +( 8.0 8.0 5.0) +( 9.0 8.0 5.0) +( 10.0 8.0 5.0) +( 0.0 9.0 5.0) +( 1.0 9.0 5.0) +( 2.0 9.0 5.0) +( 3.0 9.0 5.0) +( 4.0 9.0 5.0) +( 5.0 9.0 5.0) +( 6.0 9.0 5.0) +( 7.0 9.0 5.0) +( 8.0 9.0 5.0) +( 9.0 9.0 5.0) +( 10.0 9.0 5.0) +( 0.0 10.0 5.0) +( 1.0 10.0 5.0) +( 2.0 10.0 5.0) +( 3.0 10.0 5.0) +( 4.0 10.0 5.0) +( 5.0 10.0 5.0) +( 6.0 10.0 5.0) +( 7.0 10.0 5.0) +( 8.0 10.0 5.0) +( 9.0 10.0 5.0) +( 10.0 10.0 5.0) +( 0.0 11.0 5.0) +( 1.0 11.0 5.0) +( 2.0 11.0 5.0) +( 3.0 11.0 5.0) +( 4.0 11.0 5.0) +( 5.0 11.0 5.0) +( 6.0 11.0 5.0) +( 7.0 11.0 5.0) +( 8.0 11.0 5.0) +( 9.0 11.0 5.0) +( 10.0 11.0 5.0) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +blocks +( + + //block 0 +hex (0 1 12 11 132 133 144 143 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 1 +hex (1 2 13 12 133 134 145 144 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 2 +hex (2 3 14 13 134 135 146 145 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 3 +hex (3 4 15 14 135 136 147 146 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 4 +hex (4 5 16 15 136 137 148 147 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 5 +hex (5 6 17 16 137 138 149 148 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 6 +hex (6 7 18 17 138 139 150 149 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 7 +hex (7 8 19 18 139 140 151 150 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 8 +hex (8 9 20 19 140 141 152 151 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 9 +hex (9 10 21 20 141 142 153 152 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 10 +hex (141 142 153 152 273 274 285 284 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 11 +hex (273 274 285 284 405 406 417 416 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 12 +hex (405 406 417 416 537 538 549 548 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 13 +hex (537 538 549 548 669 670 681 680 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 14 +hex (536 537 548 547 668 669 680 679 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 15 +hex (535 536 547 546 667 668 679 678 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 16 +hex (534 535 546 545 666 667 678 677 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 17 +hex (533 534 545 544 665 666 677 676 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 18 +hex (532 533 544 543 664 665 676 675 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 19 +hex (531 532 543 542 663 664 675 674 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 20 +hex (530 531 542 541 662 663 674 673 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 21 +hex (529 530 541 540 661 662 673 672 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 22 +hex (528 529 540 539 660 661 672 671 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 23 +hex (539 540 551 550 671 672 683 682 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 24 +hex (550 551 562 561 682 683 694 693 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 25 +hex (561 562 573 572 693 694 705 704 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 26 +hex (572 573 584 583 704 705 716 715 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 27 +hex (583 584 595 594 715 716 727 726 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 28 +hex (594 595 606 605 726 727 738 737 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 29 +hex (605 606 617 616 737 738 749 748 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 30 +hex (616 617 628 627 748 749 760 759 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 31 +hex (627 628 639 638 759 760 771 770 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 32 +hex (638 639 650 649 770 771 782 781 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 33 +hex (440 441 452 451 572 573 584 583 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 34 +hex (308 309 320 319 440 441 452 451 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 35 +hex (176 177 188 187 308 309 320 319 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 36 +hex (44 45 56 55 176 177 188 187 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 37 +hex (55 56 67 66 187 188 199 198 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 38 +hex (66 67 78 77 198 199 210 209 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 39 +hex (77 78 89 88 209 210 221 220 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 40 +hex (88 89 100 99 220 221 232 231 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 41 +hex (99 100 111 110 231 232 243 242 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 42 +hex (110 111 122 121 242 243 254 253 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 43 +hex (33 34 45 44 165 166 177 176 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 44 +hex (22 23 34 33 154 155 166 165 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 45 +hex (11 12 23 22 143 144 155 154 ) +( 10 10 10 ) +SimpleGrading (1 1 1) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +defaultPatch +{ type wall;} + +patches +( +); diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/controlDict b/tutorial_cases/loop_reactor_mixing_swirl/system/controlDict new file mode 100644 index 00000000..f4665ed8 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/controlDict @@ -0,0 +1,66 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt writeNow;//endTime; + +endTime 200; + +deltaT 0.0001; + +writeControl adjustableRunTime; + +writeInterval 2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.5; + +maxDeltaT 0.01; + + +functions +{ + + #includeFunc writeObjects(d.gas) + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) + #includeFunc writeObjects(thermo:mu.liquid) + #includeFunc writeObjects(thermo:mu.gas) + #includeFunc fieldAverage(U.air, U.water, alpha.air, p) +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/decomposeParDict b/tutorial_cases/loop_reactor_mixing_swirl/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/fvConstraints b/tutorial_cases/loop_reactor_mixing_swirl/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/fvSchemes b/tutorial_cases/loop_reactor_mixing_swirl/system/fvSchemes new file mode 100644 index 00000000..52e6e13a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/fvSchemes @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + limited cellLimited Gauss linear 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + "div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + "div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon)m\)" Gauss upwind; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default uncorrected; +} + +wallDist +{ + method Poisson; + nRequired true; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/fvSolution b/tutorial_cases/loop_reactor_mixing_swirl/system/fvSolution new file mode 100644 index 00000000..2e69fdfa --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/fvSolution @@ -0,0 +1,120 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 0; + minIter 1; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + minIter 0; + maxIter 3; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 0; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/inlets_outlets.json b/tutorial_cases/loop_reactor_mixing_swirl/system/inlets_outlets.json new file mode 100644 index 00000000..a083d47f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/inlets_outlets.json @@ -0,0 +1,177 @@ +{ + "Geometry": { + "OverallDomain": { + "x": { + "nblocks": 10, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "y": { + "nblocks": 11, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "z": { + "nblocks": 5, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + } + }, + "Fluids": [ + [ + [ + 0, + 0, + 0 + ], + [ + 9, + 0, + 0 + ] + ], + [ + [ + 9, + 0, + 0 + ], + [ + 9, + 0, + 4 + ] + ], + [ + [ + 9, + 0, + 4 + ], + [ + 0, + 0, + 4 + ] + ], + [ + [ + 0, + 1, + 4 + ], + [ + 0, + 4, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 10, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 4, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 10, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 1, + 0 + ] + ] + ] + }, + "inlets": [ + { + "branch_id": 0, + "type": "circle", + "frac_space": 0.2, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 1, + "type": "circle", + "frac_space": 0.2, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 1, + "type": "circle", + "frac_space": 0.8, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 2, + "type": "circle", + "frac_space": 0.8, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + } + ], + "outlets": [ + { + "branch_id": 6, + "type": "circle", + "frac_space": 1, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "top" + }, + { + "branch_id": 4, + "type": "circle", + "frac_space": 1, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "top" + } + ] +} \ No newline at end of file diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/mesh.json b/tutorial_cases/loop_reactor_mixing_swirl/system/mesh.json new file mode 100644 index 00000000..29841d7e --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/mesh.json @@ -0,0 +1,26 @@ +{ + "Meshing": { + "Blockwise": { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0}, + "y" : {"nblocks": 11, "size_per_block": 1.0}, + "z" : {"nblocks": 5, "size_per_block": 1.0} + }, + "Fluids": [ + [ [0,0,0], [9,0,0] ], + [ [9,0,0], [9,0,4] ], + [ [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4] ], + [ [0,4,4], [0,10,4] ], + [ [0,4,4], [0,4,0] ], + [ [0,4,0], [0,10,0] ], + [ [0,4,0], [0,1,0] ] + ] + } +} diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/mixers.json b/tutorial_cases/loop_reactor_mixing_swirl/system/mixers.json new file mode 100644 index 00000000..4c88041b --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/mixers.json @@ -0,0 +1,175 @@ +{ + "Meshing": { + "Blockwise": { + "x": 10, + "y": 10, + "z": 10 + } + }, + "Geometry": { + "OverallDomain": { + "x": { + "nblocks": 10, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "y": { + "nblocks": 11, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "z": { + "nblocks": 5, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + } + }, + "Fluids": [ + [ + [ + 0, + 0, + 0 + ], + [ + 9, + 0, + 0 + ] + ], + [ + [ + 9, + 0, + 0 + ], + [ + 9, + 0, + 4 + ] + ], + [ + [ + 9, + 0, + 4 + ], + [ + 0, + 0, + 4 + ] + ], + [ + [ + 0, + 1, + 4 + ], + [ + 0, + 4, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 10, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 4, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 10, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 1, + 0 + ] + ] + ] + }, + "mixers": [ + { + "branch_id": 0, + "frac_space": 0.4, + "start_time": 3, + "sign": "+", + "swirl_sign": "+", + "radius": 0.4, + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35 + }, + { + "branch_id": 0, + "frac_space": 0.6000000000000001, + "start_time": 3, + "sign": "+", + "swirl_sign": "+", + "radius": 0.4, + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35 + }, + { + "branch_id": 0, + "frac_space": 0.8, + "start_time": 3, + "sign": "+", + "swirl_sign": "+", + "radius": 0.4, + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35 + }, + { + "branch_id": 2, + "frac_space": 0.4, + "start_time": 3, + "sign": "-", + "swirl_sign": "+", + "radius": 0.4, + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35 + } + ], + "volumetric_source": "ball", + "power": "from_Np_Vtip", + "momentum_source": "axial_and_swirl" +} \ No newline at end of file diff --git a/tutorial_cases/loop_reactor_mixing_swirl/system/setFieldsDict b/tutorial_cases/loop_reactor_mixing_swirl/system/setFieldsDict new file mode 100644 index 00000000..89a797b9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/system/setFieldsDict @@ -0,0 +1,37 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (552.3 11.046 552.3); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_swirl/writeGlobalVars.py b/tutorial_cases/loop_reactor_mixing_swirl/writeGlobalVars.py new file mode 100644 index 00000000..e64d69e3 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_swirl/writeGlobalVars.py @@ -0,0 +1,42 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + if line.startswith("inletA"): + f.write(f"inletA\t{inletA:g};\n") + elif line.startswith("liqVol"): + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + V = getLiqVol() + writeGvars(A, V) diff --git a/tutorial_cases/runall.sh b/tutorial_cases/runall.sh index c58bc65f..894373a2 100644 --- a/tutorial_cases/runall.sh +++ b/tutorial_cases/runall.sh @@ -40,7 +40,11 @@ bash run.sh cd ../../ ## Run mixing loop reactor tutorial cd tutorial_cases/loop_reactor_mixing -bash run.sh +bash run.sh +cd ../../ +## Run mixing loop reactor with swirl tutorial +cd tutorial_cases/loop_reactor_mixing_swirl +bash run.sh cd ../../ ## Run airlift reactor tutorial cd tutorial_cases/airlift_40m From 69652eeff8db6cc7e2954c40d8ce25a36f9f1aa2 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 17:59:31 -0600 Subject: [PATCH 07/52] add actuator mixer test --- tests/preprocess/test_dynamic_mixer.py | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/tests/preprocess/test_dynamic_mixer.py b/tests/preprocess/test_dynamic_mixer.py index 335f7f81..4e105c15 100644 --- a/tests/preprocess/test_dynamic_mixer.py +++ b/tests/preprocess/test_dynamic_mixer.py @@ -4,6 +4,8 @@ import numpy as np +from bird.meshing.block_rect_mesh import from_block_rect_to_seg +from bird.preprocess.dynamic_mixer.mixer import ActuatorMixer from bird.preprocess.dynamic_mixer.mixing_fvModels import * from bird.utilities.parser import parse_json @@ -54,3 +56,110 @@ def test_loop_list(): # Output to temporary directory and delete when done with tempfile.TemporaryDirectory() as tmpdirname: write_fvModel(input_dict, output_folder=tmpdirname, force_sign=True) + + +def test_ActuatorMixer(): + geom = { + "OverallDomain": { + a: {"size_per_block": 1.0, "rescale": 2.76} + for a in ("x", "y", "z") + }, + "Fluids": [[[0, 0, 0], [9, 0, 0]]], + } + g = from_block_rect_to_seg(geom) + + # loop mode: radius is a fraction of the branch cross-section + m = ActuatorMixer() + m.update_from_loop_dict( + { + "branch_id": 0, + "frac_space": 0.4, + "radius": 0.4, + "sign": "+", + "swirl_sign": "+", + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35, + "start_time": 3, + }, + g, + ) + assert m.ready + assert m.normal_dir == 0 + assert abs(m.R - 0.4 * 2.76) < 1e-9 # frac * mean transverse block size + assert (m.Vtip, m.Np, m.sigma) == (1.5, 6, 0.35) + assert m.sign == "+" and m.swirl_sign == "+" + # position = segment start + frac*conn, block size = 2.76 + assert abs(m.x - (0.5 * 2.76 + 0.4 * 9 * 2.76)) < 1e-6 + assert abs(m.y - 0.5 * 2.76) < 1e-6 + + # explicit mode: radius is absolute + m2 = ActuatorMixer() + m2.update_from_expl_dict( + { + "x": 0.1, + "y": 0.2, + "z": 0.3, + "normal_dir": 1, + "radius": 0.05, + "sign": "-", + } + ) + assert m2.ready and abs(m2.R - 0.05) < 1e-12 and m2.normal_dir == 1 + + # missing sign leaves the mixer not ready + m3 = ActuatorMixer() + m3.update_from_expl_dict( + {"x": 0.1, "y": 0.2, "z": 0.3, "normal_dir": 1, "radius": 0.05} + ) + assert not m3.ready + + +def test_write_fvModel_ball(): + base = { + "Meshing": {"Blockwise": {"x": 10, "y": 10, "z": 10}}, + "Geometry": { + "OverallDomain": { + a: {"nblocks": 10, "size_per_block": 1.0, "rescale": 2.76} + for a in ("x", "y", "z") + }, + "Fluids": [[[0, 0, 0], [9, 0, 0]]], + }, + "volumetric_source": "ball", + "mixers": [ + { + "branch_id": 0, + "frac_space": 0.5, + "radius": 0.4, + "sign": "+", + "swirl_sign": "+", + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35, + "power": 3000, + "start_time": 1, + } + ], + } + + # swirl endpoint: from_Np_Vtip + axial_and_swirl + d = dict(base, power="from_Np_Vtip", momentum_source="axial_and_swirl") + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(d, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert "// ===== ball mixer =====" in txt + assert "dynamicMix_util" not in txt # Newton solve is inlined + assert "16.0*6" in txt and "pow(pi,4.0)" in txt # Np/Vtip drive + assert "Qsw" in txt # swirl torque present + # exact conservation: runtime-summed normalisers + assert "reduce(Sax, sumOp());" in txt + assert "reduce(Sth, sumOp());" in txt + assert "Tax/Sax" in txt and "Qsw/Sth" in txt + + # axial + from_P endpoint + d = dict(base, power="from_P", momentum_source="axial") + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(d, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert "4.0*3000/(rhoM*area)" in txt # P drive + assert "Qsw" not in txt and "Sth" not in txt # no swirl From 19eed37c1c33d2261a9bb86dc18e5af962cc74e8 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 18:53:32 -0600 Subject: [PATCH 08/52] actuator-disk power helper and mixer-model keys for case generation --- bird/preprocess/dynamic_mixer/mixer.py | 15 +++++++++++++++ bird/preprocess/json_gen/design_io.py | 11 ++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index 2a4ff555..fb4cec3a 100644 --- a/bird/preprocess/dynamic_mixer/mixer.py +++ b/bird/preprocess/dynamic_mixer/mixer.py @@ -1,6 +1,21 @@ +import math + from bird import logger +def actuator_disk_power( + Np: float, Vtip: float, R: float, rho: float = 1000.0 +) -> float: + """Power [W] drawn by a ``from_Np_Vtip`` actuator-disk mixer. + + ``P = Np * rho * Vtip**3 * D**2 / pi**3`` with ``D = 2R`` (see the ball + mixer derivation). Used at case-generation time to record the derived + power for the efficiency QoI. + """ + D = 2.0 * R + return Np * rho * Vtip**3 * D**2 / math.pi**3 + + class Mixer: def __init__(self): self.x = None diff --git a/bird/preprocess/json_gen/design_io.py b/bird/preprocess/json_gen/design_io.py index aaaa7a47..7846bbff 100644 --- a/bird/preprocess/json_gen/design_io.py +++ b/bird/preprocess/json_gen/design_io.py @@ -10,8 +10,17 @@ def generate_stl_patch(filename, bc_dict, geom_dict): json.dump(final_dict, f, indent=2) -def generate_dynamic_mixer(filename, mixers_list, geom_dict): +def generate_dynamic_mixer(filename, mixers_list, geom_dict, model=None): + """Write a mixers.json. + + :param model: optional dict of top-level model selectors written verbatim + (e.g. ``{"volumetric_source": "ball", "power": "from_Np_Vtip", + "momentum_source": "axial_and_swirl"}``). ``None`` keeps the legacy + pancake output. + """ final_dict = {} + if model is not None: + final_dict.update(model) final_dict["Meshing"] = geom_dict["Meshing"] final_dict["Geometry"] = geom_dict["Geometry"] final_dict["mixers"] = mixers_list From 699bb0a3e2734bf84cafaa18ea22a4953bab3b3f Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 19:00:19 -0600 Subject: [PATCH 09/52] improve design sweep gen --- bird/preprocess/json_gen/generate_designs.py | 254 ++++++++++++++++++- 1 file changed, 253 insertions(+), 1 deletion(-) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 862de36a..1bb011a3 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -5,7 +5,12 @@ import numpy as np -from bird import BIRD_CASE_DIR, logger +from bird import BIRD_CASE_DIR, BIRD_DIR, logger +from bird.meshing.block_rect_mesh import from_block_rect_to_seg +from bird.preprocess.dynamic_mixer.mixer import ( + ActuatorMixer, + actuator_disk_power, +) from bird.preprocess.json_gen.design_io import * @@ -581,3 +586,250 @@ def generate_single_scaledup_reactor_sparger_cases( case_folder=os.path.join(study_folder, sim_folder), constantD=constantD, ) + + +def overwrite_scale(case_folder, scale): + """Rewrite the ``transformPoints`` scale in presteps.sh to `scale`.""" + filename = os.path.join(case_folder, "presteps.sh") + with open(filename, "r+") as f: + lines = f.readlines() + with open(filename, "w+") as f: + for line in lines: + if line.strip().startswith("transformPoints"): + f.write(f'transformPoints "scale=({scale} {scale} {scale})"\n') + else: + f.write(line) + + +def overwrite_ncores(case_folder, n): + """Rewrite ``numberOfSubdomains`` in system/decomposeParDict to `n`.""" + filename = os.path.join(case_folder, "system", "decomposeParDict") + with open(filename, "r+") as f: + lines = f.readlines() + with open(filename, "w+") as f: + for line in lines: + if line.strip().startswith("numberOfSubdomains"): + f.write(f"numberOfSubdomains {n};\n") + else: + f.write(line) + + +def write_script_single( + case_folder, + account="gas2fuels", + cores=4, + solver="birdmultiphaseEulerFoam", +): + """Write a per-case SLURM script (``script_single``) running one case.""" + ofbashrc = ( + "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" + ) + with open(os.path.join(case_folder, "script_single"), "w+") as f: + f.write("#!/bin/bash\n") + f.write("#SBATCH --qos=high\n") + f.write("#SBATCH --job-name=lev_single\n") + f.write("#SBATCH --nodes=1\n") + f.write(f"#SBATCH --ntasks-per-node={cores}\n") + f.write("#SBATCH --time=07:59:00\n") + f.write(f"#SBATCH --account={account}\n\n") + f.write("bash presteps.sh\n") + f.write(f"source {ofbashrc}\n") + f.write("decomposePar -fileHandler collated\n") + f.write(f"srun -n {cores} {solver} -parallel -fileHandler collated\n") + f.write("reconstructPar -newTimes\n") + + +def write_pack_scripts( + study_folder, + sim_ids, + sims_per_node=26, + cores_per_sim=4, + account="gas2fuels", + solver="birdmultiphaseEulerFoam", +): + """Write node-packing scripts (Option A): pack_XXX bundles + submit_all.sh. + + Each bundle runs up to `sims_per_node` cases concurrently on one node, each + via ``srun --exclusive -n cores_per_sim`` (so `sims_per_node*cores_per_sim` + cores are used per node). + """ + ofbashrc = ( + "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" + ) + bundles = [ + sim_ids[i : i + sims_per_node] + for i in range(0, len(sim_ids), sims_per_node) + ] + pack_names = [] + for b, bundle in enumerate(bundles): + pack_name = f"pack_{b:03}" + pack_names.append(pack_name) + with open(os.path.join(study_folder, pack_name), "w+") as f: + f.write("#!/bin/bash\n") + f.write("#SBATCH --qos=high\n") + f.write(f"#SBATCH --job-name=lev_{pack_name}\n") + f.write("#SBATCH --nodes=1\n") + f.write("#SBATCH --exclusive\n") + f.write("#SBATCH --time=07:59:00\n") + f.write(f"#SBATCH --account={account}\n\n") + f.write(f"source {ofbashrc}\n\n") + f.write("run_sim () {\n") + f.write('\tcd "$1"\n') + f.write("\tbash presteps.sh > log.presteps 2>&1\n") + f.write( + "\tdecomposePar -fileHandler collated > log.decompose 2>&1\n" + ) + f.write( + f"\tsrun --exclusive -n {cores_per_sim} {solver} -parallel" + " -fileHandler collated > log.solve 2>&1\n" + ) + f.write("\treconstructPar -newTimes > log.reconstruct 2>&1\n") + f.write("\tcd ..\n") + f.write("}\n\n") + for sim_id in bundle: + f.write(f"run_sim {id2simfolder(sim_id)} &\n") + f.write("wait\n") + with open(os.path.join(study_folder, "submit_all.sh"), "w+") as f: + for pack_name in pack_names: + f.write(f"sbatch {pack_name}\n") + + +def generate_leveled_reactor_cases( + config_dict, + branchcom_spots, + scale, + n_sim, + study_folder, + mixer_params, + vvm=0.4, + constantD=True, + start_time=3, + template_folder="loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup", + account="gas2fuels", + cores_per_sim=4, + sims_per_node=26, +): + """Generate one scale level of the actuator-disk (ball) design sweep. + + One template drives every level; the level `scale` is applied both to the + mixers.json rescale (mixer positions) and to presteps.sh transformPoints. + Uses the first `n_sim` designs of `config_dict`, so ``Sim_i`` is the same + design at every level. `mixer_params` holds Np/Vtip/sigma/radius/swirl_sign. + """ + if not os.path.isabs(template_folder): + template_folder = os.path.join( + BIRD_DIR, "preprocess", "data_case_gen", template_folder + ) + geom_dict = make_default_geom_dict_from_file( + os.path.join(template_folder, "system", "mesh.json") + ) + # mesh.json has no rescale; force the level scale (matched by transformPoints) + for a in ("x", "y", "z"): + geom_dict["Geometry"]["OverallDomain"][a]["rescale"] = scale + seg_geom = from_block_rect_to_seg(geom_dict["Geometry"]) + model = { + "volumetric_source": "ball", + "power": "from_Np_Vtip", + "momentum_source": "axial_and_swirl", + } + + try: + shutil.rmtree(study_folder) + except FileNotFoundError: + pass + Path(study_folder).mkdir(parents=True, exist_ok=True) + + sim_ids = sorted(config_dict)[:n_sim] + for sim_id in sim_ids: + sim_folder = id2simfolder(sim_id) + case = os.path.join(study_folder, sim_folder) + shutil.copytree(template_folder, case) + + bc_dict = {"inlets": [], "outlets": []} + for br in (6, 4): + bc_dict["outlets"].append( + { + "branch_id": br, + "type": "circle", + "frac_space": 1, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "top", + } + ) + for branch in (0, 1, 2): + for iind in np.argwhere(config_dict[sim_id][branch] == 1)[:, 0]: + bc_dict["inlets"].append( + { + "branch_id": branch, + "type": "circle", + "frac_space": branchcom_spots[branch][iind], + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom", + } + ) + generate_stl_patch( + os.path.join(case, "system", "inlets_outlets.json"), + bc_dict, + geom_dict, + ) + + mix_list = [] + for branch in (0, 1, 2): + for iind in np.argwhere(config_dict[sim_id][branch] == 0)[:, 0]: + sign = "+" if branch == 0 else "-" + frac = branchcom_spots[branch][iind] + # derive this mixer's power from Np/Vtip and its (scaled) radius + probe = ActuatorMixer() + probe.update_from_loop_dict( + { + "branch_id": branch, + "frac_space": frac, + "radius": mixer_params["radius"], + }, + seg_geom, + ) + power = actuator_disk_power( + mixer_params["Np"], mixer_params["Vtip"], probe.R + ) + mix_list.append( + { + "branch_id": branch, + "frac_space": float(frac), + "start_time": start_time, + "sign": sign, + "swirl_sign": mixer_params["swirl_sign"], + "radius": mixer_params["radius"], + "Vtip": mixer_params["Vtip"], + "Np": mixer_params["Np"], + "sigma": mixer_params["sigma"], + "power": power, + } + ) + generate_dynamic_mixer( + os.path.join(case, "system", "mixers.json"), + mix_list, + geom_dict, + model=model, + ) + overwrite_vvm(case_folder=case, vvm=vvm) + overwrite_scale(case_folder=case, scale=scale) + overwrite_ncores(case_folder=case, n=cores_per_sim) + overwrite_bubble_size_model(case_folder=case, constantD=constantD) + write_script_single(case, account=account, cores=cores_per_sim) + + write_pack_scripts( + study_folder, + sim_ids, + sims_per_node=sims_per_node, + cores_per_sim=cores_per_sim, + account=account, + ) + write_prep(os.path.join(study_folder, "prep.sh"), n_sim) + save_config_dict(os.path.join(study_folder, "configs.pkl"), config_dict) + save_config_dict( + os.path.join(study_folder, "branchcom_spots.pkl"), branchcom_spots + ) From a5f9e89aed8e8e74b6a755a3699ed40518bb27bd Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 29 Jul 2026 19:17:30 -0600 Subject: [PATCH 10/52] adjust path --- .../presteps.sh | 3 ++- bird/preprocess/json_gen/generate_designs.py | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/presteps.sh b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/presteps.sh index 77fa6d6f..a3c05e46 100644 --- a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/presteps.sh +++ b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/presteps.sh @@ -1,6 +1,7 @@ # Clean case module load conda -conda activate /projects/gas2fuels/conda_env/bird_wf +#conda activate /projects/gas2fuels/conda_env/bird_wf +conda activate /projects/gas2fuels/conda_env/bird_mixer source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc ./Allclean diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 1bb011a3..df100b18 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -621,9 +621,7 @@ def write_script_single( solver="birdmultiphaseEulerFoam", ): """Write a per-case SLURM script (``script_single``) running one case.""" - ofbashrc = ( - "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" - ) + ofbashrc = "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" with open(os.path.join(case_folder, "script_single"), "w+") as f: f.write("#!/bin/bash\n") f.write("#SBATCH --qos=high\n") @@ -653,9 +651,7 @@ def write_pack_scripts( via ``srun --exclusive -n cores_per_sim`` (so `sims_per_node*cores_per_sim` cores are used per node). """ - ofbashrc = ( - "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" - ) + ofbashrc = "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" bundles = [ sim_ids[i : i + sims_per_node] for i in range(0, len(sim_ids), sims_per_node) From 0963bc173cb927c51bb84eb65e847db44c1fa907 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 30 Jul 2026 09:52:36 -0600 Subject: [PATCH 11/52] remove te default qos high option --- bird/preprocess/json_gen/generate_designs.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index df100b18..a73720a8 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -624,7 +624,6 @@ def write_script_single( ofbashrc = "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" with open(os.path.join(case_folder, "script_single"), "w+") as f: f.write("#!/bin/bash\n") - f.write("#SBATCH --qos=high\n") f.write("#SBATCH --job-name=lev_single\n") f.write("#SBATCH --nodes=1\n") f.write(f"#SBATCH --ntasks-per-node={cores}\n") @@ -637,6 +636,18 @@ def write_script_single( f.write("reconstructPar -newTimes\n") +def write_script_post_single(case_folder, account="gas2fuels"): + """Write a per-case post-processing SLURM script (``script_post_single``).""" + with open(os.path.join(case_folder, "script_post_single"), "w+") as f: + f.write("#!/bin/bash\n") + f.write("#SBATCH --job-name=lev_post\n") + f.write("#SBATCH --nodes=1\n") + f.write("#SBATCH --ntasks-per-node=1\n") + f.write("#SBATCH --time=00:59:00\n") + f.write(f"#SBATCH --account={account}\n\n") + f.write("bash computeQOI.sh\n") + + def write_pack_scripts( study_folder, sim_ids, @@ -662,7 +673,6 @@ def write_pack_scripts( pack_names.append(pack_name) with open(os.path.join(study_folder, pack_name), "w+") as f: f.write("#!/bin/bash\n") - f.write("#SBATCH --qos=high\n") f.write(f"#SBATCH --job-name=lev_{pack_name}\n") f.write("#SBATCH --nodes=1\n") f.write("#SBATCH --exclusive\n") @@ -816,6 +826,7 @@ def generate_leveled_reactor_cases( overwrite_ncores(case_folder=case, n=cores_per_sim) overwrite_bubble_size_model(case_folder=case, constantD=constantD) write_script_single(case, account=account, cores=cores_per_sim) + write_script_post_single(case, account=account) write_pack_scripts( study_folder, From 6f47fe0c98e9580fa85b11ce1ff2d04e424f4a16 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 30 Jul 2026 09:55:23 -0600 Subject: [PATCH 12/52] fix _readOFScal NameError, we have a public functions for that --- .../writeGlobalVars.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/writeGlobalVars.py b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/writeGlobalVars.py index 2b42b8e8..e64d69e3 100644 --- a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/writeGlobalVars.py +++ b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/writeGlobalVars.py @@ -31,11 +31,8 @@ def readInletArea(): def getLiqVol(): - cell_centers, _ = read_cell_centers(".") volume_field, _ = read_cell_volumes(".") - alpha_field = _readOFScal( - os.path.join("0", "alpha.liquid"), len(cell_centers) - )["field"] + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") return np.sum(volume_field * alpha_field) From b096c07ff4ca7427244e2c953cebfd72b66d4d28 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 31 Jul 2026 08:20:33 -0600 Subject: [PATCH 13/52] update template file with the right qoi --- .../computeQOI.sh | 4 +- .../get_qoi.py | 31 ++++-- bird/preprocess/json_gen/generate_designs.py | 103 +++++++++++++++++- 3 files changed, 121 insertions(+), 17 deletions(-) diff --git a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/computeQOI.sh b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/computeQOI.sh index 3756ed7f..800e45d4 100644 --- a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/computeQOI.sh +++ b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/computeQOI.sh @@ -2,8 +2,8 @@ if [ ! -f qoi.txt ]; then # Reconstruct if needed source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc reconstructPar -newTimes - module load anaconda3/2023 - conda activate /projects/gas2fuels/conda_env/bird + module load conda + conda activate /projects/gas2fuels/conda_env/bird_mixer/ python read_history.py -cr .. -cn local -df data python get_qoi.py conda deactivate diff --git a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/get_qoi.py b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/get_qoi.py index 83932c5b..aa9b4a0a 100644 --- a/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/get_qoi.py +++ b/bird/preprocess/data_case_gen/loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup/get_qoi.py @@ -89,7 +89,7 @@ def get_lh(verb=False): def get_pinj(vvm, Vl, As, lh): - rhog = 1.25 # kg /m3 + rhog = 0.593333 # kg /m3 Vg = Vl * vvm / (60 * As * 1) # m/s Ptank = 101325 # Pa # Ptank = 0 # Pa @@ -116,21 +116,30 @@ def get_qoi(kla_co2, cs_co2, kla_h2, cs_h2, verb=False): P_inj = get_pinj(vvm, V_l, As, liqh) P_mix = get_pmix(verb) - qoi_co2 = kla_co2 * cs_co2 * V_l * 0.04401 / (P_mix / 3600 + P_inj / 3600) - qoi_h2 = kla_h2 * cs_h2 * V_l * 0.002016 / (P_mix / 3600 + P_inj / 3600) - return qoi_co2 * qoi_h2 + qoi_kla_co2 = kla_co2 * cs_co2 * V_l * 0.04401 + qoi_kla_h2 = kla_h2 * cs_h2 * V_l * 0.002016 + + qoi_co2 = qoi_kla_co2 / (P_mix / 3600 + P_inj / 3600) + qoi_h2 = qoi_kla_h2 / (P_mix / 3600 + P_inj / 3600) + return qoi_co2 * qoi_h2, qoi_kla_co2 * qoi_kla_h2 def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): qoi = [] + qoi_kla = [] for i in range(len(kla_co2)): if i == 0: verb = True else: verb = False - qoi.append(get_qoi(kla_co2[i], cs_co2[i], kla_h2[i], cs_h2[i], verb)) + qoi_tmp, qoi_kla_tmp = get_qoi( + kla_co2[i], cs_co2[i], kla_h2[i], cs_h2[i], verb + ) + qoi.append(qoi_tmp) + qoi_kla.append(qoi_kla_tmp) qoi = np.array(qoi) - return np.mean(qoi), np.std(qoi) + qoi_kla = np.array(qoi_kla) + return np.mean(qoi), np.std(qoi), np.mean(qoi_kla), np.std(qoi_kla) os.makedirs("Figures", exist_ok=True) @@ -139,8 +148,8 @@ def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): fold = "local" nuq = 100 -mean_cstar_co2 = np.random.uniform(14, 16.9, nuq) -mean_cstar_h2 = np.random.uniform(1.04, 1.19, nuq) +mean_cstar_co2 = np.random.uniform(7.68, 8.22, nuq) +mean_cstar_h2 = np.random.uniform(0.516, 0.548, nuq) tmp_cs_h2 = [] @@ -176,8 +185,12 @@ def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): tmp_cs_h2.append(cs_h2[i]) tmp_cs_co2.append(cs_co2[i]) -qoi_m, qoi_s = get_qoi_uq(tmp_kla_co2, tmp_cs_co2, tmp_kla_h2, tmp_cs_h2) +qoi_m, qoi_s, qoi_kla_m, qoi_kla_s = get_qoi_uq( + tmp_kla_co2, tmp_cs_co2, tmp_kla_h2, tmp_cs_h2 +) with open("qoi.txt", "w+") as f: f.write(f"{qoi_m},{qoi_s}\n") +with open("qoi_kla.txt", "w+") as f: + f.write(f"{qoi_kla_m},{qoi_kla_s}\n") diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index a73720a8..57cbb5f3 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -601,6 +601,66 @@ def overwrite_scale(case_folder, scale): f.write(line) +# setFields liquid-init box upper corner in UNSCALED (per-block) units: y is the +# 4-block liquid fill height; x/z are made wide to cover the whole domain. +_SETFIELDS_BOX_UPPER = (200.0, 4.0, 200.0) + + +def overwrite_setfields_box(case_folder, scale): + """Rewrite the setFields liquid-init box to `scale` * ``_SETFIELDS_BOX_UPPER``. + + setFields runs after transformPoints, so the box lives in scaled + coordinates; the lower corner stays ``(-1 -1 -1)``. + """ + bx, by, bz = (v * scale for v in _SETFIELDS_BOX_UPPER) + filename = os.path.join(case_folder, "system", "setFieldsDict") + with open(filename, "r+") as f: + lines = f.readlines() + with open(filename, "w+") as f: + for line in lines: + if line.strip().startswith("box "): + indent = line[: len(line) - len(line.lstrip())] + f.write(f"{indent}box (-1.0 -1.0 -1.0) ({bx} {by} {bz});\n") + else: + f.write(line) + + +def overwrite_qoi_params(case_folder, rhog, cstar_co2, cstar_h2): + """Rewrite the per-level QoI parameters in get_qoi.py. + + These are hardcoded per dimension in get_qoi.py, so each level needs its + own values (the mixer power is NOT touched here -- get_qoi.py reads it from + mixers.json). + + :param rhog: gas density [kg/m3] used in the injection-power estimate. + :param cstar_co2: (low, high) uniform-prior bounds for the CO2 c*. + :param cstar_h2: (low, high) uniform-prior bounds for the H2 c*. + """ + co2_lo, co2_hi = cstar_co2 + h2_lo, h2_hi = cstar_h2 + filename = os.path.join(case_folder, "get_qoi.py") + with open(filename, "r+") as f: + lines = f.readlines() + with open(filename, "w+") as f: + for line in lines: + stripped = line.strip() + if stripped.startswith("rhog ="): + indent = line[: len(line) - len(line.lstrip())] + f.write(f"{indent}rhog = {rhog} # kg /m3\n") + elif stripped.startswith("mean_cstar_co2 ="): + f.write( + "mean_cstar_co2 = " + f"np.random.uniform({co2_lo}, {co2_hi}, nuq)\n" + ) + elif stripped.startswith("mean_cstar_h2 ="): + f.write( + "mean_cstar_h2 = " + f"np.random.uniform({h2_lo}, {h2_hi}, nuq)\n" + ) + else: + f.write(line) + + def overwrite_ncores(case_folder, n): """Rewrite ``numberOfSubdomains`` in system/decomposeParDict to `n`.""" filename = os.path.join(case_folder, "system", "decomposeParDict") @@ -648,6 +708,11 @@ def write_script_post_single(case_folder, account="gas2fuels"): f.write("bash computeQOI.sh\n") +def write_foam_stub(case_folder: str) -> None: + """Create an empty ``test.foam`` so ParaView can open the case.""" + open(os.path.join(case_folder, "test.foam"), "w").close() + + def write_pack_scripts( study_folder, sim_ids, @@ -710,17 +775,30 @@ def generate_leveled_reactor_cases( vvm=0.4, constantD=True, start_time=3, + rhog=None, + cstar_co2=None, + cstar_h2=None, template_folder="loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup", account="gas2fuels", - cores_per_sim=4, - sims_per_node=26, + cores_per_sim=16, + cores_per_node=128, ): """Generate one scale level of the actuator-disk (ball) design sweep. One template drives every level; the level `scale` is applied both to the mixers.json rescale (mixer positions) and to presteps.sh transformPoints. Uses the first `n_sim` designs of `config_dict`, so ``Sim_i`` is the same - design at every level. `mixer_params` holds Np/Vtip/sigma/radius/swirl_sign. + design at every level. `mixer_params` holds Np/Vtip/sigma/radius and the + per-branch `sign` and `swirl_sign` (each a dict keyed by branch_id), which + are written verbatim into each mixer entry of mixers.json. + + `rhog`, `cstar_co2` and `cstar_h2` are the per-level QoI parameters; when + given they are written into each case's get_qoi.py (see + :func:`overwrite_qoi_params`). Left as ``None`` the template get_qoi.py is + used unchanged. + + Each sim runs on `cores_per_sim` cores; the node-packing bundles fit + ``cores_per_node // cores_per_sim`` sims per node. """ if not os.path.isabs(template_folder): template_folder = os.path.join( @@ -786,7 +864,9 @@ def generate_leveled_reactor_cases( mix_list = [] for branch in (0, 1, 2): for iind in np.argwhere(config_dict[sim_id][branch] == 0)[:, 0]: - sign = "+" if branch == 0 else "-" + # sign / swirl_sign are per-branch (keyed by branch_id) so the + # axial push and swirl form one coherent loop circulation; the + # values live in mixer_params and are written to mixers.json. frac = branchcom_spots[branch][iind] # derive this mixer's power from Np/Vtip and its (scaled) radius probe = ActuatorMixer() @@ -806,8 +886,8 @@ def generate_leveled_reactor_cases( "branch_id": branch, "frac_space": float(frac), "start_time": start_time, - "sign": sign, - "swirl_sign": mixer_params["swirl_sign"], + "sign": mixer_params["sign"][branch], + "swirl_sign": mixer_params["swirl_sign"][branch], "radius": mixer_params["radius"], "Vtip": mixer_params["Vtip"], "Np": mixer_params["Np"], @@ -823,11 +903,22 @@ def generate_leveled_reactor_cases( ) overwrite_vvm(case_folder=case, vvm=vvm) overwrite_scale(case_folder=case, scale=scale) + overwrite_setfields_box(case_folder=case, scale=scale) + if rhog is not None and cstar_co2 is not None and cstar_h2 is not None: + overwrite_qoi_params( + case_folder=case, + rhog=rhog, + cstar_co2=cstar_co2, + cstar_h2=cstar_h2, + ) overwrite_ncores(case_folder=case, n=cores_per_sim) overwrite_bubble_size_model(case_folder=case, constantD=constantD) write_script_single(case, account=account, cores=cores_per_sim) write_script_post_single(case, account=account) + write_foam_stub(case) + # pack as many sims per node as the requested cores allow + sims_per_node = max(1, cores_per_node // cores_per_sim) write_pack_scripts( study_folder, sim_ids, From a15f682353f8831c0d79fd704069656ac0e44ce5 Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 15:29:29 -0600 Subject: [PATCH 14/52] add static mixer class --- bird/preprocess/dynamic_mixer/mixer.py | 103 +++++++++++++++++++++++++ tests/preprocess/test_static_mixer.py | 63 +++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 tests/preprocess/test_static_mixer.py diff --git a/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index fb4cec3a..92c99dd5 100644 --- a/bird/preprocess/dynamic_mixer/mixer.py +++ b/bird/preprocess/dynamic_mixer/mixer.py @@ -217,3 +217,106 @@ def check_status(self, blocks=None) -> None: if blocks is not None: logger.info(f"\tbranch = {blocks}") self.ready = True + + +class StaticMixer: + """Passive (unpowered) momentum-source mixer used by the ``ball`` source. + + Unlike :class:`ActuatorMixer`, no power is injected: the swirl is imposed as + an energy-neutral axial-to-azimuthal redirection and the axial drag is a pure + loss. The drive is a swirl number ``S`` and a loss coefficient ``K`` rather + than ``Np``/``Vtip``; ``sign`` is the mixer orientation (the source is + inactive when the inflow opposes it) and ``swirl_sign`` the rotation sense. + """ + + def __init__(self): + self.x = None + self.y = None + self.z = None + self.normal_dir = None + self.R = None # physical mixer radius [m] + self.S = 0.35 # swirl number [-] + self.K = 0.5 # loss coefficient [-] + self.sign = None # mixer orientation, "+" / "-" + self.swirl_sign = "+" # rotation sense, "+" / "-" + self.start_time = 1.0 + self.ready = False + + def _read_common(self, mixer_dict: dict) -> None: + """Read the per-mixer keys.""" + if "S" in mixer_dict: + self.S = mixer_dict["S"] + if "K" in mixer_dict: + self.K = mixer_dict["K"] + if "sign" in mixer_dict: + self.sign = mixer_dict["sign"] + if "swirl_sign" in mixer_dict: + self.swirl_sign = mixer_dict["swirl_sign"] + if "start_time" in mixer_dict: + self.start_time = mixer_dict["start_time"] + + def update_from_expl_dict(self, mixer_dict: dict) -> None: + """Populate from an explicit mixer dict (absolute position and radius).""" + if "x" in mixer_dict: + self.x = mixer_dict["x"] + if "y" in mixer_dict: + self.y = mixer_dict["y"] + if "z" in mixer_dict: + self.z = mixer_dict["z"] + if "normal_dir" in mixer_dict: + self.normal_dir = mixer_dict["normal_dir"] + if "radius" in mixer_dict: + # explicit mode: radius is absolute [m] + self.R = mixer_dict["radius"] + self._read_common(mixer_dict) + self.check_status() + + def update_from_loop_dict(self, mixer_dict: dict, geom_dict: dict) -> None: + """Populate from a loop mixer dict. + + :param mixer_dict: mixer entry with ``branch_id``, ``frac_space`` and, + optionally, ``radius`` as a fraction of the branch cross-section + (``0.5`` spans the whole tube). + :param geom_dict: output of ``from_block_rect_to_seg`` (``segments`` and + ``blocksize``). + """ + segment = geom_dict["segments"][mixer_dict["branch_id"]] + pos = segment["start"] + mixer_dict["frac_space"] * segment["conn"] + self.x = float(pos[0]) + self.y = float(pos[1]) + self.z = float(pos[2]) + self.normal_dir = segment["normal_dir"] + # radius is a fraction of the branch cross-section (as for the actuator + # mixer): R = frac * mean of the two block sizes transverse to the axis. + bx, by, bz = geom_dict["blocksize"] + transverse = {0: (by, bz), 1: (bx, bz), 2: (bx, by)}[self.normal_dir] + frac = mixer_dict.get("radius", 0.4) + self.R = frac * 0.5 * (transverse[0] + transverse[1]) + self._read_common(mixer_dict) + self.check_status(blocks=segment["blocks"]) + + def check_status(self, blocks=None) -> None: + """Log the resolved mixer and set ``ready`` if all fields are present.""" + if ( + self.x is None + or self.y is None + or self.z is None + or self.normal_dir is None + or self.R is None + or self.sign not in ("+", "-") + or self.swirl_sign not in ("+", "-") + ): + self.ready = False + else: + logger.info( + f"\n\tpos({self.x:.2g}, {self.y:.2g}, {self.z:.2g})" + + f"\n\tnormal_dir {self.normal_dir}" + + f"\n\tR {self.R:.2g}" + + f"\n\tS {self.S:.2g}" + + f"\n\tK {self.K:.2g}" + + f"\n\tsign {self.sign} swirl_sign {self.swirl_sign}" + + f"\n\tstart_time {self.start_time:.2g}" + ) + if blocks is not None: + logger.info(f"\tbranch = {blocks}") + self.ready = True diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py new file mode 100644 index 00000000..18fb37ab --- /dev/null +++ b/tests/preprocess/test_static_mixer.py @@ -0,0 +1,63 @@ +from bird.meshing.block_rect_mesh import from_block_rect_to_seg +from bird.preprocess.dynamic_mixer.mixer import StaticMixer + + +def test_StaticMixer(): + geom = { + "OverallDomain": { + a: {"size_per_block": 1.0, "rescale": 2.76} + for a in ("x", "y", "z") + }, + "Fluids": [[[0, 0, 0], [9, 0, 0]]], + } + g = from_block_rect_to_seg(geom) + + # loop mode: radius is a fraction of the branch cross-section + # (0.5 spans the whole tube) + m = StaticMixer() + m.update_from_loop_dict( + { + "branch_id": 0, + "frac_space": 0.4, + "radius": 0.5, + "sign": "+", + "swirl_sign": "+", + "S": 0.35, + "K": 0.5, + "start_time": 3, + }, + g, + ) + assert m.ready + assert m.normal_dir == 0 + assert abs(m.R - 0.5 * 2.76) < 1e-9 # frac * mean transverse block size + assert (m.S, m.K) == (0.35, 0.5) + assert m.sign == "+" and m.swirl_sign == "+" + assert m.start_time == 3 + # position = segment start + frac*conn, block size = 2.76 + assert abs(m.x - (0.5 * 2.76 + 0.4 * 9 * 2.76)) < 1e-6 + assert abs(m.y - 0.5 * 2.76) < 1e-6 + + # explicit mode: radius is absolute, defaults for S/K + m2 = StaticMixer() + m2.update_from_expl_dict( + { + "x": 0.1, + "y": 0.2, + "z": 0.3, + "normal_dir": 1, + "radius": 0.05, + "sign": "-", + "swirl_sign": "-", + } + ) + assert m2.ready and abs(m2.R - 0.05) < 1e-12 and m2.normal_dir == 1 + assert (m2.S, m2.K) == (0.35, 0.5) # defaults + assert m2.sign == "-" and m2.swirl_sign == "-" + + # missing sign leaves the mixer not ready + m3 = StaticMixer() + m3.update_from_expl_dict( + {"x": 0.1, "y": 0.2, "z": 0.3, "normal_dir": 1, "radius": 0.05} + ) + assert not m3.ready From fbdd061546c7145297fb24742a7ad01a9261dfca Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 15:36:30 -0600 Subject: [PATCH 15/52] add write_static_mixer_ball to the static mixer class --- bird/preprocess/dynamic_mixer/io_fvModels.py | 139 +++++++++++++++++++ tests/preprocess/test_static_mixer.py | 55 ++++++++ 2 files changed, 194 insertions(+) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index e2077c17..29f56be3 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -534,6 +534,145 @@ def write_mixer_ball( f.write("\t\t}\n") +def write_static_mixer_ball(mixer, output_folder): + """Append one passive ``ball`` static-mixer block to ``fvModels``. + + The swirl is imposed as an azimuthal body force proportional to the local + axial dynamic pressure (Kiesewetter), balanced cell-by-cell by an + energy-neutral axial reaction; a lumped axial drag adds the viscous loss. + The source is inactive when the inflow opposes the mixer orientation. + + :param mixer: a ready + :class:`~bird.preprocess.dynamic_mixer.mixer.StaticMixer`. + """ + nd = int(mixer.normal_dir) + dn = ["dx", "dy", "dz"][nd] + # theta_hat = n_hat x r_hat, per axis: (component index, numerator expr) + tan = { + 0: [(1, "-dz"), (2, "dy")], + 1: [(0, "dz"), (2, "-dx")], + 2: [(0, "-dy"), (1, "dx")], + }[nd] + push_ax = "1.0" if mixer.sign == "+" else "-1.0" + push_th = "1.0" if mixer.swirl_sign == "+" else "-1.0" + + with open(os.path.join(output_folder, "fvModels"), "a+") as f: + f.write("\t\t// ===== static mixer =====\n") + f.write("\t\t{\n") + f.write(f"\t\t\tconst double Rmix = {mixer.R};\n") + f.write("\t\t\tconst double area = pi*Rmix*Rmix;\n") + f.write(f"\t\t\tconst double Snum = {mixer.S};\n") + f.write(f"\t\t\tconst double Kloss = {mixer.K};\n") + f.write(f"\t\t\tconst double startT = {mixer.start_time};\n") + f.write( + f"\t\t\tconst double px = {mixer.x}, py = {mixer.y}, pz = {mixer.z};\n" + ) + f.write("\t\t\tif (time.value() > startT)\n") + f.write("\t\t\t{\n") + # --- sense V1 and rho over the upstream half-ball --- + # (duplicated from write_mixer_ball; the dynamic path is kept untouched) + f.write("\t\t\t\tscalar sV = 0.0, sVU = 0.0, sVrho = 0.0;\n") + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write(f"\t\t\t\t\tif (d2 <= Rmix*Rmix && {push_ax}*{dn} < 0.0)\n") + f.write("\t\t\t\t\t{\n") + f.write("\t\t\t\t\t\tconst double w = V[i]*alphaL[i];\n") + f.write( + f"\t\t\t\t\t\tsV += w; sVU += w*UL[i][{nd}]; sVrho += w*rhoL[i];\n" + ) + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t\treduce(sV, sumOp());\n") + f.write("\t\t\t\treduce(sVU, sumOp());\n") + f.write("\t\t\t\treduce(sVrho, sumOp());\n") + f.write( + f"\t\t\t\tdouble V1 = (sV>1e-30) ? {push_ax}*(sVU/sV) : 0.0;\n" + ) + f.write("\t\t\t\tif (V1 < 0.0) V1 = 0.0;\n") + f.write( + "\t\t\t\tconst double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0;\n" + ) + # --- passive loads (no Newton solve) --- + f.write("\t\t\t\tconst double Qsw = Snum*Rmix*rhoM*area*V1*V1;\n") + f.write("\t\t\t\tconst double Tls = 0.5*Kloss*rhoM*area*V1*V1;\n") + # --- pass 1: normalisation sums over the ball --- + f.write("\t\t\t\tscalar Sax = 0.0, Ssw = 0.0;\n") + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write("\t\t\t\t\tif (d2 <= Rmix*Rmix)\n") + f.write("\t\t\t\t\t{\n") + f.write( + "\t\t\t\t\t\tconst double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i]));\n" + ) + f.write("\t\t\t\t\t\tconst double g = std::exp(-d2/(epsi*epsi));\n") + f.write( + f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n" + ) + f.write(f"\t\t\t\t\t\tconst double ux = UL[i][{nd}];\n") + f.write("\t\t\t\t\t\tSax += alphaL[i]*g*V[i];\n") + f.write("\t\t\t\t\t\tSsw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i];\n") + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t\treduce(Sax, sumOp());\n") + f.write("\t\t\t\treduce(Ssw, sumOp());\n") + # --- pass 2: apply --- + f.write("\t\t\t\tforAll(C, i)\n") + f.write("\t\t\t\t{\n") + f.write( + "\t\t\t\t\tconst double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz;\n" + ) + f.write("\t\t\t\t\tconst double d2 = dx*dx + dy*dy + dz*dz;\n") + f.write("\t\t\t\t\tif (d2 <= Rmix*Rmix)\n") + f.write("\t\t\t\t\t{\n") + f.write( + "\t\t\t\t\t\tconst double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i]));\n" + ) + f.write("\t\t\t\t\t\tconst double g = std::exp(-d2/(epsi*epsi));\n") + # viscous drag (lumped): opposes the oriented inflow + f.write("\t\t\t\t\t\tif (Sax > 1e-30)\n") + f.write("\t\t\t\t\t\t{\n") + f.write("\t\t\t\t\t\t\tconst double fvisc = Tls/Sax*alphaL[i]*g;\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += -{push_ax}*fvisc*V[i];\n") + f.write("\t\t\t\t\t\t}\n") + # swirl + energy-neutral axial reaction (local, velocity-weighted) + f.write( + f"\t\t\t\t\t\tconst double rr = std::sqrt(d2-({dn})*({dn}));\n" + ) + f.write("\t\t\t\t\t\tif (rr > 1e-3*Rmix && Ssw > 1e-30)\n") + f.write("\t\t\t\t\t\t{\n") + f.write(f"\t\t\t\t\t\t\tconst double ux = UL[i][{nd}];\n") + f.write( + f"\t\t\t\t\t\t\tconst double uth = UL[i][{tan[0][0]}]*(({tan[0][1]})/rr) + UL[i][{tan[1][0]}]*(({tan[1][1]})/rr);\n" + ) + f.write("\t\t\t\t\t\t\tconst double A0 = Qsw/Ssw;\n") + f.write( + "\t\t\t\t\t\t\tconst double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g;\n" + ) + f.write( + f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] += {push_th}*fsw*V[i]*(({tan[0][1]})/rr);\n" + ) + f.write( + f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] += {push_th}*fsw*V[i]*(({tan[1][1]})/rr);\n" + ) + f.write( + "\t\t\t\t\t\t\tconst double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g;\n" + ) + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += -{push_th}*fcp*V[i];\n") + f.write("\t\t\t\t\t\t}\n") + f.write("\t\t\t\t\t}\n") + f.write("\t\t\t\t}\n") + f.write("\t\t\t}\n") + f.write("\t\t}\n") + + def write_end(output_folder): with open(os.path.join(output_folder, "fvModels"), "a+") as f: f.write("\t#};\n") diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py index 18fb37ab..cd63dbbb 100644 --- a/tests/preprocess/test_static_mixer.py +++ b/tests/preprocess/test_static_mixer.py @@ -1,4 +1,12 @@ +import tempfile +from pathlib import Path + from bird.meshing.block_rect_mesh import from_block_rect_to_seg +from bird.preprocess.dynamic_mixer.io_fvModels import ( + write_end, + write_preamble_ball, + write_static_mixer_ball, +) from bird.preprocess.dynamic_mixer.mixer import StaticMixer @@ -61,3 +69,50 @@ def test_StaticMixer(): {"x": 0.1, "y": 0.2, "z": 0.3, "normal_dir": 1, "radius": 0.05} ) assert not m3.ready + + +def test_write_static_mixer_ball(): + m = StaticMixer() + m.update_from_expl_dict( + { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "normal_dir": 1, + "radius": 0.05, + "sign": "+", + "swirl_sign": "+", + "S": 0.35, + "K": 0.5, + "start_time": 1, + } + ) + assert m.ready + + with tempfile.TemporaryDirectory() as tmpdirname: + write_preamble_ball(tmpdirname) + write_static_mixer_ball(m, tmpdirname) + write_end(tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + + assert "// ===== static mixer =====" in txt + assert "dynamicMix_util" not in txt # no external header + assert "V2" not in txt # passive: no Newton solve + # passive loads (no tip speed / power) + assert "const double Qsw = Snum*Rmix*rhoM*area*V1*V1;" in txt + assert "const double Tls = 0.5*Kloss*rhoM*area*V1*V1;" in txt + # activation gate inherited from the sensing block + assert "if (V1 < 0.0) V1 = 0.0;" in txt + # exact conservation: runtime-summed normalisers (velocity-weighted swirl) + assert "reduce(Sax, sumOp());" in txt + assert "reduce(Ssw, sumOp());" in txt + assert "Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i];" in txt + assert "const double A0 = Qsw/Ssw;" in txt + # energy-neutral axial reaction f_cp ~ rho*ux*uth + assert "const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g;" in txt + # normal_dir=1 -> theta_hat = (dz/rr, 0, -dx/rr); swirl on components 0 and 2 + assert "Usource[i][0] += 1.0*fsw*V[i]*((dz)/rr);" in txt + assert "Usource[i][2] += 1.0*fsw*V[i]*((-dx)/rr);" in txt + # axial reaction and viscous drag on the normal component (index 1) + assert "Usource[i][1] += -1.0*fcp*V[i];" in txt + assert "Usource[i][1] += -1.0*fvisc*V[i];" in txt From 37c330e7da7696ef581408112cfe050eca5096da Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 15:40:44 -0600 Subject: [PATCH 16/52] make sure we can mix static and dynamic mixers --- .../dynamic_mixer/mixing_fvModels.py | 44 +++++++++-- tests/preprocess/test_static_mixer.py | 73 +++++++++++++++++++ 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/bird/preprocess/dynamic_mixer/mixing_fvModels.py b/bird/preprocess/dynamic_mixer/mixing_fvModels.py index 1c23ca07..630f8ca7 100644 --- a/bird/preprocess/dynamic_mixer/mixing_fvModels.py +++ b/bird/preprocess/dynamic_mixer/mixing_fvModels.py @@ -1,12 +1,16 @@ from bird.meshing.block_rect_mesh import from_block_rect_to_seg from bird.preprocess.dynamic_mixer.io_fvModels import * -from bird.preprocess.dynamic_mixer.mixer import ActuatorMixer, Mixer +from bird.preprocess.dynamic_mixer.mixer import ( + ActuatorMixer, + Mixer, + StaticMixer, +) def check_input(input_dict): assert isinstance(input_dict, dict) mix_type = [] - for mix in input_dict["mixers"]: + for mix in input_dict.get("mixers", []): if "x" in mix: mix_type.append("expl") else: @@ -25,11 +29,25 @@ def check_input(input_dict): return mix_type +def check_static_input(input_dict): + """Return the expl/loop type of each entry in the ``static_mixers`` list.""" + static_mix_type = [] + for mix in input_dict.get("static_mixers", []): + static_mix_type.append("expl" if "x" in mix else "loop") + if "loop" in static_mix_type: + assert "Geometry" in input_dict + assert "OverallDomain" in input_dict["Geometry"] + assert "Fluids" in input_dict["Geometry"] + return static_mix_type + + def write_fvModel(input_dict, output_folder=".", force_sign=False): # Switch on the volumetric source: "ball" (new, exact-conservation # actuator-disk) vs "pancake" (legacy, default). The legacy path below is # left byte-for-byte unchanged. - if input_dict.get("volumetric_source", "pancake") == "ball": + if input_dict.get( + "volumetric_source", "pancake" + ) == "ball" or input_dict.get("static_mixers"): write_fvModel_ball(input_dict, output_folder=output_folder) return mix_type = check_input(input_dict) @@ -64,14 +82,18 @@ def write_fvModel_ball(input_dict, output_folder="."): Reads the top-level ``power`` (``from_P`` / ``from_Np_Vtip``) and ``momentum_source`` (``axial`` / ``axial_and_swirl``) modes; both default to - the new full model. Each mixer is an - :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`. + the new full model. Each dynamic mixer is an + :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`; each entry of the + optional ``static_mixers`` list is a + :class:`~bird.preprocess.dynamic_mixer.mixer.StaticMixer` appended to the same + codedSource. """ mix_type = check_input(input_dict) + static_mix_type = check_static_input(input_dict) power_mode = input_dict.get("power", "from_Np_Vtip") momentum_mode = input_dict.get("momentum_source", "axial_and_swirl") write_preamble_ball(output_folder) - if "loop" in mix_type: + if "loop" in mix_type or "loop" in static_mix_type: geom_dict = from_block_rect_to_seg(input_dict["Geometry"]) for imix, mtype in enumerate(mix_type): mixer = ActuatorMixer() @@ -81,4 +103,14 @@ def write_fvModel_ball(input_dict, output_folder="."): mixer.update_from_loop_dict(input_dict["mixers"][imix], geom_dict) if mixer.ready: write_mixer_ball(mixer, output_folder, power_mode, momentum_mode) + for imix, mtype in enumerate(static_mix_type): + mixer = StaticMixer() + if mtype == "expl": + mixer.update_from_expl_dict(input_dict["static_mixers"][imix]) + elif mtype == "loop": + mixer.update_from_loop_dict( + input_dict["static_mixers"][imix], geom_dict + ) + if mixer.ready: + write_static_mixer_ball(mixer, output_folder) write_end(output_folder) diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py index cd63dbbb..7d257c01 100644 --- a/tests/preprocess/test_static_mixer.py +++ b/tests/preprocess/test_static_mixer.py @@ -8,6 +8,7 @@ write_static_mixer_ball, ) from bird.preprocess.dynamic_mixer.mixer import StaticMixer +from bird.preprocess.dynamic_mixer.mixing_fvModels import write_fvModel def test_StaticMixer(): @@ -116,3 +117,75 @@ def test_write_static_mixer_ball(): # axial reaction and viscous drag on the normal component (index 1) assert "Usource[i][1] += -1.0*fcp*V[i];" in txt assert "Usource[i][1] += -1.0*fvisc*V[i];" in txt + + +def test_write_fvModel_static_mixers(): + # static-only, explicit placement: the ball path is auto-triggered by the + # presence of the static_mixers list (no volumetric_source needed) + d = { + "static_mixers": [ + { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "normal_dir": 1, + "radius": 0.05, + "sign": "+", + "swirl_sign": "+", + "S": 0.35, + "K": 0.5, + "start_time": 1, + } + ] + } + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(d, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert txt.count("codedSource") == 1 # single preamble + assert "// ===== static mixer =====" in txt + assert "// ===== ball mixer =====" not in txt # no dynamic block + assert txt.rstrip().endswith("};") # write_end closed the block + + # mixed dynamic + static, loop placement: both share one codedSource + base = { + "Meshing": {"Blockwise": {"x": 10, "y": 10, "z": 10}}, + "Geometry": { + "OverallDomain": { + a: {"nblocks": 10, "size_per_block": 1.0, "rescale": 2.76} + for a in ("x", "y", "z") + }, + "Fluids": [[[0, 0, 0], [9, 0, 0]]], + }, + "volumetric_source": "ball", + "mixers": [ + { + "branch_id": 0, + "frac_space": 0.5, + "radius": 0.4, + "sign": "+", + "swirl_sign": "+", + "Vtip": 1.5, + "Np": 6, + "sigma": 0.35, + "start_time": 1, + } + ], + "static_mixers": [ + { + "branch_id": 0, + "frac_space": 0.6, + "radius": 0.5, + "sign": "+", + "swirl_sign": "+", + "S": 0.35, + "K": 0.5, + "start_time": 1, + } + ], + } + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(base, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert txt.count("codedSource") == 1 # one shared block + assert "// ===== ball mixer =====" in txt # dynamic present + assert "// ===== static mixer =====" in txt # static present From 77be001800b976daf653624786f7ad5d36492a0d Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 15:46:12 -0600 Subject: [PATCH 17/52] Add template for mixer placement --- .../static_expl_list/mixers.json | 5 +++ .../static_loop_list/mixers.json | 24 +++++++++++ tests/preprocess/test_static_mixer.py | 42 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 bird/preprocess/dynamic_mixer/mixing_template/static_expl_list/mixers.json create mode 100644 bird/preprocess/dynamic_mixer/mixing_template/static_loop_list/mixers.json diff --git a/bird/preprocess/dynamic_mixer/mixing_template/static_expl_list/mixers.json b/bird/preprocess/dynamic_mixer/mixing_template/static_expl_list/mixers.json new file mode 100644 index 00000000..af3955cf --- /dev/null +++ b/bird/preprocess/dynamic_mixer/mixing_template/static_expl_list/mixers.json @@ -0,0 +1,5 @@ +{ + "static_mixers": [ + {"x": 0.025, "y": 0.07, "z": 0.025, "normal_dir": 1, "start_time": 1, "S": 0.35, "K": 0.5, "radius": 0.01, "sign": "+", "swirl_sign": "+"} + ] +} diff --git a/bird/preprocess/dynamic_mixer/mixing_template/static_loop_list/mixers.json b/bird/preprocess/dynamic_mixer/mixing_template/static_loop_list/mixers.json new file mode 100644 index 00000000..e3bffcd7 --- /dev/null +++ b/bird/preprocess/dynamic_mixer/mixing_template/static_loop_list/mixers.json @@ -0,0 +1,24 @@ +{ + "Meshing": { + "Blockwise": { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0, "rescale": 0.05}, + "y" : {"nblocks": 5, "size_per_block": 1.0, "rescale": 0.05}, + "z" : {"nblocks": 5, "size_per_block": 1.0, "rescale": 0.05} + }, + "Fluids": [ + [ [0,0,0], [9,0,0], [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4], [0,4,0], [0,1,0] ] + ] + + }, + "static_mixers": [ + {"branch_id": 0, "frac_space": 0.5, "start_time": 1, "S": 0.35, "K": 0.5, "radius": 0.5, "sign": "+", "swirl_sign": "+"} + ] +} diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py index 7d257c01..bdfe7492 100644 --- a/tests/preprocess/test_static_mixer.py +++ b/tests/preprocess/test_static_mixer.py @@ -1,3 +1,4 @@ +import os import tempfile from pathlib import Path @@ -9,6 +10,7 @@ ) from bird.preprocess.dynamic_mixer.mixer import StaticMixer from bird.preprocess.dynamic_mixer.mixing_fvModels import write_fvModel +from bird.utilities.parser import parse_json def test_StaticMixer(): @@ -189,3 +191,43 @@ def test_write_fvModel_static_mixers(): assert txt.count("codedSource") == 1 # one shared block assert "// ===== ball mixer =====" in txt # dynamic present assert "// ===== static mixer =====" in txt # static present + + +def test_static_expl_list(): + template_dir = os.path.join( + Path(__file__).parent, + "..", + "..", + "bird", + "preprocess", + "dynamic_mixer", + "mixing_template", + ) + d = parse_json( + os.path.join(template_dir, "static_expl_list", "mixers.json") + ) + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(d, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert "// ===== static mixer =====" in txt + assert txt.rstrip().endswith("};") + + +def test_static_loop_list(): + template_dir = os.path.join( + Path(__file__).parent, + "..", + "..", + "bird", + "preprocess", + "dynamic_mixer", + "mixing_template", + ) + d = parse_json( + os.path.join(template_dir, "static_loop_list", "mixers.json") + ) + with tempfile.TemporaryDirectory() as tmpdirname: + write_fvModel(d, output_folder=tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + assert "// ===== static mixer =====" in txt + assert txt.rstrip().endswith("};") From 8b3e5b11f53e64c7ccba2e4d56688e2f295f99cd Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 15:52:08 -0600 Subject: [PATCH 18/52] doc updates for static/dynamic mixer distinction --- docs/source/bird.preprocess.dynamic_mixer.rst | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/source/bird.preprocess.dynamic_mixer.rst b/docs/source/bird.preprocess.dynamic_mixer.rst index 2849beab..41a3d4b1 100644 --- a/docs/source/bird.preprocess.dynamic_mixer.rst +++ b/docs/source/bird.preprocess.dynamic_mixer.rst @@ -1,6 +1,39 @@ bird.preprocess.dynamic\_mixer package ====================================== +The ``dynamic_mixer`` package generates mixer momentum sources as OpenFOAM coded +``fvModels`` (see +:func:`~bird.preprocess.dynamic_mixer.mixing_fvModels.write_fvModel`). Two mixer +families share the same ``ball`` deposition: + +* **Dynamic** (:class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`, the + ``mixers`` list) -- an *active* actuator disk driven by a power number ``Np`` + and tip speed ``Vtip``; it adds axial thrust and swirl. +* **Static** (:class:`~bird.preprocess.dynamic_mixer.mixer.StaticMixer`, the + ``static_mixers`` list) -- a *passive* obstacle with no power input: the swirl + is an energy-neutral axial-to-azimuthal redirection (swirl number ``S``) and + the axial drag is a pure viscous loss (loss coefficient ``K``). It is inactive + when the inflow opposes the mixer orientation. The momentum source follows the + energy-neutral swirler model of Kiesewetter (2005). + +Static mixer JSON schema +------------------------ + +Each entry of the ``static_mixers`` list accepts: + +* ``S`` -- swirl number (default ``0.35``). +* ``K`` -- loss coefficient / velocity heads (default ``0.5``). +* ``radius`` -- mixer radius; a fraction of the tube in loop mode (``0.5`` spans + the whole tube) or an absolute radius in metres in explicit mode. +* ``normal_dir`` -- mixer axis (``0``/``1``/``2`` for x/y/z). +* ``sign`` -- mixer orientation along that axis (``"+"``/``"-"``). +* ``swirl_sign`` -- rotation orientation (``"+"``/``"-"``). +* ``start_time`` -- time after which the source is active. + +Placement is either explicit (``x``, ``y``, ``z``) or on a loop branch +(``branch_id`` plus ``frac_space``, the fraction along the branch), exactly as +for the dynamic mixer. + bird.preprocess.dynamic\_mixer.io\_fvModels module -------------------------------------------------- From 704ff343ead5ac2e96adb6d05a232656d9506e79 Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 16:02:01 -0600 Subject: [PATCH 19/52] sign printing was messed up --- bird/preprocess/dynamic_mixer/io_fvModels.py | 9 ++++-- tests/preprocess/test_static_mixer.py | 32 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index 29f56be3..845424ad 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -555,6 +555,11 @@ def write_static_mixer_ball(mixer, output_folder): }[nd] push_ax = "1.0" if mixer.sign == "+" else "-1.0" push_th = "1.0" if mixer.swirl_sign == "+" else "-1.0" + # pre-combined signs (= -push_ax / -push_th) as single literals, so the + # emitted C++ never contains "--1.0" (a decrement on a literal, a compile + # error). The drag opposes the oriented inflow; the reaction is -push_th. + drag_ax = "-1.0" if mixer.sign == "+" else "1.0" + cp_th = "-1.0" if mixer.swirl_sign == "+" else "1.0" with open(os.path.join(output_folder, "fvModels"), "a+") as f: f.write("\t\t// ===== static mixer =====\n") @@ -640,7 +645,7 @@ def write_static_mixer_ball(mixer, output_folder): f.write("\t\t\t\t\t\tif (Sax > 1e-30)\n") f.write("\t\t\t\t\t\t{\n") f.write("\t\t\t\t\t\t\tconst double fvisc = Tls/Sax*alphaL[i]*g;\n") - f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += -{push_ax}*fvisc*V[i];\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {drag_ax}*fvisc*V[i];\n") f.write("\t\t\t\t\t\t}\n") # swirl + energy-neutral axial reaction (local, velocity-weighted) f.write( @@ -665,7 +670,7 @@ def write_static_mixer_ball(mixer, output_folder): f.write( "\t\t\t\t\t\t\tconst double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g;\n" ) - f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += -{push_th}*fcp*V[i];\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {cp_th}*fcp*V[i];\n") f.write("\t\t\t\t\t\t}\n") f.write("\t\t\t\t\t}\n") f.write("\t\t\t\t}\n") diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py index bdfe7492..20b11da3 100644 --- a/tests/preprocess/test_static_mixer.py +++ b/tests/preprocess/test_static_mixer.py @@ -121,6 +121,38 @@ def test_write_static_mixer_ball(): assert "Usource[i][1] += -1.0*fvisc*V[i];" in txt +def test_write_static_mixer_ball_negative_orientation(): + # sign="-" and swirl_sign="-" must not emit "--1.0" (a decrement on a + # literal, which is a C++ compile error) + m = StaticMixer() + m.update_from_expl_dict( + { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "normal_dir": 1, + "radius": 0.05, + "sign": "-", + "swirl_sign": "-", + "S": 0.35, + "K": 0.5, + "start_time": 1, + } + ) + assert m.ready + + with tempfile.TemporaryDirectory() as tmpdirname: + write_preamble_ball(tmpdirname) + write_static_mixer_ball(m, tmpdirname) + write_end(tmpdirname) + txt = Path(tmpdirname, "fvModels").read_text() + + assert "--1.0" not in txt # no decrement-on-literal + # -push_ax and -push_th collapse to +1.0 for the negative orientation + assert "Usource[i][1] += 1.0*fvisc*V[i];" in txt + assert "Usource[i][1] += 1.0*fcp*V[i];" in txt + + def test_write_fvModel_static_mixers(): # static-only, explicit placement: the ball path is auto-triggered by the # presence of the static_mixers list (no volumetric_source needed) From 7b1d084f96d2d22a7fe274330acdec829a49eb35 Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 3 Aug 2026 16:09:24 -0600 Subject: [PATCH 20/52] add regression test for later --- .github/workflows/ci.yml | 5 + .../loop_reactor_mixing_static/0.orig/CO2.gas | 47 + .../0.orig/CO2.liquid | 42 + .../loop_reactor_mixing_static/0.orig/H2.gas | 47 + .../0.orig/H2.liquid | 42 + .../loop_reactor_mixing_static/0.orig/N2.gas | 47 + .../loop_reactor_mixing_static/0.orig/T.gas | 46 + .../0.orig/T.liquid | 45 + .../loop_reactor_mixing_static/0.orig/U.gas | 47 + .../0.orig/U.liquid | 46 + .../0.orig/Ydefault.gas | 42 + .../0.orig/Ydefault.liquid | 42 + .../0.orig/alpha.gas | 43 + .../0.orig/alpha.liquid | 40 + .../0.orig/alphat.gas | 46 + .../0.orig/alphat.liquid | 44 + .../0.orig/epsilon.gas | 48 + .../0.orig/epsilon.liquid | 43 + .../loop_reactor_mixing_static/0.orig/f.gas | 41 + .../loop_reactor_mixing_static/0.orig/k.gas | 43 + .../0.orig/k.liquid | 44 + .../loop_reactor_mixing_static/0.orig/nut.gas | 48 + .../0.orig/nut.liquid | 43 + .../loop_reactor_mixing_static/0.orig/p | 39 + .../loop_reactor_mixing_static/0.orig/p_rgh | 43 + .../loop_reactor_mixing_static/Allclean | 24 + .../loop_reactor_mixing_static/README.md | 28 + .../loop_reactor_mixing_static/computeQOI.sh | 13 + .../constant/fvModels | 187 +++ .../loop_reactor_mixing_static/constant/g | 21 + .../constant/globalVars | 83 ++ .../constant/globalVars_temp | 83 ++ .../constant/momentumTransport.gas | 26 + .../constant/momentumTransport.liquid | 27 + .../constant/phaseProperties | 261 ++++ .../constant/phaseProperties_constantd | 261 ++++ .../constant/phaseProperties_pbe | 295 +++++ .../constant/thermophysicalProperties.gas | 142 +++ .../constant/thermophysicalProperties.liquid | 108 ++ .../loop_reactor_mixing_static/get_qoi.py | 199 ++++ .../loop_reactor_mixing_static/presteps.sh | 81 ++ .../read_history.py | 104 ++ .../loop_reactor_mixing_static/run.sh | 72 ++ .../loop_reactor_mixing_static/script | 14 + .../loop_reactor_mixing_static/script_post | 10 + .../system/blockMeshDict | 1050 +++++++++++++++++ .../system/controlDict | 66 ++ .../system/decomposeParDict | 30 + .../system/fvConstraints | 56 + .../system/fvSchemes | 70 ++ .../system/fvSolution | 120 ++ .../system/inlets_outlets.json | 177 +++ .../system/mesh.json | 26 + .../system/mixers.json | 148 +++ .../system/setFieldsDict | 37 + .../writeGlobalVars.py | 42 + tutorial_cases/runall.sh | 4 + 57 files changed, 4928 insertions(+) create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/H2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/H2.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/N2.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/T.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/T.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/U.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/U.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/f.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/k.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/k.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/nut.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/nut.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/p create mode 100644 tutorial_cases/loop_reactor_mixing_static/0.orig/p_rgh create mode 100755 tutorial_cases/loop_reactor_mixing_static/Allclean create mode 100644 tutorial_cases/loop_reactor_mixing_static/README.md create mode 100644 tutorial_cases/loop_reactor_mixing_static/computeQOI.sh create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/fvModels create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/g create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/globalVars create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/globalVars_temp create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_constantd create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_pbe create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.gas create mode 100644 tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid create mode 100644 tutorial_cases/loop_reactor_mixing_static/get_qoi.py create mode 100644 tutorial_cases/loop_reactor_mixing_static/presteps.sh create mode 100644 tutorial_cases/loop_reactor_mixing_static/read_history.py create mode 100644 tutorial_cases/loop_reactor_mixing_static/run.sh create mode 100755 tutorial_cases/loop_reactor_mixing_static/script create mode 100755 tutorial_cases/loop_reactor_mixing_static/script_post create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/blockMeshDict create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/controlDict create mode 100755 tutorial_cases/loop_reactor_mixing_static/system/decomposeParDict create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/fvConstraints create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/fvSchemes create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/fvSolution create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/inlets_outlets.json create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/mesh.json create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/mixers.json create mode 100644 tutorial_cases/loop_reactor_mixing_static/system/setFieldsDict create mode 100644 tutorial_cases/loop_reactor_mixing_static/writeGlobalVars.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8efcf29..9b396279 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,6 +252,11 @@ jobs: cd tutorial_cases/loop_reactor_mixing_swirl bash run.sh cd ../../ + - name: Run mixing loop reactor with static mixer tutorial + run: | + cd tutorial_cases/loop_reactor_mixing_static + bash run.sh + cd ../../ - name: Run airlift reactor tutorial run: | cd tutorial_cases/airlift_40m diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.gas new file mode 100644 index 00000000..e4165b1a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_CO2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_CO2; + //value $f_CO2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.liquid new file mode 100644 index 00000000..4b8ea6a0 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/CO2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.gas new file mode 100644 index 00000000..9f66b2d2 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_H2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_H2; + //value $f_H2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.liquid new file mode 100644 index 00000000..65ae8d34 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/H2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/N2.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/N2.gas new file mode 100644 index 00000000..c1d7225f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/N2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_N2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_N2; + //value $f_N2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/T.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/T.gas new file mode 100644 index 00000000..1202c340 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/T.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value $internalField; + } + + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/T.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/T.liquid new file mode 100644 index 00000000..d6c1836a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/T.liquid @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + inlet + { + type fixedValue; + value $internalField; + } + defaultFaces + { + type zeroGradient; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/U.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/U.gas new file mode 100644 index 00000000..e696566f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/U.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0.0 0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateGas; + //rho thermo:rho.gas; + //value $internalField; + type fixedValue; + value uniform (0 $uGasPhase 0); + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + defaultFaces + { + type slip; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/U.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/U.liquid new file mode 100644 index 00000000..1879e020 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/U.liquid @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0 0 0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateLiq; + //rho thermo:rho.liquid; + //value $internalField; + type fixedValue; + value uniform (0 0 0); + } + outlet + { + type noSlip; + } + defaultFaces + { + type noSlip; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.gas new file mode 100644 index 00000000..fba2945d --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.gas @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.liquid new file mode 100644 index 00000000..a5108564 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/Ydefault.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.gas new file mode 100644 index 00000000..1e303fbe --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $alphaGas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaGas; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1; + value uniform 1; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.liquid new file mode 100644 index 00000000..5c92070b --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/alpha.liquid @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaLiq; + } + outlet + { + type fixedValue; + value uniform 0; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.gas new file mode 100644 index 00000000..b867958f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type calculated; + value $internalField; + //type compressible::alphatWallFunction; + //Prt 0.85; + //value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.liquid new file mode 100644 index 00000000..2569c3ee --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/alphat.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.gas new file mode 100644 index 00000000..707a1cda --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object epsilon.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $eps_inlet_gas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $eps_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + //type epsilonWallFunction; + //value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.liquid new file mode 100644 index 00000000..0a4236fd --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/epsilon.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object epsilon.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $eps_inlet_liq; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $eps_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type epsilonWallFunction; + value $internalField; + } + +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/f.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/f.gas new file mode 100644 index 00000000..76ee77a9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/f.gas @@ -0,0 +1,41 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object f.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; //$internalField; // + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/k.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/k.gas new file mode 100644 index 00000000..4a3d44ca --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_gas; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/k.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/k.liquid new file mode 100644 index 00000000..cde8f6c1 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/k.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_liq; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.gas b/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.gas new file mode 100644 index 00000000..ba16dd4c --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-8; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + //type nutkWallFunction; + //value $internalField; + type calculated; + value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.liquid b/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.liquid new file mode 100644 index 00000000..1442e07f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/nut.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/p b/tutorial_cases/loop_reactor_mixing_static/0.orig/p new file mode 100644 index 00000000..b3a295fb --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/p @@ -0,0 +1,39 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + defaultFaces + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/0.orig/p_rgh b/tutorial_cases/loop_reactor_mixing_static/0.orig/p_rgh new file mode 100644 index 00000000..88ee7d80 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/0.orig/p_rgh @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + rho thermo:rho.gas; + value $internalField; + } + defaultFaces + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/Allclean b/tutorial_cases/loop_reactor_mixing_static/Allclean new file mode 100755 index 00000000..dc2f77db --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/Allclean @@ -0,0 +1,24 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +if [ -n "$WM_PROJECT_DIR" ]; then + . $WM_PROJECT_DIR/bin/tools/CleanFunctions + cleanCase +else + echo "WARNING: could not run cleanCase, OpenFOAM env not found" +fi + +# Remove 0 +[ -d "0" ] && rm -rf 0 + +# rm -f constant/triSurface/*.eMesh +# [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" +[ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" +[ -d "dynamicCode" ] && rm -rf "dynamicCode" +[ -d "processor*" ] && rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/tutorial_cases/loop_reactor_mixing_static/README.md b/tutorial_cases/loop_reactor_mixing_static/README.md new file mode 100644 index 00000000..f8a070ec --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/README.md @@ -0,0 +1,28 @@ +### Loop reactor with passive static mixers + +Same 608 m3 loop reactor as `loop_reactor_mixing`, but the mixers are **passive +static mixers** instead of the powered actuator disks of +`loop_reactor_mixing_swirl`. + +The static mixer injects no power: the swirl is imposed as an energy-neutral +axial-to-azimuthal redirection (Kiesewetter's swirler model) and the axial drag +is a pure viscous loss. It is selected simply by providing a `static_mixers` +list in `system/mixers.json` (the `ball` deposition is triggered automatically), +with per-mixer inputs: + +- `S` — swirl number (target ratio of azimuthal to axial momentum flux). +- `K` — loss coefficient (velocity heads) for the axial pressure drop. +- `radius` — mixer radius as a fraction of the branch cross-section (`0.5` + spans the whole tube), as for the spargers. +- `sign` — mixer orientation; the source is inactive when the inflow + opposes it. +- `swirl_sign` — rotation orientation. +- `start_time` — time after which the source is active. + +Placement uses `branch_id` + `frac_space`, as for the dynamic mixer. This case +places one `+`-oriented and one `-`-oriented mixer so both sign paths are +exercised. + +Single core exec + +1. `bash run.sh` diff --git a/tutorial_cases/loop_reactor_mixing_static/computeQOI.sh b/tutorial_cases/loop_reactor_mixing_static/computeQOI.sh new file mode 100644 index 00000000..3756ed7f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/computeQOI.sh @@ -0,0 +1,13 @@ +if [ ! -f qoi.txt ]; then + # Reconstruct if needed + source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc + reconstructPar -newTimes + module load anaconda3/2023 + conda activate /projects/gas2fuels/conda_env/bird + python read_history.py -cr .. -cn local -df data + python get_qoi.py + conda deactivate +else + echo "WARNING: QOI already computed" +fi + diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/fvModels b/tutorial_cases/loop_reactor_mixing_static/constant/fvModels new file mode 100644 index 00000000..268773e7 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/fvModels @@ -0,0 +1,187 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include + #include + #}; + + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + const double pi = 3.14159265358979; + // ===== static mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Snum = 0.35; + const double Kloss = 0.5; + const double startT = 1; + const double px = 11.32226290810711, py = 1.3807637692813548, pz = 1.3807637692813548; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dx)*(dx)); + const double ux = UL[i][0]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][0] += -1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][0]; + const double uth = UL[i][1]*((-dz)/rr) + UL[i][2]*((dy)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][1] += 1.0*fsw*V[i]*((-dz)/rr); + Usource[i][2] += 1.0*fsw*V[i]*((dy)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][0] += -1.0*fcp*V[i]; + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 1.1046110154250839; + const double area = pi*Rmix*Rmix; + const double Snum = 0.35; + const double Kloss = 0.5; + const double startT = 1; + const double px = 16.293012477519987, py = 1.3807637692813548, pz = 12.426873923532193; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dx < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][0]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dx)*(dx)); + const double ux = UL[i][0]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][0] += 1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dx)*(dx)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][0]; + const double uth = UL[i][1]*((-dz)/rr) + UL[i][2]*((dy)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][1] += -1.0*fsw*V[i]*((-dz)/rr); + Usource[i][2] += -1.0*fsw*V[i]*((dy)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][0] += 1.0*fcp*V[i]; + } + } + } + } + } + #}; +}; diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/g b/tutorial_cases/loop_reactor_mixing_static/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/globalVars b/tutorial_cases/loop_reactor_mixing_static/constant/globalVars new file mode 100644 index 00000000..c0dce472 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/globalVars @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 0.4; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA 15.8621; +liqVol 608.198; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/globalVars_temp b/tutorial_cases/loop_reactor_mixing_static/constant/globalVars_temp new file mode 100644 index 00000000..dfddd649 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/globalVars_temp @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 0.4; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA ; +liqVol ; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.gas b/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.gas new file mode 100644 index 00000000..ca916714 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; +RAS +{ + model mixtureKEpsilon; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.liquid b/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.liquid new file mode 100644 index 00000000..2063de0d --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model mixtureKEpsilon; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_constantd b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_constantd new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_pbe b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_pbe new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/phaseProperties_pbe @@ -0,0 +1,295 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangePopulationBalanceMultiphaseSystem; + +phases (gas liquid); + +populationBalances (bubbles); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel velocityGroup; + + velocityGroupCoeffs + { + populationBalance bubbles; + + shapeModel spherical; + + sizeGroups + ( + f1 {dSph 1.4e-3; value 0.0;} + f2 {dSph 1.8e-3; value 0.0;} + f3 {dSph 2.2e-3; value 0.0;} + f4 {dSph 2.6e-3; value 0.0;} + f5 {dSph 3e-3; value 1.0;} + f6 {dSph 3.4e-3; value 0.0;} + f7 {dSph 3.8e-3; value 0.0;} + f8 {dSph 4.2e-3; value 0.0;} + f9 {dSph 4.6e-3; value 0.0;} + f10 {dSph 5.0e-3; value 0.0;} + ); + } + + residualAlpha 1e-6; + + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + ( + LehrMilliesMewes{ + efficiency 4.695; + uCrit 0.08; + alphaMax 0.6; + } + ); + + binaryBreakupModels + (); + + breakupModels + ( + Laakkonen { + efficiency 13.83; + daughterSizeDistributionModel Laakkonen; + } + + ); + + driftModels + ( + densityChange{} + ); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.gas b/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..11b1c4b9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.gas @@ -0,0 +1,142 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + H2 + CO2 + N2 +); + +defaultSpecie N2; + +CO2 +{ + specie + { + molWeight 44.00995; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.85746029 0.00441437026 -2.21481404e-06 5.23490188e-10 -4.72084164e-14 -48759.166 2.27163806 ); + lowCpCoeffs ( 2.35677352 0.00898459677 -7.12356269e-06 2.45919022e-09 -1.43699548e-13 -48371.9697 9.90105222 ); + } + transport + { + As 1.572e-06; + Ts 240; + } + elements + { + C 1; + O 2; + } +} + +water +{ + specie + { + molWeight 18.01534; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.03399249 0.00217691804 -1.64072518e-07 -9.7041987e-11 1.68200992e-14 -30004.2971 4.9667701 ); + lowCpCoeffs ( 4.19864056 -0.0020364341 6.52040211e-06 -5.48797062e-09 1.77197817e-12 -30293.7267 -0.849032208 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + H 2; + O 1; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.3372792 -4.94024731e-05 4.99456778e-07 -1.79566394e-10 2.00255376e-14 -950.158922 -3.20502331 ); + lowCpCoeffs ( 2.34433112 0.00798052075 -1.9478151e-05 2.01572094e-08 -7.37611761e-12 -917.935173 0.683010238 ); + } + transport + { + As 6.362e-07; + Ts 72; + } + elements + { + H 2; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid b/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..d324ec51 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid @@ -0,0 +1,108 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + CO2 + water + H2 +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +CO2 +{ + specie + { + molWeight 44.00995; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrCO2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07;//-9402451; + } + transport + { + mu $muMixLiq; + Pr $PrH2; + } +} + + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/get_qoi.py b/tutorial_cases/loop_reactor_mixing_static/get_qoi.py new file mode 100644 index 00000000..7f3897ed --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/get_qoi.py @@ -0,0 +1,199 @@ +import json +import os +import pickle as pkl + +import matplotlib as mpl +import numpy as np +from prettyPlot.plotting import * +from scipy.optimize import curve_fit + + +def get_sim_folds(path): + folds = os.listdir(path) + sim_folds = [] + for fold in folds: + if fold.startswith("loop"): + sim_folds.append(fold) + return sim_folds + + +def func(t, cstar, kla): + t = t + t0 = 0 + c0 = 0 + return (cstar - c0) * (1 - np.exp(-kla * (t - t0))) + c0 + + +def get_vl(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("liqVol"): + vol = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read liqVol = {vol}m3") + return vol + + +def get_vvm(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("VVM"): + vvm = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read VVM = {vvm} [-]") + return vvm + + +def get_As(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("inletA"): + As = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read As = {As}m2") + return As + + +def get_pmix(verb=False): + with open("system/mixers.json", "r+") as f: + data = json.load(f) + mixer_list = data["mixers"] + pmix = 0 + for mix in mixer_list: + pmix += mix["power"] / 1000 + if verb: + print(f"Read Mixing power = {pmix}kW") + return pmix + + +def get_lh(verb=False): + filename = os.path.join("system", "setFieldsDict") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if "box (-1.0 -1.0 -1.0)" in line: + height = float(line.split("(")[2].split()[1]) + break + if verb: + print(f"Read Height = {height}m") + return height + + +def get_pinj(vvm, Vl, As, lh): + rhog = 1.25 # kg /m3 + Vg = Vl * vvm / (60 * As * 1) # m/s + Ptank = 101325 # Pa + # Ptank = 0 # Pa + rhoL = 1000 # kg / m3 + Pl = 101325 + rhoL * 9.8 * lh # Pa + # W + P1 = rhog * As * Vg**3 + # W + P2 = (Pl - Ptank) * As * Vg + # kg /s + MF = rhog * Vg * As + # kwh / kg + e_m = (P1 + P2) / (3600 * 1000 * MF) + + # returns kW + return (P1 + P2) * 1e-3 + + +def get_qoi(kla_co2, cs_co2, kla_h2, cs_h2, verb=False): + vvm = get_vvm(verb) + As = get_As(verb) + V_l = get_vl(verb) + liqh = get_lh(verb) + P_inj = get_pinj(vvm, V_l, As, liqh) + P_mix = get_pmix(verb) + + qoi_kla_co2 = kla_co2 * cs_co2 * V_l * 0.04401 + qoi_kla_h2 = kla_h2 * cs_h2 * V_l * 0.002016 + + qoi_co2 = qoi_kla_co2 / (P_mix / 3600 + P_inj / 3600) + qoi_h2 = qoi_kla_h2 / (P_mix / 3600 + P_inj / 3600) + return qoi_co2 * qoi_h2, qoi_kla_co2 * qoi_kla_h2 + + +def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): + qoi = [] + qoi_kla = [] + for i in range(len(kla_co2)): + if i == 0: + verb = True + else: + verb = False + qoi_tmp, qoi_kla_tmp = get_qoi( + kla_co2[i], cs_co2[i], kla_h2[i], cs_h2[i], verb + ) + qoi.append(qoi_tmp) + qoi_kla.append(qoi_kla_tmp) + qoi = np.array(qoi) + qoi_kla = np.array(qoi_kla) + return np.mean(qoi), np.std(qoi), np.mean(qoi_kla), np.std(qoi_kla) + + +os.makedirs("Figures", exist_ok=True) + +dataFolder = "data" +fold = "local" + +nuq = 100 +# mean_cstar_co2 = np.random.uniform(12.6, 13.3, nuq) +# mean_cstar_h2 = np.random.uniform(0.902, 0.96, nuq) +mean_cstar_co2 = np.random.uniform(14, 16.9, nuq) +mean_cstar_h2 = np.random.uniform(1.04, 1.19, nuq) + + +tmp_cs_h2 = [] +tmp_cs_co2 = [] +tmp_kla_h2 = [] +tmp_kla_co2 = [] +cs_co2 = mean_cstar_co2 +cs_h2 = mean_cstar_h2 + +a = np.load(os.path.join(dataFolder, fold, "conv.npz")) +endindex = -1 +if ( + "c_h2" in a + and "c_co2" in a + and len(a["time"][:endindex] > 0) + and (a["time"][:endindex][-1] > 95) +): + for i in range(nuq): + fitparamsH2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_h2"][:endindex]), + bounds=[(cs_h2[i] - 1e-6, 0), (cs_h2[i] + 1e-6, 1)], + ) + fitparamsCO2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_co2"][:endindex]), + bounds=[(cs_co2[i] - 1e-6, 0), (cs_co2[i] + 1e-6, 1)], + ) + tmp_kla_co2.append(fitparamsCO2[1]) + tmp_kla_h2.append(fitparamsH2[1]) + tmp_cs_h2.append(cs_h2[i]) + tmp_cs_co2.append(cs_co2[i]) + +qoi_m, qoi_s, qoi_kla_m, qoi_kla_s = get_qoi_uq( + tmp_kla_co2, tmp_cs_co2, tmp_kla_h2, tmp_cs_h2 +) + + +with open("qoi.txt", "w+") as f: + f.write(f"{qoi_m},{qoi_s}\n") + +with open("qoi_kla.txt", "w+") as f: + f.write(f"{qoi_kla_m},{qoi_kla_s}\n") diff --git a/tutorial_cases/loop_reactor_mixing_static/presteps.sh b/tutorial_cases/loop_reactor_mixing_static/presteps.sh new file mode 100644 index 00000000..bfcff75f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/presteps.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# Clean case +module load conda +conda activate /projects/gas2fuels/conda_env/bird +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +# Define what to do on error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +# Generate blockmeshDict +python /projects/gas2fuels/BioReactorDesign/applications/write_block_rect_mesh.py -i system/mesh.json -o system +#python ../../../applications/write_block_rect_mesh.py -i system/mesh.json -o system + +# Generate boundary stl +python /projects/gas2fuels/BioReactorDesign/applications/write_stl_patch.py -i system/inlets_outlets.json +#python ../../../applications/write_stl_patch.py -i system/inlets_outlets.json + +# Generate mixers +python /projects/gas2fuels/BioReactorDesign/applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant +#python ../../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant + +# Generate species thermo properties +python /projects/gas2fuels/BioReactorDesign//applications/write_species_thermo_prop.py -cf . + +echo PRESTEP 2 +# Mesh gen +blockMesh -dict system/blockMeshDict + +# Inlet BC +surfaceToPatch -tol 1e-3 inlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/inlets\.stl/inlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + +# Outlet BC +surfaceToPatch -tol 1e-3 outlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/outlets\.stl/outlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + + +# Scale +transformPoints "scale=(2.7615275385627096 2.7615275385627096 2.7615275385627096)" + + +# setup IC +cp -r 0.orig 0 +setFields + +# Setup mass flow rate +# Get inlet area +postProcess -func 'patchIntegrate(patch="inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_pbe constant/phaseProperties + +conda deactivate + +if [ -f qoi.txt ]; then + rm qoi.txt +fi +if [ -f data/local/conv.npz ]; then + rm data/local/conv.npz +fi + diff --git a/tutorial_cases/loop_reactor_mixing_static/read_history.py b/tutorial_cases/loop_reactor_mixing_static/read_history.py new file mode 100644 index 00000000..c27eae94 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/read_history.py @@ -0,0 +1,104 @@ +import argparse +import os +import sys + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.postprocess.post_quantities import * +from bird.utilities.ofio import * + +parser = argparse.ArgumentParser(description="Convergence of GH") +parser.add_argument( + "-cn", + "--case_name", + type=str, + metavar="", + required=True, + help="Case name", +) +parser.add_argument( + "-df", + "--data_folder", + type=str, + metavar="", + required=False, + help="data folder name", + default="data", +) + +args, unknown = parser.parse_known_args() + + +case_root = "." # "../" +case_name = args.case_name # "12_hole_sparger_snappyRefine_700rpm_opt_coeff" +case_path = "." +dataFolder = args.data_folder + +if os.path.isfile(os.path.join(dataFolder, case_name, "conv.npz")): + sys.exit("WARNING: History already created, Skipping") + +time_float_sorted, time_str_sorted = get_case_times( + case_path, remove_zero=True +) +cell_centers, _ = read_cell_centers(".") +nCells = len(cell_centers) + + +co2_history = np.zeros(len(time_str_sorted)) +c_co2_history = np.zeros(len(time_str_sorted)) +h2_history = np.zeros(len(time_str_sorted)) +c_h2_history = np.zeros(len(time_str_sorted)) +gh_history = np.zeros(len(time_str_sorted)) +liqvol_history = np.zeros(len(time_str_sorted)) +print(f"case_path = {case_path}") +field_dict = {} +for itime, time in enumerate(time_float_sorted): + time_folder = time_str_sorted[itime] + print(f"\tTime : {time_folder}") + if not field_dict == {}: + new_field_dict = {} + if "V" in field_dict: + new_field_dict["V"] = field_dict["V"] + field_dict = new_field_dict + gh_history[itime], field_dict = compute_gas_holdup( + case_path, + time_str_sorted[itime], + field_dict=field_dict, + ) + co2_history[itime], field_dict = compute_ave_y_liq( + case_path, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + h2_history[itime], field_dict = compute_ave_y_liq( + case_path, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + c_co2_history[itime], field_dict = compute_ave_conc_liq( + case_path, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + c_h2_history[itime], field_dict = compute_ave_conc_liq( + case_path, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + +os.makedirs(dataFolder, exist_ok=True) +os.makedirs(os.path.join(dataFolder, case_name), exist_ok=True) +np.savez( + os.path.join(dataFolder, case_name, "conv.npz"), + time=np.array(time_float_sorted), + gh=gh_history, + co2=co2_history, + h2=h2_history, + c_h2=c_h2_history, + c_co2=c_co2_history, +) diff --git a/tutorial_cases/loop_reactor_mixing_static/run.sh b/tutorial_cases/loop_reactor_mixing_static/run.sh new file mode 100644 index 00000000..25251599 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/run.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Clean case +#module load anaconda3/2023 +#conda activate /projects/gas2fuels/conda_env/bird +#source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +# Define what to do on error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +# Generate blockmeshDict +python ../../applications/write_block_rect_mesh.py -i system/mesh.json -o system + +# Generate boundary stl +python ../../applications/write_stl_patch.py -i system/inlets_outlets.json + +# Generate mixers +python ../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant + +# Generate species thermo properties +python ../../applications/write_species_thermo_prop.py -cf . + +echo PRESTEP 2 +# Mesh gen +blockMesh -dict system/blockMeshDict + +# Inlet BC +surfaceToPatch -tol 1e-3 inlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/inlets\.stl/inlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + +# Outlet BC +surfaceToPatch -tol 1e-3 outlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary /tmp +sed -i -e 's/outlets\.stl/outlet/g' /tmp/boundary +cat /tmp/boundary > constant/polyMesh/boundary + + +# Scale +transformPoints "scale=(2.7615275385627096 2.7615275385627096 2.7615275385627096)" + + +# setup IC +cp -r 0.orig 0 +setFields + +# Setup mass flow rate +# Get inlet area +postProcess -func 'patchIntegrate(patch="inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_pbe constant/phaseProperties + +#conda deactivate + +echo RUN +birdmultiphaseEulerFoam diff --git a/tutorial_cases/loop_reactor_mixing_static/script b/tutorial_cases/loop_reactor_mixing_static/script new file mode 100755 index 00000000..efe675ff --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/script @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=07:59:00 +#SBATCH --account=co2snow + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes diff --git a/tutorial_cases/loop_reactor_mixing_static/script_post b/tutorial_cases/loop_reactor_mixing_static/script_post new file mode 100755 index 00000000..aabbc33e --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/script_post @@ -0,0 +1,10 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=00:59:00 +#SBATCH --account=co2snow + +bash computeQOI.sh diff --git a/tutorial_cases/loop_reactor_mixing_static/system/blockMeshDict b/tutorial_cases/loop_reactor_mixing_static/system/blockMeshDict new file mode 100644 index 00000000..0bb60950 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/blockMeshDict @@ -0,0 +1,1050 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1.0; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +vertices +( +( 0.0 0.0 0.0) +( 1.0 0.0 0.0) +( 2.0 0.0 0.0) +( 3.0 0.0 0.0) +( 4.0 0.0 0.0) +( 5.0 0.0 0.0) +( 6.0 0.0 0.0) +( 7.0 0.0 0.0) +( 8.0 0.0 0.0) +( 9.0 0.0 0.0) +( 10.0 0.0 0.0) +( 0.0 1.0 0.0) +( 1.0 1.0 0.0) +( 2.0 1.0 0.0) +( 3.0 1.0 0.0) +( 4.0 1.0 0.0) +( 5.0 1.0 0.0) +( 6.0 1.0 0.0) +( 7.0 1.0 0.0) +( 8.0 1.0 0.0) +( 9.0 1.0 0.0) +( 10.0 1.0 0.0) +( 0.0 2.0 0.0) +( 1.0 2.0 0.0) +( 2.0 2.0 0.0) +( 3.0 2.0 0.0) +( 4.0 2.0 0.0) +( 5.0 2.0 0.0) +( 6.0 2.0 0.0) +( 7.0 2.0 0.0) +( 8.0 2.0 0.0) +( 9.0 2.0 0.0) +( 10.0 2.0 0.0) +( 0.0 3.0 0.0) +( 1.0 3.0 0.0) +( 2.0 3.0 0.0) +( 3.0 3.0 0.0) +( 4.0 3.0 0.0) +( 5.0 3.0 0.0) +( 6.0 3.0 0.0) +( 7.0 3.0 0.0) +( 8.0 3.0 0.0) +( 9.0 3.0 0.0) +( 10.0 3.0 0.0) +( 0.0 4.0 0.0) +( 1.0 4.0 0.0) +( 2.0 4.0 0.0) +( 3.0 4.0 0.0) +( 4.0 4.0 0.0) +( 5.0 4.0 0.0) +( 6.0 4.0 0.0) +( 7.0 4.0 0.0) +( 8.0 4.0 0.0) +( 9.0 4.0 0.0) +( 10.0 4.0 0.0) +( 0.0 5.0 0.0) +( 1.0 5.0 0.0) +( 2.0 5.0 0.0) +( 3.0 5.0 0.0) +( 4.0 5.0 0.0) +( 5.0 5.0 0.0) +( 6.0 5.0 0.0) +( 7.0 5.0 0.0) +( 8.0 5.0 0.0) +( 9.0 5.0 0.0) +( 10.0 5.0 0.0) +( 0.0 6.0 0.0) +( 1.0 6.0 0.0) +( 2.0 6.0 0.0) +( 3.0 6.0 0.0) +( 4.0 6.0 0.0) +( 5.0 6.0 0.0) +( 6.0 6.0 0.0) +( 7.0 6.0 0.0) +( 8.0 6.0 0.0) +( 9.0 6.0 0.0) +( 10.0 6.0 0.0) +( 0.0 7.0 0.0) +( 1.0 7.0 0.0) +( 2.0 7.0 0.0) +( 3.0 7.0 0.0) +( 4.0 7.0 0.0) +( 5.0 7.0 0.0) +( 6.0 7.0 0.0) +( 7.0 7.0 0.0) +( 8.0 7.0 0.0) +( 9.0 7.0 0.0) +( 10.0 7.0 0.0) +( 0.0 8.0 0.0) +( 1.0 8.0 0.0) +( 2.0 8.0 0.0) +( 3.0 8.0 0.0) +( 4.0 8.0 0.0) +( 5.0 8.0 0.0) +( 6.0 8.0 0.0) +( 7.0 8.0 0.0) +( 8.0 8.0 0.0) +( 9.0 8.0 0.0) +( 10.0 8.0 0.0) +( 0.0 9.0 0.0) +( 1.0 9.0 0.0) +( 2.0 9.0 0.0) +( 3.0 9.0 0.0) +( 4.0 9.0 0.0) +( 5.0 9.0 0.0) +( 6.0 9.0 0.0) +( 7.0 9.0 0.0) +( 8.0 9.0 0.0) +( 9.0 9.0 0.0) +( 10.0 9.0 0.0) +( 0.0 10.0 0.0) +( 1.0 10.0 0.0) +( 2.0 10.0 0.0) +( 3.0 10.0 0.0) +( 4.0 10.0 0.0) +( 5.0 10.0 0.0) +( 6.0 10.0 0.0) +( 7.0 10.0 0.0) +( 8.0 10.0 0.0) +( 9.0 10.0 0.0) +( 10.0 10.0 0.0) +( 0.0 11.0 0.0) +( 1.0 11.0 0.0) +( 2.0 11.0 0.0) +( 3.0 11.0 0.0) +( 4.0 11.0 0.0) +( 5.0 11.0 0.0) +( 6.0 11.0 0.0) +( 7.0 11.0 0.0) +( 8.0 11.0 0.0) +( 9.0 11.0 0.0) +( 10.0 11.0 0.0) +( 0.0 0.0 1.0) +( 1.0 0.0 1.0) +( 2.0 0.0 1.0) +( 3.0 0.0 1.0) +( 4.0 0.0 1.0) +( 5.0 0.0 1.0) +( 6.0 0.0 1.0) +( 7.0 0.0 1.0) +( 8.0 0.0 1.0) +( 9.0 0.0 1.0) +( 10.0 0.0 1.0) +( 0.0 1.0 1.0) +( 1.0 1.0 1.0) +( 2.0 1.0 1.0) +( 3.0 1.0 1.0) +( 4.0 1.0 1.0) +( 5.0 1.0 1.0) +( 6.0 1.0 1.0) +( 7.0 1.0 1.0) +( 8.0 1.0 1.0) +( 9.0 1.0 1.0) +( 10.0 1.0 1.0) +( 0.0 2.0 1.0) +( 1.0 2.0 1.0) +( 2.0 2.0 1.0) +( 3.0 2.0 1.0) +( 4.0 2.0 1.0) +( 5.0 2.0 1.0) +( 6.0 2.0 1.0) +( 7.0 2.0 1.0) +( 8.0 2.0 1.0) +( 9.0 2.0 1.0) +( 10.0 2.0 1.0) +( 0.0 3.0 1.0) +( 1.0 3.0 1.0) +( 2.0 3.0 1.0) +( 3.0 3.0 1.0) +( 4.0 3.0 1.0) +( 5.0 3.0 1.0) +( 6.0 3.0 1.0) +( 7.0 3.0 1.0) +( 8.0 3.0 1.0) +( 9.0 3.0 1.0) +( 10.0 3.0 1.0) +( 0.0 4.0 1.0) +( 1.0 4.0 1.0) +( 2.0 4.0 1.0) +( 3.0 4.0 1.0) +( 4.0 4.0 1.0) +( 5.0 4.0 1.0) +( 6.0 4.0 1.0) +( 7.0 4.0 1.0) +( 8.0 4.0 1.0) +( 9.0 4.0 1.0) +( 10.0 4.0 1.0) +( 0.0 5.0 1.0) +( 1.0 5.0 1.0) +( 2.0 5.0 1.0) +( 3.0 5.0 1.0) +( 4.0 5.0 1.0) +( 5.0 5.0 1.0) +( 6.0 5.0 1.0) +( 7.0 5.0 1.0) +( 8.0 5.0 1.0) +( 9.0 5.0 1.0) +( 10.0 5.0 1.0) +( 0.0 6.0 1.0) +( 1.0 6.0 1.0) +( 2.0 6.0 1.0) +( 3.0 6.0 1.0) +( 4.0 6.0 1.0) +( 5.0 6.0 1.0) +( 6.0 6.0 1.0) +( 7.0 6.0 1.0) +( 8.0 6.0 1.0) +( 9.0 6.0 1.0) +( 10.0 6.0 1.0) +( 0.0 7.0 1.0) +( 1.0 7.0 1.0) +( 2.0 7.0 1.0) +( 3.0 7.0 1.0) +( 4.0 7.0 1.0) +( 5.0 7.0 1.0) +( 6.0 7.0 1.0) +( 7.0 7.0 1.0) +( 8.0 7.0 1.0) +( 9.0 7.0 1.0) +( 10.0 7.0 1.0) +( 0.0 8.0 1.0) +( 1.0 8.0 1.0) +( 2.0 8.0 1.0) +( 3.0 8.0 1.0) +( 4.0 8.0 1.0) +( 5.0 8.0 1.0) +( 6.0 8.0 1.0) +( 7.0 8.0 1.0) +( 8.0 8.0 1.0) +( 9.0 8.0 1.0) +( 10.0 8.0 1.0) +( 0.0 9.0 1.0) +( 1.0 9.0 1.0) +( 2.0 9.0 1.0) +( 3.0 9.0 1.0) +( 4.0 9.0 1.0) +( 5.0 9.0 1.0) +( 6.0 9.0 1.0) +( 7.0 9.0 1.0) +( 8.0 9.0 1.0) +( 9.0 9.0 1.0) +( 10.0 9.0 1.0) +( 0.0 10.0 1.0) +( 1.0 10.0 1.0) +( 2.0 10.0 1.0) +( 3.0 10.0 1.0) +( 4.0 10.0 1.0) +( 5.0 10.0 1.0) +( 6.0 10.0 1.0) +( 7.0 10.0 1.0) +( 8.0 10.0 1.0) +( 9.0 10.0 1.0) +( 10.0 10.0 1.0) +( 0.0 11.0 1.0) +( 1.0 11.0 1.0) +( 2.0 11.0 1.0) +( 3.0 11.0 1.0) +( 4.0 11.0 1.0) +( 5.0 11.0 1.0) +( 6.0 11.0 1.0) +( 7.0 11.0 1.0) +( 8.0 11.0 1.0) +( 9.0 11.0 1.0) +( 10.0 11.0 1.0) +( 0.0 0.0 2.0) +( 1.0 0.0 2.0) +( 2.0 0.0 2.0) +( 3.0 0.0 2.0) +( 4.0 0.0 2.0) +( 5.0 0.0 2.0) +( 6.0 0.0 2.0) +( 7.0 0.0 2.0) +( 8.0 0.0 2.0) +( 9.0 0.0 2.0) +( 10.0 0.0 2.0) +( 0.0 1.0 2.0) +( 1.0 1.0 2.0) +( 2.0 1.0 2.0) +( 3.0 1.0 2.0) +( 4.0 1.0 2.0) +( 5.0 1.0 2.0) +( 6.0 1.0 2.0) +( 7.0 1.0 2.0) +( 8.0 1.0 2.0) +( 9.0 1.0 2.0) +( 10.0 1.0 2.0) +( 0.0 2.0 2.0) +( 1.0 2.0 2.0) +( 2.0 2.0 2.0) +( 3.0 2.0 2.0) +( 4.0 2.0 2.0) +( 5.0 2.0 2.0) +( 6.0 2.0 2.0) +( 7.0 2.0 2.0) +( 8.0 2.0 2.0) +( 9.0 2.0 2.0) +( 10.0 2.0 2.0) +( 0.0 3.0 2.0) +( 1.0 3.0 2.0) +( 2.0 3.0 2.0) +( 3.0 3.0 2.0) +( 4.0 3.0 2.0) +( 5.0 3.0 2.0) +( 6.0 3.0 2.0) +( 7.0 3.0 2.0) +( 8.0 3.0 2.0) +( 9.0 3.0 2.0) +( 10.0 3.0 2.0) +( 0.0 4.0 2.0) +( 1.0 4.0 2.0) +( 2.0 4.0 2.0) +( 3.0 4.0 2.0) +( 4.0 4.0 2.0) +( 5.0 4.0 2.0) +( 6.0 4.0 2.0) +( 7.0 4.0 2.0) +( 8.0 4.0 2.0) +( 9.0 4.0 2.0) +( 10.0 4.0 2.0) +( 0.0 5.0 2.0) +( 1.0 5.0 2.0) +( 2.0 5.0 2.0) +( 3.0 5.0 2.0) +( 4.0 5.0 2.0) +( 5.0 5.0 2.0) +( 6.0 5.0 2.0) +( 7.0 5.0 2.0) +( 8.0 5.0 2.0) +( 9.0 5.0 2.0) +( 10.0 5.0 2.0) +( 0.0 6.0 2.0) +( 1.0 6.0 2.0) +( 2.0 6.0 2.0) +( 3.0 6.0 2.0) +( 4.0 6.0 2.0) +( 5.0 6.0 2.0) +( 6.0 6.0 2.0) +( 7.0 6.0 2.0) +( 8.0 6.0 2.0) +( 9.0 6.0 2.0) +( 10.0 6.0 2.0) +( 0.0 7.0 2.0) +( 1.0 7.0 2.0) +( 2.0 7.0 2.0) +( 3.0 7.0 2.0) +( 4.0 7.0 2.0) +( 5.0 7.0 2.0) +( 6.0 7.0 2.0) +( 7.0 7.0 2.0) +( 8.0 7.0 2.0) +( 9.0 7.0 2.0) +( 10.0 7.0 2.0) +( 0.0 8.0 2.0) +( 1.0 8.0 2.0) +( 2.0 8.0 2.0) +( 3.0 8.0 2.0) +( 4.0 8.0 2.0) +( 5.0 8.0 2.0) +( 6.0 8.0 2.0) +( 7.0 8.0 2.0) +( 8.0 8.0 2.0) +( 9.0 8.0 2.0) +( 10.0 8.0 2.0) +( 0.0 9.0 2.0) +( 1.0 9.0 2.0) +( 2.0 9.0 2.0) +( 3.0 9.0 2.0) +( 4.0 9.0 2.0) +( 5.0 9.0 2.0) +( 6.0 9.0 2.0) +( 7.0 9.0 2.0) +( 8.0 9.0 2.0) +( 9.0 9.0 2.0) +( 10.0 9.0 2.0) +( 0.0 10.0 2.0) +( 1.0 10.0 2.0) +( 2.0 10.0 2.0) +( 3.0 10.0 2.0) +( 4.0 10.0 2.0) +( 5.0 10.0 2.0) +( 6.0 10.0 2.0) +( 7.0 10.0 2.0) +( 8.0 10.0 2.0) +( 9.0 10.0 2.0) +( 10.0 10.0 2.0) +( 0.0 11.0 2.0) +( 1.0 11.0 2.0) +( 2.0 11.0 2.0) +( 3.0 11.0 2.0) +( 4.0 11.0 2.0) +( 5.0 11.0 2.0) +( 6.0 11.0 2.0) +( 7.0 11.0 2.0) +( 8.0 11.0 2.0) +( 9.0 11.0 2.0) +( 10.0 11.0 2.0) +( 0.0 0.0 3.0) +( 1.0 0.0 3.0) +( 2.0 0.0 3.0) +( 3.0 0.0 3.0) +( 4.0 0.0 3.0) +( 5.0 0.0 3.0) +( 6.0 0.0 3.0) +( 7.0 0.0 3.0) +( 8.0 0.0 3.0) +( 9.0 0.0 3.0) +( 10.0 0.0 3.0) +( 0.0 1.0 3.0) +( 1.0 1.0 3.0) +( 2.0 1.0 3.0) +( 3.0 1.0 3.0) +( 4.0 1.0 3.0) +( 5.0 1.0 3.0) +( 6.0 1.0 3.0) +( 7.0 1.0 3.0) +( 8.0 1.0 3.0) +( 9.0 1.0 3.0) +( 10.0 1.0 3.0) +( 0.0 2.0 3.0) +( 1.0 2.0 3.0) +( 2.0 2.0 3.0) +( 3.0 2.0 3.0) +( 4.0 2.0 3.0) +( 5.0 2.0 3.0) +( 6.0 2.0 3.0) +( 7.0 2.0 3.0) +( 8.0 2.0 3.0) +( 9.0 2.0 3.0) +( 10.0 2.0 3.0) +( 0.0 3.0 3.0) +( 1.0 3.0 3.0) +( 2.0 3.0 3.0) +( 3.0 3.0 3.0) +( 4.0 3.0 3.0) +( 5.0 3.0 3.0) +( 6.0 3.0 3.0) +( 7.0 3.0 3.0) +( 8.0 3.0 3.0) +( 9.0 3.0 3.0) +( 10.0 3.0 3.0) +( 0.0 4.0 3.0) +( 1.0 4.0 3.0) +( 2.0 4.0 3.0) +( 3.0 4.0 3.0) +( 4.0 4.0 3.0) +( 5.0 4.0 3.0) +( 6.0 4.0 3.0) +( 7.0 4.0 3.0) +( 8.0 4.0 3.0) +( 9.0 4.0 3.0) +( 10.0 4.0 3.0) +( 0.0 5.0 3.0) +( 1.0 5.0 3.0) +( 2.0 5.0 3.0) +( 3.0 5.0 3.0) +( 4.0 5.0 3.0) +( 5.0 5.0 3.0) +( 6.0 5.0 3.0) +( 7.0 5.0 3.0) +( 8.0 5.0 3.0) +( 9.0 5.0 3.0) +( 10.0 5.0 3.0) +( 0.0 6.0 3.0) +( 1.0 6.0 3.0) +( 2.0 6.0 3.0) +( 3.0 6.0 3.0) +( 4.0 6.0 3.0) +( 5.0 6.0 3.0) +( 6.0 6.0 3.0) +( 7.0 6.0 3.0) +( 8.0 6.0 3.0) +( 9.0 6.0 3.0) +( 10.0 6.0 3.0) +( 0.0 7.0 3.0) +( 1.0 7.0 3.0) +( 2.0 7.0 3.0) +( 3.0 7.0 3.0) +( 4.0 7.0 3.0) +( 5.0 7.0 3.0) +( 6.0 7.0 3.0) +( 7.0 7.0 3.0) +( 8.0 7.0 3.0) +( 9.0 7.0 3.0) +( 10.0 7.0 3.0) +( 0.0 8.0 3.0) +( 1.0 8.0 3.0) +( 2.0 8.0 3.0) +( 3.0 8.0 3.0) +( 4.0 8.0 3.0) +( 5.0 8.0 3.0) +( 6.0 8.0 3.0) +( 7.0 8.0 3.0) +( 8.0 8.0 3.0) +( 9.0 8.0 3.0) +( 10.0 8.0 3.0) +( 0.0 9.0 3.0) +( 1.0 9.0 3.0) +( 2.0 9.0 3.0) +( 3.0 9.0 3.0) +( 4.0 9.0 3.0) +( 5.0 9.0 3.0) +( 6.0 9.0 3.0) +( 7.0 9.0 3.0) +( 8.0 9.0 3.0) +( 9.0 9.0 3.0) +( 10.0 9.0 3.0) +( 0.0 10.0 3.0) +( 1.0 10.0 3.0) +( 2.0 10.0 3.0) +( 3.0 10.0 3.0) +( 4.0 10.0 3.0) +( 5.0 10.0 3.0) +( 6.0 10.0 3.0) +( 7.0 10.0 3.0) +( 8.0 10.0 3.0) +( 9.0 10.0 3.0) +( 10.0 10.0 3.0) +( 0.0 11.0 3.0) +( 1.0 11.0 3.0) +( 2.0 11.0 3.0) +( 3.0 11.0 3.0) +( 4.0 11.0 3.0) +( 5.0 11.0 3.0) +( 6.0 11.0 3.0) +( 7.0 11.0 3.0) +( 8.0 11.0 3.0) +( 9.0 11.0 3.0) +( 10.0 11.0 3.0) +( 0.0 0.0 4.0) +( 1.0 0.0 4.0) +( 2.0 0.0 4.0) +( 3.0 0.0 4.0) +( 4.0 0.0 4.0) +( 5.0 0.0 4.0) +( 6.0 0.0 4.0) +( 7.0 0.0 4.0) +( 8.0 0.0 4.0) +( 9.0 0.0 4.0) +( 10.0 0.0 4.0) +( 0.0 1.0 4.0) +( 1.0 1.0 4.0) +( 2.0 1.0 4.0) +( 3.0 1.0 4.0) +( 4.0 1.0 4.0) +( 5.0 1.0 4.0) +( 6.0 1.0 4.0) +( 7.0 1.0 4.0) +( 8.0 1.0 4.0) +( 9.0 1.0 4.0) +( 10.0 1.0 4.0) +( 0.0 2.0 4.0) +( 1.0 2.0 4.0) +( 2.0 2.0 4.0) +( 3.0 2.0 4.0) +( 4.0 2.0 4.0) +( 5.0 2.0 4.0) +( 6.0 2.0 4.0) +( 7.0 2.0 4.0) +( 8.0 2.0 4.0) +( 9.0 2.0 4.0) +( 10.0 2.0 4.0) +( 0.0 3.0 4.0) +( 1.0 3.0 4.0) +( 2.0 3.0 4.0) +( 3.0 3.0 4.0) +( 4.0 3.0 4.0) +( 5.0 3.0 4.0) +( 6.0 3.0 4.0) +( 7.0 3.0 4.0) +( 8.0 3.0 4.0) +( 9.0 3.0 4.0) +( 10.0 3.0 4.0) +( 0.0 4.0 4.0) +( 1.0 4.0 4.0) +( 2.0 4.0 4.0) +( 3.0 4.0 4.0) +( 4.0 4.0 4.0) +( 5.0 4.0 4.0) +( 6.0 4.0 4.0) +( 7.0 4.0 4.0) +( 8.0 4.0 4.0) +( 9.0 4.0 4.0) +( 10.0 4.0 4.0) +( 0.0 5.0 4.0) +( 1.0 5.0 4.0) +( 2.0 5.0 4.0) +( 3.0 5.0 4.0) +( 4.0 5.0 4.0) +( 5.0 5.0 4.0) +( 6.0 5.0 4.0) +( 7.0 5.0 4.0) +( 8.0 5.0 4.0) +( 9.0 5.0 4.0) +( 10.0 5.0 4.0) +( 0.0 6.0 4.0) +( 1.0 6.0 4.0) +( 2.0 6.0 4.0) +( 3.0 6.0 4.0) +( 4.0 6.0 4.0) +( 5.0 6.0 4.0) +( 6.0 6.0 4.0) +( 7.0 6.0 4.0) +( 8.0 6.0 4.0) +( 9.0 6.0 4.0) +( 10.0 6.0 4.0) +( 0.0 7.0 4.0) +( 1.0 7.0 4.0) +( 2.0 7.0 4.0) +( 3.0 7.0 4.0) +( 4.0 7.0 4.0) +( 5.0 7.0 4.0) +( 6.0 7.0 4.0) +( 7.0 7.0 4.0) +( 8.0 7.0 4.0) +( 9.0 7.0 4.0) +( 10.0 7.0 4.0) +( 0.0 8.0 4.0) +( 1.0 8.0 4.0) +( 2.0 8.0 4.0) +( 3.0 8.0 4.0) +( 4.0 8.0 4.0) +( 5.0 8.0 4.0) +( 6.0 8.0 4.0) +( 7.0 8.0 4.0) +( 8.0 8.0 4.0) +( 9.0 8.0 4.0) +( 10.0 8.0 4.0) +( 0.0 9.0 4.0) +( 1.0 9.0 4.0) +( 2.0 9.0 4.0) +( 3.0 9.0 4.0) +( 4.0 9.0 4.0) +( 5.0 9.0 4.0) +( 6.0 9.0 4.0) +( 7.0 9.0 4.0) +( 8.0 9.0 4.0) +( 9.0 9.0 4.0) +( 10.0 9.0 4.0) +( 0.0 10.0 4.0) +( 1.0 10.0 4.0) +( 2.0 10.0 4.0) +( 3.0 10.0 4.0) +( 4.0 10.0 4.0) +( 5.0 10.0 4.0) +( 6.0 10.0 4.0) +( 7.0 10.0 4.0) +( 8.0 10.0 4.0) +( 9.0 10.0 4.0) +( 10.0 10.0 4.0) +( 0.0 11.0 4.0) +( 1.0 11.0 4.0) +( 2.0 11.0 4.0) +( 3.0 11.0 4.0) +( 4.0 11.0 4.0) +( 5.0 11.0 4.0) +( 6.0 11.0 4.0) +( 7.0 11.0 4.0) +( 8.0 11.0 4.0) +( 9.0 11.0 4.0) +( 10.0 11.0 4.0) +( 0.0 0.0 5.0) +( 1.0 0.0 5.0) +( 2.0 0.0 5.0) +( 3.0 0.0 5.0) +( 4.0 0.0 5.0) +( 5.0 0.0 5.0) +( 6.0 0.0 5.0) +( 7.0 0.0 5.0) +( 8.0 0.0 5.0) +( 9.0 0.0 5.0) +( 10.0 0.0 5.0) +( 0.0 1.0 5.0) +( 1.0 1.0 5.0) +( 2.0 1.0 5.0) +( 3.0 1.0 5.0) +( 4.0 1.0 5.0) +( 5.0 1.0 5.0) +( 6.0 1.0 5.0) +( 7.0 1.0 5.0) +( 8.0 1.0 5.0) +( 9.0 1.0 5.0) +( 10.0 1.0 5.0) +( 0.0 2.0 5.0) +( 1.0 2.0 5.0) +( 2.0 2.0 5.0) +( 3.0 2.0 5.0) +( 4.0 2.0 5.0) +( 5.0 2.0 5.0) +( 6.0 2.0 5.0) +( 7.0 2.0 5.0) +( 8.0 2.0 5.0) +( 9.0 2.0 5.0) +( 10.0 2.0 5.0) +( 0.0 3.0 5.0) +( 1.0 3.0 5.0) +( 2.0 3.0 5.0) +( 3.0 3.0 5.0) +( 4.0 3.0 5.0) +( 5.0 3.0 5.0) +( 6.0 3.0 5.0) +( 7.0 3.0 5.0) +( 8.0 3.0 5.0) +( 9.0 3.0 5.0) +( 10.0 3.0 5.0) +( 0.0 4.0 5.0) +( 1.0 4.0 5.0) +( 2.0 4.0 5.0) +( 3.0 4.0 5.0) +( 4.0 4.0 5.0) +( 5.0 4.0 5.0) +( 6.0 4.0 5.0) +( 7.0 4.0 5.0) +( 8.0 4.0 5.0) +( 9.0 4.0 5.0) +( 10.0 4.0 5.0) +( 0.0 5.0 5.0) +( 1.0 5.0 5.0) +( 2.0 5.0 5.0) +( 3.0 5.0 5.0) +( 4.0 5.0 5.0) +( 5.0 5.0 5.0) +( 6.0 5.0 5.0) +( 7.0 5.0 5.0) +( 8.0 5.0 5.0) +( 9.0 5.0 5.0) +( 10.0 5.0 5.0) +( 0.0 6.0 5.0) +( 1.0 6.0 5.0) +( 2.0 6.0 5.0) +( 3.0 6.0 5.0) +( 4.0 6.0 5.0) +( 5.0 6.0 5.0) +( 6.0 6.0 5.0) +( 7.0 6.0 5.0) +( 8.0 6.0 5.0) +( 9.0 6.0 5.0) +( 10.0 6.0 5.0) +( 0.0 7.0 5.0) +( 1.0 7.0 5.0) +( 2.0 7.0 5.0) +( 3.0 7.0 5.0) +( 4.0 7.0 5.0) +( 5.0 7.0 5.0) +( 6.0 7.0 5.0) +( 7.0 7.0 5.0) +( 8.0 7.0 5.0) +( 9.0 7.0 5.0) +( 10.0 7.0 5.0) +( 0.0 8.0 5.0) +( 1.0 8.0 5.0) +( 2.0 8.0 5.0) +( 3.0 8.0 5.0) +( 4.0 8.0 5.0) +( 5.0 8.0 5.0) +( 6.0 8.0 5.0) +( 7.0 8.0 5.0) +( 8.0 8.0 5.0) +( 9.0 8.0 5.0) +( 10.0 8.0 5.0) +( 0.0 9.0 5.0) +( 1.0 9.0 5.0) +( 2.0 9.0 5.0) +( 3.0 9.0 5.0) +( 4.0 9.0 5.0) +( 5.0 9.0 5.0) +( 6.0 9.0 5.0) +( 7.0 9.0 5.0) +( 8.0 9.0 5.0) +( 9.0 9.0 5.0) +( 10.0 9.0 5.0) +( 0.0 10.0 5.0) +( 1.0 10.0 5.0) +( 2.0 10.0 5.0) +( 3.0 10.0 5.0) +( 4.0 10.0 5.0) +( 5.0 10.0 5.0) +( 6.0 10.0 5.0) +( 7.0 10.0 5.0) +( 8.0 10.0 5.0) +( 9.0 10.0 5.0) +( 10.0 10.0 5.0) +( 0.0 11.0 5.0) +( 1.0 11.0 5.0) +( 2.0 11.0 5.0) +( 3.0 11.0 5.0) +( 4.0 11.0 5.0) +( 5.0 11.0 5.0) +( 6.0 11.0 5.0) +( 7.0 11.0 5.0) +( 8.0 11.0 5.0) +( 9.0 11.0 5.0) +( 10.0 11.0 5.0) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +blocks +( + + //block 0 +hex (0 1 12 11 132 133 144 143 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 1 +hex (1 2 13 12 133 134 145 144 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 2 +hex (2 3 14 13 134 135 146 145 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 3 +hex (3 4 15 14 135 136 147 146 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 4 +hex (4 5 16 15 136 137 148 147 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 5 +hex (5 6 17 16 137 138 149 148 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 6 +hex (6 7 18 17 138 139 150 149 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 7 +hex (7 8 19 18 139 140 151 150 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 8 +hex (8 9 20 19 140 141 152 151 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 9 +hex (9 10 21 20 141 142 153 152 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 10 +hex (141 142 153 152 273 274 285 284 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 11 +hex (273 274 285 284 405 406 417 416 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 12 +hex (405 406 417 416 537 538 549 548 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 13 +hex (537 538 549 548 669 670 681 680 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 14 +hex (536 537 548 547 668 669 680 679 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 15 +hex (535 536 547 546 667 668 679 678 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 16 +hex (534 535 546 545 666 667 678 677 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 17 +hex (533 534 545 544 665 666 677 676 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 18 +hex (532 533 544 543 664 665 676 675 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 19 +hex (531 532 543 542 663 664 675 674 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 20 +hex (530 531 542 541 662 663 674 673 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 21 +hex (529 530 541 540 661 662 673 672 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 22 +hex (528 529 540 539 660 661 672 671 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 23 +hex (539 540 551 550 671 672 683 682 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 24 +hex (550 551 562 561 682 683 694 693 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 25 +hex (561 562 573 572 693 694 705 704 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 26 +hex (572 573 584 583 704 705 716 715 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 27 +hex (583 584 595 594 715 716 727 726 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 28 +hex (594 595 606 605 726 727 738 737 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 29 +hex (605 606 617 616 737 738 749 748 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 30 +hex (616 617 628 627 748 749 760 759 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 31 +hex (627 628 639 638 759 760 771 770 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 32 +hex (638 639 650 649 770 771 782 781 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 33 +hex (440 441 452 451 572 573 584 583 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 34 +hex (308 309 320 319 440 441 452 451 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 35 +hex (176 177 188 187 308 309 320 319 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 36 +hex (44 45 56 55 176 177 188 187 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 37 +hex (55 56 67 66 187 188 199 198 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 38 +hex (66 67 78 77 198 199 210 209 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 39 +hex (77 78 89 88 209 210 221 220 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 40 +hex (88 89 100 99 220 221 232 231 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 41 +hex (99 100 111 110 231 232 243 242 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 42 +hex (110 111 122 121 242 243 254 253 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 43 +hex (33 34 45 44 165 166 177 176 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 44 +hex (22 23 34 33 154 155 166 165 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 45 +hex (11 12 23 22 143 144 155 154 ) +( 10 10 10 ) +SimpleGrading (1 1 1) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +defaultPatch +{ type wall;} + +patches +( +); diff --git a/tutorial_cases/loop_reactor_mixing_static/system/controlDict b/tutorial_cases/loop_reactor_mixing_static/system/controlDict new file mode 100644 index 00000000..f4665ed8 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/controlDict @@ -0,0 +1,66 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt writeNow;//endTime; + +endTime 200; + +deltaT 0.0001; + +writeControl adjustableRunTime; + +writeInterval 2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.5; + +maxDeltaT 0.01; + + +functions +{ + + #includeFunc writeObjects(d.gas) + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) + #includeFunc writeObjects(thermo:mu.liquid) + #includeFunc writeObjects(thermo:mu.gas) + #includeFunc fieldAverage(U.air, U.water, alpha.air, p) +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/system/decomposeParDict b/tutorial_cases/loop_reactor_mixing_static/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/system/fvConstraints b/tutorial_cases/loop_reactor_mixing_static/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/system/fvSchemes b/tutorial_cases/loop_reactor_mixing_static/system/fvSchemes new file mode 100644 index 00000000..52e6e13a --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/fvSchemes @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + limited cellLimited Gauss linear 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + "div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + "div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon)m\)" Gauss upwind; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default uncorrected; +} + +wallDist +{ + method Poisson; + nRequired true; +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/system/fvSolution b/tutorial_cases/loop_reactor_mixing_static/system/fvSolution new file mode 100644 index 00000000..2e69fdfa --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/fvSolution @@ -0,0 +1,120 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 0; + minIter 1; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + minIter 0; + maxIter 3; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 0; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/system/inlets_outlets.json b/tutorial_cases/loop_reactor_mixing_static/system/inlets_outlets.json new file mode 100644 index 00000000..a083d47f --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/inlets_outlets.json @@ -0,0 +1,177 @@ +{ + "Geometry": { + "OverallDomain": { + "x": { + "nblocks": 10, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "y": { + "nblocks": 11, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "z": { + "nblocks": 5, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + } + }, + "Fluids": [ + [ + [ + 0, + 0, + 0 + ], + [ + 9, + 0, + 0 + ] + ], + [ + [ + 9, + 0, + 0 + ], + [ + 9, + 0, + 4 + ] + ], + [ + [ + 9, + 0, + 4 + ], + [ + 0, + 0, + 4 + ] + ], + [ + [ + 0, + 1, + 4 + ], + [ + 0, + 4, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 10, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 4, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 10, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 1, + 0 + ] + ] + ] + }, + "inlets": [ + { + "branch_id": 0, + "type": "circle", + "frac_space": 0.2, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 1, + "type": "circle", + "frac_space": 0.2, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 1, + "type": "circle", + "frac_space": 0.8, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + }, + { + "branch_id": 2, + "type": "circle", + "frac_space": 0.8, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "bottom" + } + ], + "outlets": [ + { + "branch_id": 6, + "type": "circle", + "frac_space": 1, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "top" + }, + { + "branch_id": 4, + "type": "circle", + "frac_space": 1, + "normal_dir": 1, + "radius": 0.4, + "nelements": 50, + "block_pos": "top" + } + ] +} \ No newline at end of file diff --git a/tutorial_cases/loop_reactor_mixing_static/system/mesh.json b/tutorial_cases/loop_reactor_mixing_static/system/mesh.json new file mode 100644 index 00000000..29841d7e --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/mesh.json @@ -0,0 +1,26 @@ +{ + "Meshing": { + "Blockwise": { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0}, + "y" : {"nblocks": 11, "size_per_block": 1.0}, + "z" : {"nblocks": 5, "size_per_block": 1.0} + }, + "Fluids": [ + [ [0,0,0], [9,0,0] ], + [ [9,0,0], [9,0,4] ], + [ [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4] ], + [ [0,4,4], [0,10,4] ], + [ [0,4,4], [0,4,0] ], + [ [0,4,0], [0,10,0] ], + [ [0,4,0], [0,1,0] ] + ] + } +} diff --git a/tutorial_cases/loop_reactor_mixing_static/system/mixers.json b/tutorial_cases/loop_reactor_mixing_static/system/mixers.json new file mode 100644 index 00000000..87557d6b --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/mixers.json @@ -0,0 +1,148 @@ +{ + "Meshing": { + "Blockwise": { + "x": 10, + "y": 10, + "z": 10 + } + }, + "Geometry": { + "OverallDomain": { + "x": { + "nblocks": 10, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "y": { + "nblocks": 11, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + }, + "z": { + "nblocks": 5, + "size_per_block": 1.0, + "rescale": 2.7615275385627096 + } + }, + "Fluids": [ + [ + [ + 0, + 0, + 0 + ], + [ + 9, + 0, + 0 + ] + ], + [ + [ + 9, + 0, + 0 + ], + [ + 9, + 0, + 4 + ] + ], + [ + [ + 9, + 0, + 4 + ], + [ + 0, + 0, + 4 + ] + ], + [ + [ + 0, + 1, + 4 + ], + [ + 0, + 4, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 10, + 4 + ] + ], + [ + [ + 0, + 4, + 4 + ], + [ + 0, + 4, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 10, + 0 + ] + ], + [ + [ + 0, + 4, + 0 + ], + [ + 0, + 1, + 0 + ] + ] + ] + }, + "static_mixers": [ + { + "branch_id": 0, + "frac_space": 0.4, + "start_time": 1, + "sign": "+", + "swirl_sign": "+", + "radius": 0.4, + "S": 0.35, + "K": 0.5 + }, + { + "branch_id": 2, + "frac_space": 0.4, + "start_time": 1, + "sign": "-", + "swirl_sign": "-", + "radius": 0.4, + "S": 0.35, + "K": 0.5 + } + ] +} \ No newline at end of file diff --git a/tutorial_cases/loop_reactor_mixing_static/system/setFieldsDict b/tutorial_cases/loop_reactor_mixing_static/system/setFieldsDict new file mode 100644 index 00000000..89a797b9 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/system/setFieldsDict @@ -0,0 +1,37 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (552.3 11.046 552.3); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/tutorial_cases/loop_reactor_mixing_static/writeGlobalVars.py b/tutorial_cases/loop_reactor_mixing_static/writeGlobalVars.py new file mode 100644 index 00000000..e64d69e3 --- /dev/null +++ b/tutorial_cases/loop_reactor_mixing_static/writeGlobalVars.py @@ -0,0 +1,42 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + if line.startswith("inletA"): + f.write(f"inletA\t{inletA:g};\n") + elif line.startswith("liqVol"): + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + V = getLiqVol() + writeGvars(A, V) diff --git a/tutorial_cases/runall.sh b/tutorial_cases/runall.sh index 894373a2..31e971fb 100644 --- a/tutorial_cases/runall.sh +++ b/tutorial_cases/runall.sh @@ -46,6 +46,10 @@ cd ../../ cd tutorial_cases/loop_reactor_mixing_swirl bash run.sh cd ../../ +## Run mixing loop reactor with static mixer tutorial +cd tutorial_cases/loop_reactor_mixing_static +bash run.sh +cd ../../ ## Run airlift reactor tutorial cd tutorial_cases/airlift_40m bash run.sh From e5f1debeb125c0dedabaddc28297db856f2212bf Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 7 Aug 2026 11:42:18 -0600 Subject: [PATCH 21/52] sign issue --- bird/preprocess/dynamic_mixer/io_fvModels.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index 845424ad..f8b02d38 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -512,7 +512,7 @@ def write_mixer_ball( f.write("\t\t\t\t\t\tif (Sax > 1e-30)\n") f.write("\t\t\t\t\t\t{\n") f.write("\t\t\t\t\t\t\tconst double fax = Tax/Sax*alphaL[i]*g;\n") - f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {push_ax}*fax*V[i];\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] -= {push_ax}*fax*V[i];\n") f.write("\t\t\t\t\t\t}\n") if swirl: f.write( @@ -522,10 +522,10 @@ def write_mixer_ball( f.write("\t\t\t\t\t\t{\n") f.write("\t\t\t\t\t\t\tconst double fth = Qsw/Sth*alphaL[i]*g;\n") f.write( - f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] += {push_th}*fth*V[i]*(({tan[0][1]})/rr);\n" + f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] -= {push_th}*fth*V[i]*(({tan[0][1]})/rr);\n" ) f.write( - f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] += {push_th}*fth*V[i]*(({tan[1][1]})/rr);\n" + f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] -= {push_th}*fth*V[i]*(({tan[1][1]})/rr);\n" ) f.write("\t\t\t\t\t\t}\n") f.write("\t\t\t\t\t}\n") @@ -645,7 +645,7 @@ def write_static_mixer_ball(mixer, output_folder): f.write("\t\t\t\t\t\tif (Sax > 1e-30)\n") f.write("\t\t\t\t\t\t{\n") f.write("\t\t\t\t\t\t\tconst double fvisc = Tls/Sax*alphaL[i]*g;\n") - f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {drag_ax}*fvisc*V[i];\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] -= {drag_ax}*fvisc*V[i];\n") f.write("\t\t\t\t\t\t}\n") # swirl + energy-neutral axial reaction (local, velocity-weighted) f.write( @@ -662,15 +662,15 @@ def write_static_mixer_ball(mixer, output_folder): "\t\t\t\t\t\t\tconst double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g;\n" ) f.write( - f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] += {push_th}*fsw*V[i]*(({tan[0][1]})/rr);\n" + f"\t\t\t\t\t\t\tUsource[i][{tan[0][0]}] -= {push_th}*fsw*V[i]*(({tan[0][1]})/rr);\n" ) f.write( - f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] += {push_th}*fsw*V[i]*(({tan[1][1]})/rr);\n" + f"\t\t\t\t\t\t\tUsource[i][{tan[1][0]}] -= {push_th}*fsw*V[i]*(({tan[1][1]})/rr);\n" ) f.write( "\t\t\t\t\t\t\tconst double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g;\n" ) - f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] += {cp_th}*fcp*V[i];\n") + f.write(f"\t\t\t\t\t\t\tUsource[i][{nd}] -= {cp_th}*fcp*V[i];\n") f.write("\t\t\t\t\t\t}\n") f.write("\t\t\t\t\t}\n") f.write("\t\t\t\t}\n") From 8d596d7bed351104df09d90b79f8575a457b0b34 Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 18 Aug 2026 10:36:11 -0600 Subject: [PATCH 22/52] source is -= --- tests/preprocess/test_static_mixer.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py index 20b11da3..cbfa52ae 100644 --- a/tests/preprocess/test_static_mixer.py +++ b/tests/preprocess/test_static_mixer.py @@ -114,11 +114,13 @@ def test_write_static_mixer_ball(): # energy-neutral axial reaction f_cp ~ rho*ux*uth assert "const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g;" in txt # normal_dir=1 -> theta_hat = (dz/rr, 0, -dx/rr); swirl on components 0 and 2 - assert "Usource[i][0] += 1.0*fsw*V[i]*((dz)/rr);" in txt - assert "Usource[i][2] += 1.0*fsw*V[i]*((-dx)/rr);" in txt + # Usource -= B applies body force +B (adds B to the RHS), so the deposition + # is emitted with -= and the pre-combined sign literals. + assert "Usource[i][0] -= 1.0*fsw*V[i]*((dz)/rr);" in txt + assert "Usource[i][2] -= 1.0*fsw*V[i]*((-dx)/rr);" in txt # axial reaction and viscous drag on the normal component (index 1) - assert "Usource[i][1] += -1.0*fcp*V[i];" in txt - assert "Usource[i][1] += -1.0*fvisc*V[i];" in txt + assert "Usource[i][1] -= -1.0*fcp*V[i];" in txt + assert "Usource[i][1] -= -1.0*fvisc*V[i];" in txt def test_write_static_mixer_ball_negative_orientation(): @@ -148,9 +150,9 @@ def test_write_static_mixer_ball_negative_orientation(): txt = Path(tmpdirname, "fvModels").read_text() assert "--1.0" not in txt # no decrement-on-literal - # -push_ax and -push_th collapse to +1.0 for the negative orientation - assert "Usource[i][1] += 1.0*fvisc*V[i];" in txt - assert "Usource[i][1] += 1.0*fcp*V[i];" in txt + # drag_ax and cp_th are +1.0 for the negative orientation + assert "Usource[i][1] -= 1.0*fvisc*V[i];" in txt + assert "Usource[i][1] -= 1.0*fcp*V[i];" in txt def test_write_fvModel_static_mixers(): From 4024b107cd8b6a96174410e992e8a037f508c68c Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 18 Aug 2026 10:50:14 -0600 Subject: [PATCH 23/52] regen fvModels --- .../constant/fvModels | 16 ++++++------- .../constant/fvModels | 24 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tutorial_cases/loop_reactor_mixing_static/constant/fvModels b/tutorial_cases/loop_reactor_mixing_static/constant/fvModels index 268773e7..6b37fb16 100644 --- a/tutorial_cases/loop_reactor_mixing_static/constant/fvModels +++ b/tutorial_cases/loop_reactor_mixing_static/constant/fvModels @@ -90,7 +90,7 @@ codedSource if (Sax > 1e-30) { const double fvisc = Tls/Sax*alphaL[i]*g; - Usource[i][0] += -1.0*fvisc*V[i]; + Usource[i][0] -= -1.0*fvisc*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Ssw > 1e-30) @@ -99,10 +99,10 @@ codedSource const double uth = UL[i][1]*((-dz)/rr) + UL[i][2]*((dy)/rr); const double A0 = Qsw/Ssw; const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; - Usource[i][1] += 1.0*fsw*V[i]*((-dz)/rr); - Usource[i][2] += 1.0*fsw*V[i]*((dy)/rr); + Usource[i][1] -= 1.0*fsw*V[i]*((-dz)/rr); + Usource[i][2] -= 1.0*fsw*V[i]*((dy)/rr); const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; - Usource[i][0] += -1.0*fcp*V[i]; + Usource[i][0] -= -1.0*fcp*V[i]; } } } @@ -165,7 +165,7 @@ codedSource if (Sax > 1e-30) { const double fvisc = Tls/Sax*alphaL[i]*g; - Usource[i][0] += 1.0*fvisc*V[i]; + Usource[i][0] -= 1.0*fvisc*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Ssw > 1e-30) @@ -174,10 +174,10 @@ codedSource const double uth = UL[i][1]*((-dz)/rr) + UL[i][2]*((dy)/rr); const double A0 = Qsw/Ssw; const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; - Usource[i][1] += -1.0*fsw*V[i]*((-dz)/rr); - Usource[i][2] += -1.0*fsw*V[i]*((dy)/rr); + Usource[i][1] -= -1.0*fsw*V[i]*((-dz)/rr); + Usource[i][2] -= -1.0*fsw*V[i]*((dy)/rr); const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; - Usource[i][0] += 1.0*fcp*V[i]; + Usource[i][0] -= 1.0*fcp*V[i]; } } } diff --git a/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels b/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels index 8bad277c..51497b7c 100644 --- a/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels +++ b/tutorial_cases/loop_reactor_mixing_swirl/constant/fvModels @@ -99,14 +99,14 @@ codedSource if (Sax > 1e-30) { const double fax = Tax/Sax*alphaL[i]*g; - Usource[i][0] += 1.0*fax*V[i]; + Usource[i][0] -= 1.0*fax*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Sth > 1e-30) { const double fth = Qsw/Sth*alphaL[i]*g; - Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); - Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + Usource[i][1] -= 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] -= 1.0*fth*V[i]*((dy)/rr); } } } @@ -178,14 +178,14 @@ codedSource if (Sax > 1e-30) { const double fax = Tax/Sax*alphaL[i]*g; - Usource[i][0] += 1.0*fax*V[i]; + Usource[i][0] -= 1.0*fax*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Sth > 1e-30) { const double fth = Qsw/Sth*alphaL[i]*g; - Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); - Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + Usource[i][1] -= 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] -= 1.0*fth*V[i]*((dy)/rr); } } } @@ -257,14 +257,14 @@ codedSource if (Sax > 1e-30) { const double fax = Tax/Sax*alphaL[i]*g; - Usource[i][0] += 1.0*fax*V[i]; + Usource[i][0] -= 1.0*fax*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Sth > 1e-30) { const double fth = Qsw/Sth*alphaL[i]*g; - Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); - Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + Usource[i][1] -= 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] -= 1.0*fth*V[i]*((dy)/rr); } } } @@ -336,14 +336,14 @@ codedSource if (Sax > 1e-30) { const double fax = Tax/Sax*alphaL[i]*g; - Usource[i][0] += -1.0*fax*V[i]; + Usource[i][0] -= -1.0*fax*V[i]; } const double rr = std::sqrt(d2-(dx)*(dx)); if (rr > 1e-3*Rmix && Sth > 1e-30) { const double fth = Qsw/Sth*alphaL[i]*g; - Usource[i][1] += 1.0*fth*V[i]*((-dz)/rr); - Usource[i][2] += 1.0*fth*V[i]*((dy)/rr); + Usource[i][1] -= 1.0*fth*V[i]*((-dz)/rr); + Usource[i][2] -= 1.0*fth*V[i]*((dy)/rr); } } } From 6525f17dbbd4936311aceed3e8861df896992f5c Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 19 Aug 2026 15:36:21 -0600 Subject: [PATCH 24/52] add per level timestepping option --- bird/preprocess/json_gen/generate_designs.py | 26 ++++++++ tests/preprocess/test_case_gen.py | 62 ++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 57cbb5f3..a48a6858 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -674,6 +674,24 @@ def overwrite_ncores(case_folder, n): f.write(line) +def overwrite_controldict(case_folder, params): + """Rewrite time-stepping entries in system/controlDict. + + :param params: dict with any of ``deltaT``, ``endTime``, ``maxCo``, + ``maxDeltaT``; each present key overwrites its scalar entry. + """ + filename = os.path.join(case_folder, "system", "controlDict") + with open(filename, "r+") as f: + lines = f.readlines() + with open(filename, "w+") as f: + for line in lines: + key = line.strip().split(None, 1)[0] if line.strip() else "" + if key in params: + f.write(f"{key:<16}{params[key]};\n") + else: + f.write(line) + + def write_script_single( case_folder, account="gas2fuels", @@ -782,6 +800,7 @@ def generate_leveled_reactor_cases( account="gas2fuels", cores_per_sim=16, cores_per_node=128, + controldict_params=None, ): """Generate one scale level of the actuator-disk (ball) design sweep. @@ -799,6 +818,11 @@ def generate_leveled_reactor_cases( Each sim runs on `cores_per_sim` cores; the node-packing bundles fit ``cores_per_node // cores_per_sim`` sims per node. + + `controldict_params`, when given, is a dict of ``system/controlDict`` + scalar entries (any of ``deltaT``, ``endTime``, ``maxCo``, ``maxDeltaT``) + written into every case of this level via :func:`overwrite_controldict`; + left ``None`` the template controlDict is used unchanged. """ if not os.path.isabs(template_folder): template_folder = os.path.join( @@ -912,6 +936,8 @@ def generate_leveled_reactor_cases( cstar_h2=cstar_h2, ) overwrite_ncores(case_folder=case, n=cores_per_sim) + if controldict_params is not None: + overwrite_controldict(case_folder=case, params=controldict_params) overwrite_bubble_size_model(case_folder=case, constantD=constantD) write_script_single(case, account=account, cores=cores_per_sim) write_script_post_single(case, account=account) diff --git a/tests/preprocess/test_case_gen.py b/tests/preprocess/test_case_gen.py index fbb15b26..a47c86da 100644 --- a/tests/preprocess/test_case_gen.py +++ b/tests/preprocess/test_case_gen.py @@ -129,3 +129,65 @@ def random_sample(branches_com, branchcom_spots, config_dict={}): save_config_dict( f"{study_folder}/branchcom_spots.pkl", branchcom_spots ) + + +def test_overwrite_controldict(): + + template_control_dict = os.path.join( + Path(__file__).parent, + "..", + "..", + "bird", + "preprocess", + "data_case_gen", + "loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup", + "system", + "controlDict", + ) + + def read_scalars(control_dict_path): + scalars = {} + with open(control_dict_path, "r") as f: + for line in f: + tokens = line.strip().rstrip(";").split() + if len(tokens) == 2 and tokens[0] in ( + "deltaT", + "endTime", + "maxCo", + "maxDeltaT", + ): + scalars[tokens[0]] = tokens[1] + return scalars + + # a full params dict is applied verbatim to a fresh case copy + params = { + "maxCo": "0.25", + "maxDeltaT": "0.00025", + "deltaT": "1e-5", + "endTime": "100", + } + with tempfile.TemporaryDirectory() as tmpdirname: + case = os.path.join(tmpdirname, "case") + os.makedirs(os.path.join(case, "system")) + shutil.copy( + template_control_dict, + os.path.join(case, "system", "controlDict"), + ) + overwrite_controldict(case, params) + written = read_scalars(os.path.join(case, "system", "controlDict")) + assert written == params + + # a partial params dict overwrites only the keys it names + with tempfile.TemporaryDirectory() as tmpdirname: + case = os.path.join(tmpdirname, "case") + os.makedirs(os.path.join(case, "system")) + shutil.copy( + template_control_dict, + os.path.join(case, "system", "controlDict"), + ) + before = read_scalars(os.path.join(case, "system", "controlDict")) + overwrite_controldict(case, {"endTime": "50"}) + after = read_scalars(os.path.join(case, "system", "controlDict")) + assert after["endTime"] == "50" + assert after["deltaT"] == before["deltaT"] + assert after["maxCo"] == before["maxCo"] From 225384232aa89ac36350f2ef342e60945669c85d Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 19 Aug 2026 15:41:53 -0600 Subject: [PATCH 25/52] robust template folder resolution --- bird/preprocess/json_gen/generate_designs.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index a48a6858..77a8ab36 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -824,9 +824,20 @@ def generate_leveled_reactor_cases( written into every case of this level via :func:`overwrite_controldict`; left ``None`` the template controlDict is used unchanged. """ - if not os.path.isabs(template_folder): - template_folder = os.path.join( - BIRD_DIR, "preprocess", "data_case_gen", template_folder + # Resolve template_folder: use it if it points at a real directory (an + # absolute path or one relative to the cwd, e.g. "./template_kom"); + # otherwise fall back to a template bundled under data_case_gen. + bundled = os.path.join( + BIRD_DIR, "preprocess", "data_case_gen", template_folder + ) + if os.path.isdir(template_folder): + template_folder = os.path.abspath(template_folder) + elif os.path.isdir(bundled): + template_folder = bundled + else: + raise FileNotFoundError( + f"template_folder not found: {template_folder!r} is not a " + f"directory, nor is {bundled!r}" ) geom_dict = make_default_geom_dict_from_file( os.path.join(template_folder, "system", "mesh.json") From d14d7890c1b79c216a0cc0fba4a5a71fec4fa067 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 20 Aug 2026 12:01:05 -0600 Subject: [PATCH 26/52] make sure outlets are read from template json --- bird/preprocess/json_gen/generate_designs.py | 30 +++---- tests/preprocess/test_case_gen.py | 84 ++++++++++++++++++++ 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 77a8ab36..71002048 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -1,3 +1,4 @@ +import json import os import pickle import shutil @@ -705,7 +706,7 @@ def write_script_single( f.write("#SBATCH --job-name=lev_single\n") f.write("#SBATCH --nodes=1\n") f.write(f"#SBATCH --ntasks-per-node={cores}\n") - f.write("#SBATCH --time=07:59:00\n") + f.write("#SBATCH --time=47:59:00\n") f.write(f"#SBATCH --account={account}\n\n") f.write("bash presteps.sh\n") f.write(f"source {ofbashrc}\n") @@ -759,7 +760,7 @@ def write_pack_scripts( f.write(f"#SBATCH --job-name=lev_{pack_name}\n") f.write("#SBATCH --nodes=1\n") f.write("#SBATCH --exclusive\n") - f.write("#SBATCH --time=07:59:00\n") + f.write("#SBATCH --time=47:59:00\n") f.write(f"#SBATCH --account={account}\n\n") f.write(f"source {ofbashrc}\n\n") f.write("run_sim () {\n") @@ -864,19 +865,18 @@ def generate_leveled_reactor_cases( case = os.path.join(study_folder, sim_folder) shutil.copytree(template_folder, case) - bc_dict = {"inlets": [], "outlets": []} - for br in (6, 4): - bc_dict["outlets"].append( - { - "branch_id": br, - "type": "circle", - "frac_space": 1, - "normal_dir": 1, - "radius": 0.4, - "nelements": 50, - "block_pos": "top", - } - ) + # Outlets are template-driven: read from the template's + # inlets_outlets.json so each head shape carries its own outlet -- the + # square-head templates define a full-face rectangle covering the whole + # top patch, while the baseline templates define the two disk outlets on + # branches 6 and 4. Inlets stay config-driven, built below. + with open( + os.path.join(template_folder, "system", "inlets_outlets.json") + ) as f: + bc_dict = { + "inlets": [], + "outlets": json.load(f).get("outlets", []), + } for branch in (0, 1, 2): for iind in np.argwhere(config_dict[sim_id][branch] == 1)[:, 0]: bc_dict["inlets"].append( diff --git a/tests/preprocess/test_case_gen.py b/tests/preprocess/test_case_gen.py index a47c86da..f060c61e 100644 --- a/tests/preprocess/test_case_gen.py +++ b/tests/preprocess/test_case_gen.py @@ -1,3 +1,4 @@ +import json import os import pickle import shutil @@ -131,6 +132,89 @@ def random_sample(branches_com, branchcom_spots, config_dict={}): ) +def test_generate_leveled_reactor_cases(): + # Outlets must be template-driven (read from the template's + # inlets_outlets.json), not hardcoded: a template carrying a distinctive + # full-face rectangle outlet must reproduce that rectangle in every + # generated case. Under the old hardcoded (branch 6 & 4 disks) path this + # assertion fails. + BIRD_CASE_GEN_DATA_DIR = os.path.join( + Path(__file__).parent, + "..", + "..", + "bird", + "preprocess", + "data_case_gen", + ) + bundled = os.path.join( + BIRD_CASE_GEN_DATA_DIR, + "loop_reactor_pbe_dynmix_nonstat_headbranch_scaleup", + ) + rectangle = { + "type": "rectangle", + "normal_dir": 1, + "centx": 0.5, + "centy": 11.0, + "centz": 2.5, + "width": 3.0, + "height": 7.0, + } + + branchcom_spots = { + 0: np.linspace(0.2, 0.8, 4), + 1: np.linspace(0.2, 0.8, 3), + 2: np.linspace(0.2, 0.8, 4), + } + branches_com = [0, 1, 2] + config_dict = {} + for _ in range(10): + config = { + b: np.random.choice([0, 1, 2], size=len(branchcom_spots[b])) + for b in branches_com + } + if check_config(config): + config_dict[len(config_dict)] = config + if len(config_dict) >= 1: + break + mixer_params = { + "Np": 6, + "Vtip": 1.5, + "sigma": 0.35, + "radius": 0.4, + "sign": {0: "+", 1: "+", 2: "-"}, + "swirl_sign": {0: "+", 1: "+", 2: "-"}, + } + + with tempfile.TemporaryDirectory() as tmpdirname: + # a template whose outlet differs from the old hardcoded disks + template = os.path.join(tmpdirname, "template") + shutil.copytree(bundled, template) + io_path = os.path.join(template, "system", "inlets_outlets.json") + with open(io_path) as f: + io = json.load(f) + io["outlets"] = [rectangle] + with open(io_path, "w") as f: + json.dump(io, f) + + study = os.path.join(tmpdirname, "study") + generate_leveled_reactor_cases( + config_dict, + branchcom_spots, + scale=0.05, + n_sim=1, + study_folder=study, + mixer_params=mixer_params, + template_folder=template, + constantD=True, + start_time=1, + ) + with open( + os.path.join(study, "Sim_0000", "system", "inlets_outlets.json") + ) as f: + generated = json.load(f) + assert generated["outlets"] == [rectangle] + + def test_overwrite_controldict(): template_control_dict = os.path.join( From da321fc2b80dd4979b4e8fc2b6ed39e259f37520 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 21 Aug 2026 17:39:06 -0600 Subject: [PATCH 27/52] use random sampling or shared pool depending on if we need to compute correlations --- bird/preprocess/json_gen/generate_designs.py | 88 +++++++++++++++++++- tests/preprocess/test_case_gen.py | 69 +++++++++++++++ 2 files changed, 153 insertions(+), 4 deletions(-) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 71002048..0ff5d5aa 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -43,6 +43,12 @@ def compare_config(config1, config2): def check_config(config): + """Accept a design only if it has at least one sparger. + + Choice value ``1`` marks a sparger (a bottom gas inlet); ``0`` a mixer, + ``2`` nothing. A design with no sparger is rejected, so + :func:`sample_placement_designs` never keeps one. + """ success = False inlet_exist = False for key in config: @@ -67,6 +73,73 @@ def load_config_dict(filename): return config_dict +def sample_placement_designs( + branches_com, + branchcom_spots, + n_designs, + choices=(0, 1, 2), + max_attempts=1_000_000, +): + """Randomly sample `n_designs` distinct, valid placement designs. + + Draws are non-deterministic (the caller must NOT seed for reproducibility). + Each design maps ``branch_id -> array`` of per-spot choices; + :func:`check_config` keeps only designs with at least one inlet and + :func:`compare_config` rejects duplicates. Keys are contiguous ``0..n-1``. + + :param branches_com: branch ids on which choices are placed. + :param branchcom_spots: ``branch_id -> array`` of candidate spot fractions. + :param n_designs: number of distinct valid designs to return. + :param choices: per-spot categorical choices (e.g. mixer/sparger/none). + :param max_attempts: give up after this many draws. + """ + config_dict = {} + attempts = 0 + while len(config_dict) < n_designs and attempts < max_attempts: + config = { + b: np.random.choice(choices, size=len(branchcom_spots[b])) + for b in branches_com + } + attempts += 1 + if any(compare_config(config_dict[k], config) for k in config_dict): + continue + if check_config(config): + config_dict[len(config_dict)] = config + if len(config_dict) < n_designs: + raise RuntimeError( + f"only found {len(config_dict)} designs in {attempts} attempts" + ) + return config_dict + + +def load_or_sample_designs( + design_file, + branches_com, + branchcom_spots, + n_designs, + choices=(0, 1, 2), +): + """Borrow designs from `design_file` if it exists, else sample and save. + + The first sweep run samples a fresh random design set (see + :func:`sample_placement_designs`) and pickles it to `design_file`; every + later sweep pointed at the same file loads it instead of re-sampling, so + ``Sim_i`` is the same design across all sweeps without relying on a fixed + seed. `design_file` should hold enough designs for the largest sweep -- + downstream slicing (``sorted(config_dict)[:n_sim]``) selects the first + `n_sim`. + """ + if os.path.exists(design_file): + logger.info(f"Borrowing designs from existing {design_file}") + return load_config_dict(design_file) + logger.info(f"Sampling {n_designs} designs and saving to {design_file}") + config_dict = sample_placement_designs( + branches_com, branchcom_spots, n_designs, choices=choices + ) + save_config_dict(design_file, config_dict) + return config_dict + + def write_script_start(filename, n): with open(filename, "w+") as f: for i in range(n): @@ -698,6 +771,7 @@ def write_script_single( account="gas2fuels", cores=4, solver="birdmultiphaseEulerFoam", + walltime="47:59:00", ): """Write a per-case SLURM script (``script_single``) running one case.""" ofbashrc = "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" @@ -706,7 +780,7 @@ def write_script_single( f.write("#SBATCH --job-name=lev_single\n") f.write("#SBATCH --nodes=1\n") f.write(f"#SBATCH --ntasks-per-node={cores}\n") - f.write("#SBATCH --time=47:59:00\n") + f.write(f"#SBATCH --time={walltime}\n") f.write(f"#SBATCH --account={account}\n\n") f.write("bash presteps.sh\n") f.write(f"source {ofbashrc}\n") @@ -739,6 +813,7 @@ def write_pack_scripts( cores_per_sim=4, account="gas2fuels", solver="birdmultiphaseEulerFoam", + walltime="47:59:00", ): """Write node-packing scripts (Option A): pack_XXX bundles + submit_all.sh. @@ -760,7 +835,7 @@ def write_pack_scripts( f.write(f"#SBATCH --job-name=lev_{pack_name}\n") f.write("#SBATCH --nodes=1\n") f.write("#SBATCH --exclusive\n") - f.write("#SBATCH --time=47:59:00\n") + f.write(f"#SBATCH --time={walltime}\n") f.write(f"#SBATCH --account={account}\n\n") f.write(f"source {ofbashrc}\n\n") f.write("run_sim () {\n") @@ -802,6 +877,7 @@ def generate_leveled_reactor_cases( cores_per_sim=16, cores_per_node=128, controldict_params=None, + walltime="47:59:00", ): """Generate one scale level of the actuator-disk (ball) design sweep. @@ -818,7 +894,8 @@ def generate_leveled_reactor_cases( used unchanged. Each sim runs on `cores_per_sim` cores; the node-packing bundles fit - ``cores_per_node // cores_per_sim`` sims per node. + ``cores_per_node // cores_per_sim`` sims per node. `walltime` is the SLURM + ``--time`` written into both the per-case and node-packing scripts. `controldict_params`, when given, is a dict of ``system/controlDict`` scalar entries (any of ``deltaT``, ``endTime``, ``maxCo``, ``maxDeltaT``) @@ -950,7 +1027,9 @@ def generate_leveled_reactor_cases( if controldict_params is not None: overwrite_controldict(case_folder=case, params=controldict_params) overwrite_bubble_size_model(case_folder=case, constantD=constantD) - write_script_single(case, account=account, cores=cores_per_sim) + write_script_single( + case, account=account, cores=cores_per_sim, walltime=walltime + ) write_script_post_single(case, account=account) write_foam_stub(case) @@ -962,6 +1041,7 @@ def generate_leveled_reactor_cases( sims_per_node=sims_per_node, cores_per_sim=cores_per_sim, account=account, + walltime=walltime, ) write_prep(os.path.join(study_folder, "prep.sh"), n_sim) save_config_dict(os.path.join(study_folder, "configs.pkl"), config_dict) diff --git a/tests/preprocess/test_case_gen.py b/tests/preprocess/test_case_gen.py index f060c61e..025ba510 100644 --- a/tests/preprocess/test_case_gen.py +++ b/tests/preprocess/test_case_gen.py @@ -275,3 +275,72 @@ def read_scalars(control_dict_path): assert after["endTime"] == "50" assert after["deltaT"] == before["deltaT"] assert after["maxCo"] == before["maxCo"] + + +def test_sample_placement_designs(): + branchcom_spots = { + 0: np.linspace(0.2, 0.8, 4), + 1: np.linspace(0.2, 0.8, 3), + 2: np.linspace(0.2, 0.8, 4), + } + branches_com = [0, 1, 2] + n_designs = 30 + config_dict = sample_placement_designs( + branches_com, branchcom_spots, n_designs + ) + # exactly n_designs, contiguous keys, one array per branch of the right size + assert len(config_dict) == n_designs + assert sorted(config_dict) == list(range(n_designs)) + for design in config_dict.values(): + for b in branches_com: + assert design[b].shape == (len(branchcom_spots[b]),) + # every design is valid (>=1 inlet) and all are distinct + assert all(check_config(d) for d in config_dict.values()) + for i in range(n_designs): + for j in range(i + 1, n_designs): + assert not compare_config(config_dict[i], config_dict[j]) + # sampling is non-deterministic: an independent draw differs + other = sample_placement_designs(branches_com, branchcom_spots, n_designs) + assert any( + not np.array_equal(config_dict[k][b], other[k][b]) + for k in range(n_designs) + for b in branches_com + ) + # too many designs for the space raises rather than looping forever + try: + sample_placement_designs( + branches_com, branchcom_spots, n_designs, max_attempts=5 + ) + raised = False + except RuntimeError: + raised = True + assert raised + + +def test_load_or_sample_designs(): + branchcom_spots = { + 0: np.linspace(0.2, 0.8, 4), + 1: np.linspace(0.2, 0.8, 3), + 2: np.linspace(0.2, 0.8, 4), + } + branches_com = [0, 1, 2] + with tempfile.TemporaryDirectory() as tmpdirname: + design_file = os.path.join(tmpdirname, "designs.pkl") + # first call: no file yet -> samples and saves + first = load_or_sample_designs( + design_file, branches_com, branchcom_spots, n_designs=20 + ) + assert os.path.exists(design_file) + assert len(first) == 20 + # second call: file exists -> borrows the identical set (n_designs + # is ignored once a file is present, so a later sweep asking for + # fewer still reuses the saved pool) + borrowed = load_or_sample_designs( + design_file, branches_com, branchcom_spots, n_designs=5 + ) + assert len(borrowed) == 20 + assert all( + np.array_equal(first[k][b], borrowed[k][b]) + for k in first + for b in branches_com + ) From 2a5ca8f42435b8be963da48689162f866a022e29 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 21 Aug 2026 17:50:26 -0600 Subject: [PATCH 28/52] also pack post proc --- tests/preprocess/test_case_gen.py | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/preprocess/test_case_gen.py b/tests/preprocess/test_case_gen.py index 025ba510..2abe5791 100644 --- a/tests/preprocess/test_case_gen.py +++ b/tests/preprocess/test_case_gen.py @@ -344,3 +344,43 @@ def test_load_or_sample_designs(): for k in first for b in branches_com ) + + +def test_write_pack_post_scripts(): + sim_ids = list(range(5)) + with tempfile.TemporaryDirectory() as tmpdirname: + write_pack_post_scripts( + tmpdirname, + sim_ids, + sims_per_node=2, + account="catmod", + walltime="1:00:00", + ) + # 5 sims, 2 per node -> 3 bundles (2, 2, 1) + packs = sorted( + p for p in os.listdir(tmpdirname) if p.startswith("pack_post_") + ) + assert packs == ["pack_post_000", "pack_post_001", "pack_post_002"] + + first = Path(tmpdirname, "pack_post_000").read_text() + # header: 1 core per sim in the bundle, catmod, 1h + assert "#SBATCH --ntasks-per-node=2" in first + assert "#SBATCH --account=catmod" in first + assert "#SBATCH --time=1:00:00" in first + # the post pipeline, once per sim in the bundle + assert "reconstructPar -newTimes" in first + assert "python read_history.py -cr .. -cn local -df data" in first + assert "python get_qoi.py" in first + assert first.count("run_post Sim_") == 2 + assert first.rstrip().endswith("wait") + # last bundle has the single trailing sim + last = Path(tmpdirname, "pack_post_002").read_text() + assert "#SBATCH --ntasks-per-node=1" in last + assert last.count("run_post Sim_") == 1 + + submit = Path(tmpdirname, "submit_all_post.sh").read_text() + assert submit.splitlines() == [ + "sbatch pack_post_000", + "sbatch pack_post_001", + "sbatch pack_post_002", + ] From 0e70925895c2224e53b2d0c9bf4407370783b2d8 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 21 Aug 2026 17:55:24 -0600 Subject: [PATCH 29/52] pack post proc together --- bird/preprocess/json_gen/generate_designs.py | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 0ff5d5aa..254b722f 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -859,6 +859,64 @@ def write_pack_scripts( f.write(f"sbatch {pack_name}\n") +def write_pack_post_scripts( + study_folder, + sim_ids, + sims_per_node=26, + account="gas2fuels", + walltime="1:00:00", +): + """Write post-processing packing scripts: pack_post_XXX + submit_all_post.sh. + + Mirrors :func:`write_pack_scripts` one-to-one (same `sims_per_node` + bundling, so ``pack_post_b`` post-processes exactly the sims in + ``pack_b``), but each sim runs the QoI pipeline on a single core: + ``reconstructPar`` then ``read_history.py`` + ``get_qoi.py`` under the + bird_mixer conda env. The bundle requests one core per sim + (``ntasks-per-node = len(bundle)``) and its sims run concurrently, each in + its own subshell so their conda state stays isolated. ``submit_all_post.sh`` + sbatches every bundle. + """ + ofbashrc = "/projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc" + conda_env = "/projects/gas2fuels/conda_env/bird_mixer/" + bundles = [ + sim_ids[i : i + sims_per_node] + for i in range(0, len(sim_ids), sims_per_node) + ] + pack_names = [] + for b, bundle in enumerate(bundles): + pack_name = f"pack_post_{b:03}" + pack_names.append(pack_name) + with open(os.path.join(study_folder, pack_name), "w+") as f: + f.write("#!/bin/bash\n") + f.write(f"#SBATCH --job-name=lev_{pack_name}\n") + f.write("#SBATCH --nodes=1\n") + f.write(f"#SBATCH --ntasks-per-node={len(bundle)}\n") + f.write(f"#SBATCH --time={walltime}\n") + f.write(f"#SBATCH --account={account}\n\n") + f.write("run_post () {\n") + f.write("(\n") + f.write('\tcd "$1"\n') + f.write(f"\tsource {ofbashrc}\n") + f.write("\treconstructPar -newTimes > log.reconstruct 2>&1\n") + f.write("\tmodule load conda\n") + f.write(f"\tconda activate {conda_env}\n") + f.write( + "\tpython read_history.py -cr .. -cn local -df data" + " > log.readhist 2>&1\n" + ) + f.write("\tpython get_qoi.py > log.getqoi 2>&1\n") + f.write("\tconda deactivate\n") + f.write(") &\n") + f.write("}\n\n") + for sim_id in bundle: + f.write(f"run_post {id2simfolder(sim_id)}\n") + f.write("wait\n") + with open(os.path.join(study_folder, "submit_all_post.sh"), "w+") as f: + for pack_name in pack_names: + f.write(f"sbatch {pack_name}\n") + + def generate_leveled_reactor_cases( config_dict, branchcom_spots, @@ -1043,6 +1101,13 @@ def generate_leveled_reactor_cases( account=account, walltime=walltime, ) + # post-processing packs mirror the run packs one-to-one (1 core per sim) + write_pack_post_scripts( + study_folder, + sim_ids, + sims_per_node=cores_per_node, + account=account, + ) write_prep(os.path.join(study_folder, "prep.sh"), n_sim) save_config_dict(os.path.join(study_folder, "configs.pkl"), config_dict) save_config_dict( From bdf264fbd7714ef92119310f5409864b8370b6a4 Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 15:56:25 -0600 Subject: [PATCH 30/52] add uloop validation case --- .github/workflows/ci.yml | 15 + .../uloop_valadbeigy_exp1/0.orig/N2.gas | 45 ++ .../uloop_valadbeigy_exp1/0.orig/N2.liquid | 61 +++ .../uloop_valadbeigy_exp1/0.orig/O2.gas | 45 ++ .../uloop_valadbeigy_exp1/0.orig/O2.liquid | 62 +++ .../uloop_valadbeigy_exp1/0.orig/T.gas | 48 ++ .../uloop_valadbeigy_exp1/0.orig/T.liquid | 67 +++ .../uloop_valadbeigy_exp1/0.orig/U.gas | 65 +++ .../uloop_valadbeigy_exp1/0.orig/U.liquid | 70 +++ .../uloop_valadbeigy_exp1/0.orig/Ydefault.gas | 44 ++ .../0.orig/Ydefault.liquid | 64 +++ .../uloop_valadbeigy_exp1/0.orig/Z.liquid | 62 +++ .../uloop_valadbeigy_exp1/0.orig/alpha.gas | 65 +++ .../uloop_valadbeigy_exp1/0.orig/alpha.liquid | 62 +++ .../uloop_valadbeigy_exp1/0.orig/alphat.gas | 46 ++ .../0.orig/alphat.liquid | 47 ++ .../uloop_valadbeigy_exp1/0.orig/k.gas | 43 ++ .../uloop_valadbeigy_exp1/0.orig/k.liquid | 63 +++ .../uloop_valadbeigy_exp1/0.orig/nut.gas | 44 ++ .../uloop_valadbeigy_exp1/0.orig/nut.liquid | 44 ++ .../uloop_valadbeigy_exp1/0.orig/omega.gas | 43 ++ .../uloop_valadbeigy_exp1/0.orig/omega.liquid | 63 +++ .../uloop_valadbeigy_exp1/0.orig/p | 44 ++ .../uloop_valadbeigy_exp1/0.orig/p_rgh | 47 ++ .../uloop_valadbeigy_exp1/Allclean | 24 + .../uloop_valadbeigy_exp1/build_uloop_hex.py | 418 ++++++++++++++++++ .../uloop_valadbeigy_exp1/constant/fvModels | 266 +++++++++++ .../uloop_valadbeigy_exp1/constant/g | 21 + .../uloop_valadbeigy_exp1/constant/globalVars | 70 +++ .../constant/globalVars_temp | 70 +++ .../constant/momentumTransport.gas | 26 ++ .../constant/momentumTransport.liquid | 27 ++ .../constant/phaseProperties | 261 +++++++++++ .../constant/phaseProperties_constantd | 261 +++++++++++ .../constant/thermophysicalProperties.gas | 89 ++++ .../constant/thermophysicalProperties.liquid | 132 ++++++ .../uloop_valadbeigy_exp1/get_mixing_time.py | 209 +++++++++ .../uloop_valadbeigy_exp1/presteps.sh | 77 ++++ .../uloop_valadbeigy_exp1/run.sh | 75 ++++ .../uloop_valadbeigy_exp1/script | 16 + .../uloop_valadbeigy_exp1/script_post | 14 + .../uloop_valadbeigy_exp1/stitch_and_check.sh | 87 ++++ .../uloop_valadbeigy_exp1/system/controlDict | 95 ++++ .../system/createPatchDict | 35 ++ .../system/decomposeParDict | 30 ++ .../system/fvConstraints | 56 +++ .../uloop_valadbeigy_exp1/system/fvSchemes | 76 ++++ .../uloop_valadbeigy_exp1/system/fvSolution | 121 +++++ .../system/inlets_outlets.json | 24 + .../uloop_valadbeigy_exp1/system/mixers.json | 45 ++ .../system/setFieldsDict | 43 ++ .../uloop_valadbeigy_exp1/writeGlobalVars.py | 75 ++++ .../uloop_valadbeigy_exp2/0.orig/N2.gas | 45 ++ .../uloop_valadbeigy_exp2/0.orig/N2.liquid | 61 +++ .../uloop_valadbeigy_exp2/0.orig/O2.gas | 45 ++ .../uloop_valadbeigy_exp2/0.orig/O2.liquid | 62 +++ .../uloop_valadbeigy_exp2/0.orig/T.gas | 48 ++ .../uloop_valadbeigy_exp2/0.orig/T.liquid | 67 +++ .../uloop_valadbeigy_exp2/0.orig/U.gas | 65 +++ .../uloop_valadbeigy_exp2/0.orig/U.liquid | 70 +++ .../uloop_valadbeigy_exp2/0.orig/Ydefault.gas | 44 ++ .../0.orig/Ydefault.liquid | 64 +++ .../uloop_valadbeigy_exp2/0.orig/Z.liquid | 62 +++ .../uloop_valadbeigy_exp2/0.orig/alpha.gas | 65 +++ .../uloop_valadbeigy_exp2/0.orig/alpha.liquid | 62 +++ .../uloop_valadbeigy_exp2/0.orig/alphat.gas | 46 ++ .../0.orig/alphat.liquid | 47 ++ .../uloop_valadbeigy_exp2/0.orig/k.gas | 43 ++ .../uloop_valadbeigy_exp2/0.orig/k.liquid | 63 +++ .../uloop_valadbeigy_exp2/0.orig/nut.gas | 44 ++ .../uloop_valadbeigy_exp2/0.orig/nut.liquid | 44 ++ .../uloop_valadbeigy_exp2/0.orig/omega.gas | 43 ++ .../uloop_valadbeigy_exp2/0.orig/omega.liquid | 63 +++ .../uloop_valadbeigy_exp2/0.orig/p | 44 ++ .../uloop_valadbeigy_exp2/0.orig/p_rgh | 47 ++ .../uloop_valadbeigy_exp2/Allclean | 24 + .../uloop_valadbeigy_exp2/build_uloop_hex.py | 418 ++++++++++++++++++ .../uloop_valadbeigy_exp2/constant/fvModels | 266 +++++++++++ .../uloop_valadbeigy_exp2/constant/g | 21 + .../uloop_valadbeigy_exp2/constant/globalVars | 70 +++ .../constant/globalVars_temp | 70 +++ .../constant/momentumTransport.gas | 26 ++ .../constant/momentumTransport.liquid | 27 ++ .../constant/phaseProperties | 261 +++++++++++ .../constant/phaseProperties_constantd | 261 +++++++++++ .../constant/thermophysicalProperties.gas | 89 ++++ .../constant/thermophysicalProperties.liquid | 132 ++++++ .../uloop_valadbeigy_exp2/get_mixing_time.py | 209 +++++++++ .../uloop_valadbeigy_exp2/presteps.sh | 77 ++++ .../uloop_valadbeigy_exp2/run.sh | 75 ++++ .../uloop_valadbeigy_exp2/script | 16 + .../uloop_valadbeigy_exp2/script_post | 14 + .../uloop_valadbeigy_exp2/stitch_and_check.sh | 87 ++++ .../uloop_valadbeigy_exp2/system/controlDict | 95 ++++ .../system/createPatchDict | 35 ++ .../system/decomposeParDict | 30 ++ .../system/fvConstraints | 56 +++ .../uloop_valadbeigy_exp2/system/fvSchemes | 76 ++++ .../uloop_valadbeigy_exp2/system/fvSolution | 121 +++++ .../system/inlets_outlets.json | 24 + .../uloop_valadbeigy_exp2/system/mixers.json | 45 ++ .../system/setFieldsDict | 43 ++ .../uloop_valadbeigy_exp2/writeGlobalVars.py | 75 ++++ .../uloop_valadbeigy_exp3/0.orig/N2.gas | 45 ++ .../uloop_valadbeigy_exp3/0.orig/N2.liquid | 61 +++ .../uloop_valadbeigy_exp3/0.orig/O2.gas | 45 ++ .../uloop_valadbeigy_exp3/0.orig/O2.liquid | 62 +++ .../uloop_valadbeigy_exp3/0.orig/T.gas | 48 ++ .../uloop_valadbeigy_exp3/0.orig/T.liquid | 67 +++ .../uloop_valadbeigy_exp3/0.orig/U.gas | 65 +++ .../uloop_valadbeigy_exp3/0.orig/U.liquid | 70 +++ .../uloop_valadbeigy_exp3/0.orig/Ydefault.gas | 44 ++ .../0.orig/Ydefault.liquid | 64 +++ .../uloop_valadbeigy_exp3/0.orig/Z.liquid | 62 +++ .../uloop_valadbeigy_exp3/0.orig/alpha.gas | 65 +++ .../uloop_valadbeigy_exp3/0.orig/alpha.liquid | 62 +++ .../uloop_valadbeigy_exp3/0.orig/alphat.gas | 46 ++ .../0.orig/alphat.liquid | 47 ++ .../uloop_valadbeigy_exp3/0.orig/k.gas | 43 ++ .../uloop_valadbeigy_exp3/0.orig/k.liquid | 63 +++ .../uloop_valadbeigy_exp3/0.orig/nut.gas | 44 ++ .../uloop_valadbeigy_exp3/0.orig/nut.liquid | 44 ++ .../uloop_valadbeigy_exp3/0.orig/omega.gas | 43 ++ .../uloop_valadbeigy_exp3/0.orig/omega.liquid | 63 +++ .../uloop_valadbeigy_exp3/0.orig/p | 44 ++ .../uloop_valadbeigy_exp3/0.orig/p_rgh | 47 ++ .../uloop_valadbeigy_exp3/Allclean | 24 + .../uloop_valadbeigy_exp3/build_uloop_hex.py | 418 ++++++++++++++++++ .../uloop_valadbeigy_exp3/constant/fvModels | 266 +++++++++++ .../uloop_valadbeigy_exp3/constant/g | 21 + .../uloop_valadbeigy_exp3/constant/globalVars | 70 +++ .../constant/globalVars_temp | 70 +++ .../constant/momentumTransport.gas | 26 ++ .../constant/momentumTransport.liquid | 27 ++ .../constant/phaseProperties | 261 +++++++++++ .../constant/phaseProperties_constantd | 261 +++++++++++ .../constant/thermophysicalProperties.gas | 89 ++++ .../constant/thermophysicalProperties.liquid | 132 ++++++ .../uloop_valadbeigy_exp3/get_mixing_time.py | 209 +++++++++ .../uloop_valadbeigy_exp3/presteps.sh | 77 ++++ .../uloop_valadbeigy_exp3/run.sh | 75 ++++ .../uloop_valadbeigy_exp3/script | 16 + .../uloop_valadbeigy_exp3/script_post | 14 + .../uloop_valadbeigy_exp3/stitch_and_check.sh | 87 ++++ .../uloop_valadbeigy_exp3/system/controlDict | 95 ++++ .../system/createPatchDict | 35 ++ .../system/decomposeParDict | 30 ++ .../system/fvConstraints | 56 +++ .../uloop_valadbeigy_exp3/system/fvSchemes | 76 ++++ .../uloop_valadbeigy_exp3/system/fvSolution | 121 +++++ .../system/inlets_outlets.json | 24 + .../uloop_valadbeigy_exp3/system/mixers.json | 45 ++ .../system/setFieldsDict | 43 ++ .../uloop_valadbeigy_exp3/writeGlobalVars.py | 75 ++++ pyproject.toml | 1 + 155 files changed, 11977 insertions(+) create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/T.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/T.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/U.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/U.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/Z.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/k.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/k.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/p create mode 100644 experimental_cases/uloop_valadbeigy_exp1/0.orig/p_rgh create mode 100755 experimental_cases/uloop_valadbeigy_exp1/Allclean create mode 100644 experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/fvModels create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/g create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/globalVars create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/globalVars_temp create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties_constantd create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py create mode 100755 experimental_cases/uloop_valadbeigy_exp1/presteps.sh create mode 100755 experimental_cases/uloop_valadbeigy_exp1/run.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp1/script create mode 100755 experimental_cases/uloop_valadbeigy_exp1/script_post create mode 100755 experimental_cases/uloop_valadbeigy_exp1/stitch_and_check.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/controlDict create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/createPatchDict create mode 100755 experimental_cases/uloop_valadbeigy_exp1/system/decomposeParDict create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/fvConstraints create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/fvSchemes create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/fvSolution create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/inlets_outlets.json create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/mixers.json create mode 100644 experimental_cases/uloop_valadbeigy_exp1/system/setFieldsDict create mode 100644 experimental_cases/uloop_valadbeigy_exp1/writeGlobalVars.py create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/T.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/T.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/U.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/U.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/Z.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/k.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/k.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/p create mode 100644 experimental_cases/uloop_valadbeigy_exp2/0.orig/p_rgh create mode 100755 experimental_cases/uloop_valadbeigy_exp2/Allclean create mode 100644 experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/fvModels create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/g create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/globalVars create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/globalVars_temp create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties_constantd create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py create mode 100755 experimental_cases/uloop_valadbeigy_exp2/presteps.sh create mode 100755 experimental_cases/uloop_valadbeigy_exp2/run.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp2/script create mode 100755 experimental_cases/uloop_valadbeigy_exp2/script_post create mode 100755 experimental_cases/uloop_valadbeigy_exp2/stitch_and_check.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/controlDict create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/createPatchDict create mode 100755 experimental_cases/uloop_valadbeigy_exp2/system/decomposeParDict create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/fvConstraints create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/fvSchemes create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/fvSolution create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/inlets_outlets.json create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/mixers.json create mode 100644 experimental_cases/uloop_valadbeigy_exp2/system/setFieldsDict create mode 100644 experimental_cases/uloop_valadbeigy_exp2/writeGlobalVars.py create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/T.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/T.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/U.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/U.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/Z.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/k.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/k.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/p create mode 100644 experimental_cases/uloop_valadbeigy_exp3/0.orig/p_rgh create mode 100755 experimental_cases/uloop_valadbeigy_exp3/Allclean create mode 100644 experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/fvModels create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/g create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/globalVars create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/globalVars_temp create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties_constantd create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas create mode 100644 experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid create mode 100644 experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py create mode 100755 experimental_cases/uloop_valadbeigy_exp3/presteps.sh create mode 100755 experimental_cases/uloop_valadbeigy_exp3/run.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp3/script create mode 100755 experimental_cases/uloop_valadbeigy_exp3/script_post create mode 100755 experimental_cases/uloop_valadbeigy_exp3/stitch_and_check.sh create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/controlDict create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/createPatchDict create mode 100755 experimental_cases/uloop_valadbeigy_exp3/system/decomposeParDict create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/fvConstraints create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/fvSchemes create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/fvSolution create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/inlets_outlets.json create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/mixers.json create mode 100644 experimental_cases/uloop_valadbeigy_exp3/system/setFieldsDict create mode 100644 experimental_cases/uloop_valadbeigy_exp3/writeGlobalVars.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b396279..da95571b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,6 +222,21 @@ jobs: cd experimental_cases/deckwer19 bash run.sh cd ../../ + - name: Run uloop_valadbeigy_exp1 + run: | + cd experimental_cases/ + bash run.sh + cd ../../ + - name: Run uloop_valadbeigy_exp2 + run: | + cd experimental_cases/ + bash run.sh + cd ../../ + - name: Run uloop_valadbeigy_exp3 + run: | + cd experimental_cases/ + bash run.sh + cd ../../ - name: Run side sparger tutorial run: | cd tutorial_cases/side_sparger diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_N2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_N2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/N2.liquid @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeN2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_O2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_O2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/O2.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeO2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $T0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/T.liquid @@ -0,0 +1,67 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $T0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $T0; + name dyeTliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0.0 0.0 0.0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name spargerInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar Q = 4.0*1e-3/60; // 4 L/min + + vectorField Up(this->size(), Foam::vector::zero); + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + this->operator==(Up); + #}; + } + + dye_inlet + { + type slip; + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + walls + { + type slip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/U.liquid @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0.0 0.0 0.0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type noSlip; + } + dye_inlet + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name dyeInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + vectorField Up(this->size(), Foam::vector::zero); + if (t >= tStart && t < tStop) + { + const scalar dyeVol = 50.0e-6; // m3 (50 mL) + const scalar Q = dyeVol/(tStop - tStart); // m3/s + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + } + this->operator==(Up); + #}; + + } + + outlet + { + type noSlip; + } + walls + { + type noSlip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid @@ -0,0 +1,64 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Ydefault = the inert specie (water). At the dye inlet the injected fluid is +// pure tracer Z, so water = 0 there. + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeYdliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/Z.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/Z.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Z.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeZliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 1.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaGas; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1.0; + value uniform 1.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alpha.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type fixedValue; + value uniform 0.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/alphat.liquid @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $k_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/k.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $k_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $k_inlet_liq; + name dyekinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/nut.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-2; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.gas b/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_gas; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $omega_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.liquid b/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/omega.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_liq; + +boundaryField +{ + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform $omega_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $omega_inlet_liq; + name dyeepsinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = 1.0; + const scalar tStop = 2.0; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + + outlet + { + type zeroGradient; + } + walls + { + type omegaWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/p b/experimental_cases/uloop_valadbeigy_exp1/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/p @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/0.orig/p_rgh b/experimental_cases/uloop_valadbeigy_exp1/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/0.orig/p_rgh @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type fixedFluxPressure; + value $internalField; + } + dye_inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + value $internalField; + } + walls + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/Allclean b/experimental_cases/uloop_valadbeigy_exp1/Allclean new file mode 100755 index 00000000..dc2f77db --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/Allclean @@ -0,0 +1,24 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +if [ -n "$WM_PROJECT_DIR" ]; then + . $WM_PROJECT_DIR/bin/tools/CleanFunctions + cleanCase +else + echo "WARNING: could not run cleanCase, OpenFOAM env not found" +fi + +# Remove 0 +[ -d "0" ] && rm -rf 0 + +# rm -f constant/triSurface/*.eMesh +# [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" +[ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" +[ -d "dynamicCode" ] && rm -rf "dynamicCode" +[ -d "processor*" ] && rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py new file mode 100644 index 00000000..bef692ab --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py @@ -0,0 +1,418 @@ +""" +Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 + +Open-top U-loop reactor as 3 stitchable gmsh blocks + +Structured hex mesh everywhere except the U-loop<->tank junction + +Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): + A hex : the U pipe + B tet : U-loop <-> tank junction + Two down-stubs (filleted where they meet the tank floor) + C hex : structured-hex tank, extruded up to the open top (Z_TOP). + Flat top face is the `outlet` boundary; sides = wall. + +This output block{A,B,C}.{msh,vtk} +""" + +import math +import gmsh +import numpy as np + +# Geometrical parameters +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +TANK_LEN = 2 * R_TANK +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] + + +def loop_pipe_length(include_tank=False): + ''' Compute pipe length which is reported in the paper''' + r_bend = R_BEND + z_bend_top = Z_HORIZ + r_bend + leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) + leg = leg_top - z_bend_top + arc = 0.5 * math.pi * r_bend + horiz = 2.0 * (X_LEG - r_bend) + return 2.0 * leg + 2.0 * arc + horiz + + +def reactor_volume(tank_fraction=1.0): + v_pipe = math.pi * R**2 * loop_pipe_length(include_tank=False) + v_tank = math.pi * R_TANK**2 * TANK_LEN + return v_pipe + tank_fraction * v_tank + +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] + +# --- resolution +RI_FRAC = 0.5 +N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge +# FINER mesh at the junction is obtained with SMALLER JUNCTION_RES +JUNCTION_RES = 1.8 + + +# ---- iterative mesh cleanup +N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) +N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) +N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells + + +def _pillow(geo, cx, cy, cz, r, n_side, n_rad): + '''Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)''' + ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] + ri = RI_FRAC * r + c = geo.addPoint(cx, cy, cz) + Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] + A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] + Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] + Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] + surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] + for i in range(4): + surfs.append(geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + for e in Qe + Arc: + geo.mesh.setTransfiniteCurve(e, n_side + 1) + for e in Rad: + geo.mesh.setTransfiniteCurve(e, n_rad + 1) + for s in surfs: + geo.mesh.setTransfiniteSurface(s) + geo.mesh.setRecombine(2, s) + return surfs + + +def _isflat(s, idx, val, tol=1e-6): + ''' + True if surface *s* lies entirely on the plane coord[idx] == val. + I.e. is a constant coordinate plane + useful to check if what we extruded gives us a flat surface + ''' + bb = gmsh.model.getBoundingBox(2, s) + return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol + + +def _tip(idx, val): + ''' + Find flat boundary surface after gmesh extrusion + ''' + vols = [t for _, t in gmsh.model.getEntities(3)] + bnd = {t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)} + return [(2, s) for s in bnd if _isflat(s, idx, val)] + + +def _by(surfs, idx, val): + '''Filter surface to those lying on the plane coord[idx] == val.''' + return [s for s in surfs if _isflat(s, idx, val)] + + +def _cx(s): + '''Bounding box used to distinguish the left and right leg''' + bb = gmsh.model.getBoundingBox(2, s) + return 0.5 * (bb[0] + bb[3]) + + +def _rims(surfs): + ''' find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block''' + rim = set() + for s in surfs: + for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): + rim.add(cc) + return rim + + +def _boundary_surfs(): + """Returns volume IDs and their boundary surface IDs.""" + vols = [t for _, t in gmsh.model.getEntities(3)] + return vols, [t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)] + + +def _cell_volume(): + """Sum of all 3-D cell volumes""" + tags, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + idx = {int(t): i for i, t in enumerate(tags)} + npe = {4: 4, 5: 8, 6: 6, 7: 5} + fans = { + 4: [(0, 1, 2, 3)], + 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), + (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], + 7: [(0, 1, 2, 4), (0, 2, 3, 4)], + } + total = 0.0 + ets, _, enodes = gmsh.model.mesh.getElements(3) + for et, en in zip(ets, enodes): + conn = np.array([idx[int(t)] for t in en]).reshape(-1, npe[et]) + P = coords[conn] + for a, b, c, d in fans[et]: + v = P[:, a], P[:, b], P[:, c], P[:, d] + total += np.abs(np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + return total / 6.0 + + +def _write(path, tag): + ''' Write Gmesh object to .msh and print summary''' + TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} + ets, etags, _ = gmsh.model.mesh.getElements(3) + counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} + vol = _cell_volume() + print(f"[block {tag}] cells={counts} volume={vol * 1e3:.3f} L") + gmsh.option.setNumber("Mesh.MshFileVersion", 2.2) + gmsh.write(path) + gmsh.write(path.rsplit(".", 1)[0] + ".vtk") + return vol + + +# --- U pipe (structured hex) +def build_block_A(path): + """Extrude the pillow cross-section down in sequence + 1) left leg + 2) 90 deg elbow + 3) bottom leg + 4) second 90 degree elbow + 5) up the right leg + + the two leg-top meet the filleted mesh as z=Z_AB""" + gmsh.initialize() + gmsh.model.add("A") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) + geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], recombine=True) + geo.synchronize() + + # left elbow: revolve the leg-bottom disk about y through the bend centre + geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # bottom horizontal run: extrude +x + geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, + numElements=[N_HOR], recombine=True) + geo.synchronize() + + # right elbow + geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # right leg: extrude +z up to Z_AB + geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, + numElements=[N_LEG], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + iface = _by(bnd, 2, Z_AB) + legL = [s for s in iface if _cx(s) < 0] + legR = [s for s in iface if _cx(s) > 0] + walls = [s for s in bnd if s not in iface] + gmsh.model.addPhysicalGroup(3, vols, name="pipeU") + gmsh.model.addPhysicalGroup(2, legL, name="int_A_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_A_legR") + gmsh.model.addPhysicalGroup(2, walls, name="wall_A") + + gmsh.model.mesh.generate(3) + vol = _write(path, "A") + gmsh.finalize() + return vol + + +# ---- block B: U-loop <-> tank junction +def build_block_B(path): + '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). + 2. Two cylindrical partial leds + 3. Fillet + + Interface matching (that was the hard part!) + - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + ''' + + gmsh.initialize() + gmsh.model.add("B") + gmsh.option.setNumber("General.Terminal", 0) + occ = gmsh.model.occ + + pen = 0.4 * (Z_BC - Z_BOT) + slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) + stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG)] + S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) + occ.synchronize() + vol = S[0][1] + + ring = [] + for _, e in gmsh.model.getEntities(1): + ex, _ey, ez = occ.getCenterOfMass(1, e) + x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) + if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ + and (x1 - x0) < 3 * R: + ring.append(e) + occ.fillet([vol], ring, [FILLET_R]) + occ.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C + walls = [s for s in bnd if s not in bot and s not in top] + legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] + legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] + + for s in bot: # match each stub rim to A (4*N_SIDE) + rc = _rims([s]) + per = max(1, round(4 * N_SIDE / len(rc))) + for cc in rc: + gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) + + gmsh.model.addPhysicalGroup(3, vols, name="juncB") + gmsh.model.addPhysicalGroup(2, legL, name="int_B_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_B_legR") + gmsh.model.addPhysicalGroup(2, top, name="int_B_top") + gmsh.model.addPhysicalGroup(2, walls, name="wall_B") + gmsh.option.setNumber("Mesh.MeshSizeMax", R / N_SIDE * JUNCTION_RES) + gmsh.option.setNumber("Mesh.Optimize", 1) + gmsh.option.setNumber("Mesh.OptimizeNetgen", 1) + gmsh.model.mesh.generate(3) + gmsh.model.mesh.optimize("Netgen") + vol = _write(path, "B") + gmsh.finalize() + return vol + + +# --- block C: hex tank +def build_block_C(path): + """Structured-hex tank extruded from Z_BC to Z_TOP. + + 1) N_TANK nodes per edge, matching block B's top + 2) Extrude +z to Z_TOP with N_HC uniform layers. + + Top face is the open outlet boundary; + Sides are wall_C; + Bottom is for stitching to block B. + """ + gmsh.initialize() + gmsh.model.add("C") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] + sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) + for e in l: + geo.mesh.setTransfiniteCurve(e, N_TANK + 1) + geo.mesh.setTransfiniteSurface(sq) + geo.mesh.setRecombine(2, sq) + geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_BC) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + walls = [s for s in bnd if s not in bot and s not in top] + gmsh.model.addPhysicalGroup(3, vols, name="tank") + gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") + gmsh.model.addPhysicalGroup(2, top, name="outlet") + gmsh.model.addPhysicalGroup(2, walls, name="wall_C") + gmsh.model.mesh.generate(3) + vol = _write(path, "C") + gmsh.finalize() + return vol + + +# ---- verify that the junction that stitch mesh will operate on has consistent +# face perimeter +def _plane_nodes(path, zval): + """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" + gmsh.initialize() + gmsh.open(path) + _, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + pts = [(x, y) for x, y, z in coords if abs(z - zval) < 1e-6] + gmsh.finalize() + return pts + + +def _circle_rim(pts, cx, r): + """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4) + + +def _square_rim(pts, hx, hy): + """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + + +def _verify(name, a, b, tol=1e-9): + """Assert two rim point sets have the same count and are coincident within tol.""" + assert len(a) == len(b), \ + f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + ok = worst < tol + print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." + + +def verify_interfaces(): + """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" + A_ab = _plane_nodes("blockA.msh", Z_AB) + B_ab = _plane_nodes("blockB.msh", Z_AB) + _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) + _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + B_bc = _plane_nodes("blockB.msh", Z_BC) + C_bc = _plane_nodes("blockC.msh", Z_BC) + _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) + + +# ---- main +if __name__ == "__main__": + print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + vols = { + "A": build_block_A("blockA.msh"), + "B": build_block_B("blockB.msh"), + "C": build_block_C("blockC.msh"), + } + verify_interfaces() + + box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) + print("=" * 70) + print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m") + print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L") + print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") + print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/fvModels b/experimental_cases/uloop_valadbeigy_exp1/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/fvModels @@ -0,0 +1,266 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include + #include + #}; + + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + const double pi = 3.14159265358979; + // ===== ball mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Vtip = 5; + const double sigma = 0.35; + const double startT = 0.1; + const double px = 0.063, py = 0.47, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 4.0*9.75/(rhoM*area); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dy)*(dy)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][0] -= -1.0*fth*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fth*V[i]*((-dx)/rr); + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = 0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= 1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= -1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= 1.0*fcp*V[i]; + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = -0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= 1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= 1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= -1.0*fcp*V[i]; + } + } + } + } + } + #}; +}; diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/g b/experimental_cases/uloop_valadbeigy_exp1/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars b/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA 0.000251007; +inletA_dye 0.000251007; +liqVol 0.00588087; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars_temp b/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/globalVars_temp @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA ; // sparger patch area [m2], filled by writeGlobalVars.py +inletA_dye ; // dye_inlet patch area [m2], filled by writeGlobalVars.py +liqVol ; // liquid volume [m3], filled by writeGlobalVars.py +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.gas b/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType laminar; +//simulationType RAS; +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.liquid b/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties b/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties_constantd b/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas b/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas @@ -0,0 +1,89 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + O2 + N2 +); + +defaultSpecie N2; + +O2 +{ + specie + { + molWeight 31.9988; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.28253784 0.00148308754 -7.57966669e-07 2.09470555e-10 -2.16717794e-14 -1088.45772 5.45323129 ); + lowCpCoeffs ( 3.78245636 -0.00299673416 9.84730201e-06 -9.68129509e-09 3.24372837e-12 -1063.94356 3.65767573 ); + } + transport + { + As 1.693411300e-06; + Ts 127; + } + elements + { + O 2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid b/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid @@ -0,0 +1,132 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + O2 + N2 + water + Z +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +// Passive dye tracer: identical to water, no interphase mass transfer (Z is +// deliberately absent from every Henry / diffusiveMassTransfer list). +Z +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +O2 +{ + specie + { + molWeight 31.9988; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrO2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrN2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py new file mode 100644 index 00000000..2f86cf69 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py @@ -0,0 +1,209 @@ +"""Volume-averaged dye tracer (Z.liquid) in the bottom U-bend box vs time. + +For every time folder this reads the ``Z.liquid`` with BiRD +then computes the cell-volume-weighted average over the +cells whose centres lie inside the box + + x in [-0.01, 0.01], y in [-0.1, 0.1], z in [-0.1, 0.1] [m] + +and plots that average versus time. +""" + +import os + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.utilities.ofio import ( + get_case_times, + read_cell_centers, + read_cell_volumes, + read_field, +) + +CASE = os.path.dirname(os.path.abspath(__file__)) + +# Averaging box [m]. The mesh is y-up after the presteps transformPoints. +X_BOUNDS = (-0.01, 0.01) +Y_BOUNDS = (-0.1, 0.1) +Z_BOUNDS = (-0.1, 0.1) + +# Mixing-time criterion. +BAND = 0.05 # within +/-5% of the final well-mixed value +TAIL_WINDOW = 0.5 # s, tail used to define the final value + + +def read_dye_start(): + """Dye injection start time [s], read from constant/globalVars.""" + with open(os.path.join(CASE, "constant", "globalVars")) as f: + for line in f: + if line.startswith("dyeStart"): + return float(line.split()[1].rstrip(";")) + return 1.0 + + +def box_mask(cell_centers): + """Boolean mask of cells whose centres lie inside the averaging box.""" + x, y, z = cell_centers[:, 0], cell_centers[:, 1], cell_centers[:, 2] + return ( + (x >= X_BOUNDS[0]) + & (x <= X_BOUNDS[1]) + & (y >= Y_BOUNDS[0]) + & (y <= Y_BOUNDS[1]) + & (z >= Z_BOUNDS[0]) + & (z <= Z_BOUNDS[1]) + ) + + +def box_volume_average(z_field, cell_volumes, mask): + """Cell-volume-weighted average of z_field over the masked cells. + + read_field returns a bare float for a uniform OpenFOAM field (e.g. the dye + tracer before injection starts); the volume average is then exactly that + value. Otherwise it is the volume-weighted mean over the box cells. + """ + if np.ndim(z_field) == 0: + return float(z_field) + else: + vol = cell_volumes[mask] + return float(np.sum(z_field[mask] * vol) / np.sum(vol)) + + +def mixing_time(t_arr, z_arr, t_start, continuous=True): + """Mixing time from the box-averaged dye signal. + + The final well-mixed value is the mean of the signal over the last + TAIL_WINDOW seconds. The mixing time is the interval from dye injection + (t_start) to the last instant the signal leaves the +/-BAND envelope of + that final value (after which it stays inside for good). + + Parameters + ---------- + t_arr : array-like + Time array. + z_arr : array-like + Box-averaged dye signal. + t_start : float + Injection time. + continuous : bool, optional + If True, linearly interpolates between the last timestep outside the + band and the first timestep inside to find the exact crossing time. + + Returns + ------- + t_mix : float + Mixing time measured from injection [s]. + t_settle : float + Absolute simulation time at which the signal settles [s]. + z_final : float + Final well-mixed box-averaged value. + """ + # Calculate final value and allowable band + z_final = float(np.mean(z_arr[t_arr >= t_arr[-1] - TAIL_WINDOW])) + band = BAND * abs(z_final) + + post = t_arr >= t_start + outside = post & (np.abs(z_arr - z_final) > band) + + if not np.any(outside): + # already within the band from injection onward + t_settle = t_start + else: + last_out = np.nonzero(outside)[0][-1] + + # Check if we have a subsequent point to interpolate with + if last_out + 1 < len(t_arr): + if continuous: + # Extract time and Z values for the crossing interval + t0, t1 = t_arr[last_out], t_arr[last_out + 1] + z0, z1 = z_arr[last_out], z_arr[last_out + 1] + + # Determine which boundary of the band was crossed + if z0 > z_final: + z_target = z_final + band # Crossed the top boundary + else: + z_target = z_final - band # Crossed the bottom boundary + + # Linearly interpolate to find the exact time t_settle at z_target + if z1 != z0: # Safety check to prevent division by zero + t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) + else: + t_settle = t1 + else: + # Original discrete behavior + t_settle = t_arr[last_out + 1] + else: + # The signal was outside the band up to the very last recorded timestep + t_settle = t_arr[last_out] + + return t_settle - t_start, t_settle, z_final + +if __name__ == "__main__": + os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) + + # Geometry is time-independent: read the cell centres and cell volumes once + # and keep them in the shared field_dict cache. + cell_centers, geom = read_cell_centers(CASE) + n_cells = cell_centers.shape[0] + cell_volumes, geom = read_cell_volumes(CASE, field_dict=geom) + + mask = box_mask(cell_centers) + if mask.sum() == 0: + raise RuntimeError("averaging box contains no cell centres") + + times_float, times_str = get_case_times(CASE) + + t_list, z_list = [], [] + for t_val, t_str in zip(times_float, times_str): + try: + # Fresh field_dict per time so Z.liquid is never served stale. + z_field, _ = read_field(CASE, t_str, "Z.liquid", n_cells=n_cells) + except FileNotFoundError: + continue + t_list.append(t_val) + z_list.append(box_volume_average(z_field, cell_volumes, mask)) + + order = np.argsort(t_list) + t_arr = np.asarray(t_list)[order] + z_arr = np.asarray(z_list)[order] + + np.savetxt( + os.path.join(CASE, "Z_box_average.dat"), + np.column_stack([t_arr, z_arr]), + header="time[s] volAvg(Z.liquid)_box", + ) + + dye_start = read_dye_start() + t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + + with open(os.path.join(CASE, "mix_time.txt"), "w") as f: + f.write(f"Continuous: {t_mix:.4f}\n") + f.write(f"Discrete: {t_mix_disc:.4f}\n") + + fig, ax = plt.subplots(figsize=(6, 4)) + ax.plot(t_arr, z_arr, color="k") + ax.axhline(z_final, color="b", ls="--", label=r"$Z_{final}$") + ax.axhspan( + (1 - BAND) * z_final, (1 + BAND) * z_final, color="b", alpha=0.15 + ) + ax.axvline( + t_settle, color="r", ls=":", label=f"$t_{{mix}}$={t_mix_disc:.2f} s" + ) + ax.set_xlim(left=dye_start) + pretty_labels("time [s]", r"box-averaged $Z_{liquid}$ [-]", 14, ax=ax) + ax.legend() + fig.savefig( + os.path.join(CASE, "Figures", "Z_box_average.png"), + dpi=150, + bbox_inches="tight", + ) + + print(f"box cells : {int(mask.sum())}") + print(f"time folders averaged : {len(t_arr)}") + print(f"final well-mixed Z discrete : {z_final_disc:.6g}") + print(f"final well-mixed Z continous : {z_final:.6g}") + print(f"dye injection start : {dye_start:.3f} s") + print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") + print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") + print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") diff --git a/experimental_cases/uloop_valadbeigy_exp1/presteps.sh b/experimental_cases/uloop_valadbeigy_exp1/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/presteps.sh @@ -0,0 +1,77 @@ +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +# setup IC +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + +conda deactivate diff --git a/experimental_cases/uloop_valadbeigy_exp1/run.sh b/experimental_cases/uloop_valadbeigy_exp1/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/run.sh @@ -0,0 +1,75 @@ +#!/bin/bash +### OpenFOAM command +./Allclean +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + +### BiRD command +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + + +birdmultiphaseEulerFoam diff --git a/experimental_cases/uloop_valadbeigy_exp1/script b/experimental_cases/uloop_valadbeigy_exp1/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/script @@ -0,0 +1,16 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=14:59:00 +#SBATCH --account=gas2fuels + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes -fields "(U.liquid alpha.gas Z.liquid)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp1/script_post b/experimental_cases/uloop_valadbeigy_exp1/script_post new file mode 100755 index 00000000..dcbf59d8 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/script_post @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=01:59:00 +#SBATCH --account=gas2fuels +#SBATCH --dependency=afterany:15800966 + +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp1/stitch_and_check.sh b/experimental_cases/uloop_valadbeigy_exp1/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/stitch_and_check.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# +# Stitch a list of gmsh block meshes into ONE OpenFOAM mesh and run checkMesh. +# +# Each mesh is converted with gmshToFoam; mesh #0 becomes the master case that +# the rest are merged into; then each --stitch pair is coupled with integral +# (non -perfect) stitchMesh +# +# Options: +# --mesh (repeatable; order = stack order, #0 is master) +# --stitch (repeatable; integral, for non-matching faces) +# --stitch-perfect (repeatable; -perfect, for conformal faces) +# --case (output case dir, default: stitched_case) + +set -euo pipefail + +CASE="stitched_case" +MESHES=() +STITCHES=() # entries: "integral m:s" or "perfect m:s" (order preserved) +while [[ $# -gt 0 ]]; do + case "$1" in + --mesh) MESHES+=("$2"); shift 2;; + --stitch) STITCHES+=("integral $2"); shift 2;; + --stitch-perfect) STITCHES+=("perfect $2"); shift 2;; + --case) CASE="$2"; shift 2;; + *) echo "unknown argument: $1" >&2; exit 1;; + esac +done + +# >=1 mesh: with a single --mesh and no --stitch this just gmshToFoam+checkMesh +# one block (useful to isolate which block owns a checkMesh failure). +[[ ${#MESHES[@]} -ge 1 ]] || { echo "need at least one --mesh file" >&2; exit 1; } +command -v gmshToFoam >/dev/null 2>&1 || { + echo "OpenFOAM not found on PATH — source OpenFOAM-9 first." >&2; exit 1; } + +# minimal case skeleton (mesh utilities need controlDict/fvSchemes/fvSolution) +write_system() { + local d="$1"; mkdir -p "$d/system" "$d/constant" + cat > "$d/system/controlDict" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object controlDict; } +application checkMesh; +startFrom startTime; startTime 0; +stopAt endTime; endTime 1; +deltaT 1; writeControl timeStep; writeInterval 1; +EOF + cat > "$d/system/fvSchemes" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSchemes; } +ddtSchemes { default steadyState; } +gradSchemes { default Gauss linear; } +divSchemes { default none; } +laplacianSchemes { default Gauss linear corrected; } +interpolationSchemes { default linear; } +snGradSchemes { default corrected; } +EOF + cat > "$d/system/fvSolution" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSolution; } +solvers {} +EOF +} + +echo "==> master case: $CASE (from ${MESHES[0]})" +rm -rf "$CASE"; write_system "$CASE" +gmshToFoam "${MESHES[0]}" -case "$CASE" + +# convert + merge the remaining blocks into the master +for ((i=1; i<${#MESHES[@]}; i++)); do + sub="${CASE}_add${i}" + echo "==> add block $i: ${MESHES[$i]}" + rm -rf "$sub"; write_system "$sub" + gmshToFoam "${MESHES[$i]}" -case "$sub" + # merge into master (OF-9 foundation syntax) + mergeMeshes "$CASE" "$sub" -overwrite + rm -rf "$sub" +done + +# couple each interface with its chosen mode +for spec in "${STITCHES[@]}"; do + mode="${spec%% *}"; pair="${spec#* }" + master="${pair%%:*}"; slave="${pair##*:}" + flags="-overwrite"; [[ "$mode" == perfect ]] && flags="$flags -perfect" + echo "==> stitchMesh ($mode) $master $slave" + stitchMesh $flags "$master" "$slave" -case "$CASE" +done + +echo "==> checkMesh" +checkMesh -allGeometry -allTopology -case "$CASE" +echo "==> done. Mesh in $CASE/constant/polyMesh" diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/controlDict b/experimental_cases/uloop_valadbeigy_exp1/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/controlDict @@ -0,0 +1,95 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt writeNow;//endTime; + +// ~20 s spin-up for steady circulation, dye pulse at t=20-21 s, then ~24 s to +// capture a ~10 s mixing time. +endTime 20; + +deltaT 1e-6; + +writeControl adjustableRunTime; +//writeControl timeStep; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 1.0; + +maxDeltaT 0.001; + + +functions +{ + + limitNut + { + type coded; + libs ("libutilityFunctionObjects.so"); + name limitNut; + codeExecute + #{ + const scalar nutMaxLiq = 1e-3; // [m2/s] liquid nut ceiling (tune) + //const scalar nutMaxGas = 1e-3; // [m2/s] gas nut ceiling (tune) + + volScalarField& nutLiq = + mesh().lookupObjectRef("nut.liquid"); + //volScalarField& nutGas = + // mesh().lookupObjectRef("nut.gas"); + + nutLiq = min(nutLiq, dimensionedScalar(nutLiq.dimensions(), nutMaxLiq)); + //nutGas = min(nutGas, dimensionedScalar(nutGas.dimensions(), nutMaxGas)); + nutLiq.correctBoundaryConditions(); + //nutGas.correctBoundaryConditions(); + + //Info<< "limitNut: max nut.liq=" << max(nutLiq).value() + // << " nut.gas=" << max(nutGas).value() << endl; + Info<< "limitNut: max nut.liq=" << max(nutLiq).value() << endl; + #}; + } + + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) + + // Mixing time is post-processed offline from the written time folders + // (Z.liquid + alpha.liquid), so no sensor/dyeMean function objects here. + // Set writeInterval to the temporal resolution the offline analysis needs. +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/createPatchDict b/experimental_cases/uloop_valadbeigy_exp1/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/createPatchDict @@ -0,0 +1,35 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object createPatchDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Consolidate the per-block wall patches (wall_A/B/C) into a single "walls" patch. +// createPatch also drops the now-empty stitch interface patches (int_*, 0 faces). +// The open tank roof is already its own "outlet" mesh patch (block C physical +// group), so it is NOT merged here and needs no surfaceToPatch. sparger and +// dye_inlet are still carved from "walls" with surfaceToPatch in presteps.sh. + +pointSync false; + +patches +( + { + name walls; + patchInfo { type wall; } + constructFrom patches; + patches (wall_A wall_B wall_C); + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/decomposeParDict b/experimental_cases/uloop_valadbeigy_exp1/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/fvConstraints b/experimental_cases/uloop_valadbeigy_exp1/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/fvSchemes b/experimental_cases/uloop_valadbeigy_exp1/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/fvSchemes @@ -0,0 +1,76 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + //default Gauss linear; + //limited cellLimited Gauss linear 1; + default cellLimited 1.5 leastSquares 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + //"div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + //"div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,U.*\)" Gauss Minmod; + "div\(phi.*,U.*\)" Gauss Minmod; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon)m\)" Gauss limitedLinear 1; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + //default Gauss linear corrected; + default Gauss linear corrected 0.33; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + //default uncorrected; + default limited corrected 0.33; +} + +wallDist +{ + //method Poisson; + //nRequired true; + method meshWave; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/fvSolution b/experimental_cases/uloop_valadbeigy_exp1/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/fvSolution @@ -0,0 +1,121 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega|epsilon|omega).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 1e-3; + minIter 0; + maxIter 5; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 1e-3; + minIter 0; + maxIter 0; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 2; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/inlets_outlets.json b/experimental_cases/uloop_valadbeigy_exp1/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/inlets_outlets.json @@ -0,0 +1,24 @@ +{ + "sparger": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.23, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ], + "dye_inlet": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.65, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ] +} diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/mixers.json b/experimental_cases/uloop_valadbeigy_exp1/system/mixers.json new file mode 100644 index 00000000..1f51bc16 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/mixers.json @@ -0,0 +1,45 @@ +{ + "mixers": [ + { + "x": 0.063, + "y": 0.47, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "power": 9.75, + "Vtip": 5, + "sign": "-", + "swirl_sign": "-" + } + ], + "static_mixers": [ + { + "x": 0.063, + "y": 0.05, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "-", + "swirl_sign": "-" + }, + { + "x": -0.063, + "y": 0.05, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "+", + "swirl_sign": "+" + } + ], + "volumetric_source": "ball", + "power": "from_P", + "momentum_source": "axial_and_swirl" +} diff --git a/experimental_cases/uloop_valadbeigy_exp1/system/setFieldsDict b/experimental_cases/uloop_valadbeigy_exp1/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/system/setFieldsDict @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Applied AFTER the z->y rotation, so the vertical coordinate is y. +// Liquid fills everything below y = 0.8 m (loop + lower half of the degassing +// tank, whose axis is at y = 0.8); gas headspace above. + +// 0.99/0.01 (not 1/0) for numerical stability. +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 + volScalarFieldValue Z.liquid 0 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (1.0 0.8 1.0); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp1/writeGlobalVars.py b/experimental_cases/uloop_valadbeigy_exp1/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp1/writeGlobalVars.py @@ -0,0 +1,75 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, inletA_dye, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + # match on the first whitespace-delimited token so "inletA" does not + # also capture "inletA_dye" + token = line.split()[0] if line.split() else "" + if token == "inletA": + f.write(f"inletA\t{inletA:g};\n") + elif token == "inletA_dye": + f.write(f"inletA_dye\t{inletA_dye:g};\n") + elif token == "liqVol": + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + # sparger patch area (alpha.gas = 1 there, so the integral is the area); + # used only for the nominal gas velocity in the turbulence inlet BCs. + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=sparger,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def readDyeInletArea(): + # dye_inlet patch area. Unlike the sparger (alpha.gas = 1 there, so a single + # integral gives the area), no field is uniformly 1 at the dye port, so use + # area = integral(alpha.liquid) + integral(alpha.gas): the phase fractions sum + # to 1 pointwise, hence their integrals sum to the exact patch area. + base = os.path.join("postProcessing") + a_liq = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.liquid)", + "0", + "surfaceFieldValue.dat", + ) + ) + a_gas = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + ) + return a_liq + a_gas + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + A_dye = readDyeInletArea() + V = getLiqVol() + writeGvars(A, A_dye, V) diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_N2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_N2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/N2.liquid @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeN2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_O2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_O2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/O2.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeO2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $T0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/T.liquid @@ -0,0 +1,67 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $T0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $T0; + name dyeTliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0.0 0.0 0.0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name spargerInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar Q = 4.0*1e-3/60; // 4 L/min + + vectorField Up(this->size(), Foam::vector::zero); + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + this->operator==(Up); + #}; + } + + dye_inlet + { + type slip; + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + walls + { + type slip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/U.liquid @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0.0 0.0 0.0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type noSlip; + } + dye_inlet + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name dyeInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + vectorField Up(this->size(), Foam::vector::zero); + if (t >= tStart && t < tStop) + { + const scalar dyeVol = 50.0e-6; // m3 (50 mL) + const scalar Q = dyeVol/(tStop - tStart); // m3/s + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + } + this->operator==(Up); + #}; + + } + + outlet + { + type noSlip; + } + walls + { + type noSlip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid @@ -0,0 +1,64 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Ydefault = the inert specie (water). At the dye inlet the injected fluid is +// pure tracer Z, so water = 0 there. + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeYdliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/Z.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/Z.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Z.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeZliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 1.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaGas; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1.0; + value uniform 1.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alpha.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type fixedValue; + value uniform 0.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/alphat.liquid @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $k_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/k.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $k_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $k_inlet_liq; + name dyekinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/nut.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-2; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.gas b/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_gas; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $omega_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.liquid b/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/omega.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_liq; + +boundaryField +{ + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform $omega_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $omega_inlet_liq; + name dyeepsinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = 1.0; + const scalar tStop = 2.0; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + + outlet + { + type zeroGradient; + } + walls + { + type omegaWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/p b/experimental_cases/uloop_valadbeigy_exp2/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/p @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/0.orig/p_rgh b/experimental_cases/uloop_valadbeigy_exp2/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/0.orig/p_rgh @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type fixedFluxPressure; + value $internalField; + } + dye_inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + value $internalField; + } + walls + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/Allclean b/experimental_cases/uloop_valadbeigy_exp2/Allclean new file mode 100755 index 00000000..dc2f77db --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/Allclean @@ -0,0 +1,24 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +if [ -n "$WM_PROJECT_DIR" ]; then + . $WM_PROJECT_DIR/bin/tools/CleanFunctions + cleanCase +else + echo "WARNING: could not run cleanCase, OpenFOAM env not found" +fi + +# Remove 0 +[ -d "0" ] && rm -rf 0 + +# rm -f constant/triSurface/*.eMesh +# [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" +[ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" +[ -d "dynamicCode" ] && rm -rf "dynamicCode" +[ -d "processor*" ] && rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py new file mode 100644 index 00000000..bef692ab --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py @@ -0,0 +1,418 @@ +""" +Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 + +Open-top U-loop reactor as 3 stitchable gmsh blocks + +Structured hex mesh everywhere except the U-loop<->tank junction + +Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): + A hex : the U pipe + B tet : U-loop <-> tank junction + Two down-stubs (filleted where they meet the tank floor) + C hex : structured-hex tank, extruded up to the open top (Z_TOP). + Flat top face is the `outlet` boundary; sides = wall. + +This output block{A,B,C}.{msh,vtk} +""" + +import math +import gmsh +import numpy as np + +# Geometrical parameters +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +TANK_LEN = 2 * R_TANK +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] + + +def loop_pipe_length(include_tank=False): + ''' Compute pipe length which is reported in the paper''' + r_bend = R_BEND + z_bend_top = Z_HORIZ + r_bend + leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) + leg = leg_top - z_bend_top + arc = 0.5 * math.pi * r_bend + horiz = 2.0 * (X_LEG - r_bend) + return 2.0 * leg + 2.0 * arc + horiz + + +def reactor_volume(tank_fraction=1.0): + v_pipe = math.pi * R**2 * loop_pipe_length(include_tank=False) + v_tank = math.pi * R_TANK**2 * TANK_LEN + return v_pipe + tank_fraction * v_tank + +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] + +# --- resolution +RI_FRAC = 0.5 +N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge +# FINER mesh at the junction is obtained with SMALLER JUNCTION_RES +JUNCTION_RES = 1.8 + + +# ---- iterative mesh cleanup +N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) +N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) +N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells + + +def _pillow(geo, cx, cy, cz, r, n_side, n_rad): + '''Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)''' + ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] + ri = RI_FRAC * r + c = geo.addPoint(cx, cy, cz) + Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] + A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] + Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] + Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] + surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] + for i in range(4): + surfs.append(geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + for e in Qe + Arc: + geo.mesh.setTransfiniteCurve(e, n_side + 1) + for e in Rad: + geo.mesh.setTransfiniteCurve(e, n_rad + 1) + for s in surfs: + geo.mesh.setTransfiniteSurface(s) + geo.mesh.setRecombine(2, s) + return surfs + + +def _isflat(s, idx, val, tol=1e-6): + ''' + True if surface *s* lies entirely on the plane coord[idx] == val. + I.e. is a constant coordinate plane + useful to check if what we extruded gives us a flat surface + ''' + bb = gmsh.model.getBoundingBox(2, s) + return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol + + +def _tip(idx, val): + ''' + Find flat boundary surface after gmesh extrusion + ''' + vols = [t for _, t in gmsh.model.getEntities(3)] + bnd = {t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)} + return [(2, s) for s in bnd if _isflat(s, idx, val)] + + +def _by(surfs, idx, val): + '''Filter surface to those lying on the plane coord[idx] == val.''' + return [s for s in surfs if _isflat(s, idx, val)] + + +def _cx(s): + '''Bounding box used to distinguish the left and right leg''' + bb = gmsh.model.getBoundingBox(2, s) + return 0.5 * (bb[0] + bb[3]) + + +def _rims(surfs): + ''' find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block''' + rim = set() + for s in surfs: + for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): + rim.add(cc) + return rim + + +def _boundary_surfs(): + """Returns volume IDs and their boundary surface IDs.""" + vols = [t for _, t in gmsh.model.getEntities(3)] + return vols, [t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)] + + +def _cell_volume(): + """Sum of all 3-D cell volumes""" + tags, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + idx = {int(t): i for i, t in enumerate(tags)} + npe = {4: 4, 5: 8, 6: 6, 7: 5} + fans = { + 4: [(0, 1, 2, 3)], + 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), + (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], + 7: [(0, 1, 2, 4), (0, 2, 3, 4)], + } + total = 0.0 + ets, _, enodes = gmsh.model.mesh.getElements(3) + for et, en in zip(ets, enodes): + conn = np.array([idx[int(t)] for t in en]).reshape(-1, npe[et]) + P = coords[conn] + for a, b, c, d in fans[et]: + v = P[:, a], P[:, b], P[:, c], P[:, d] + total += np.abs(np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + return total / 6.0 + + +def _write(path, tag): + ''' Write Gmesh object to .msh and print summary''' + TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} + ets, etags, _ = gmsh.model.mesh.getElements(3) + counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} + vol = _cell_volume() + print(f"[block {tag}] cells={counts} volume={vol * 1e3:.3f} L") + gmsh.option.setNumber("Mesh.MshFileVersion", 2.2) + gmsh.write(path) + gmsh.write(path.rsplit(".", 1)[0] + ".vtk") + return vol + + +# --- U pipe (structured hex) +def build_block_A(path): + """Extrude the pillow cross-section down in sequence + 1) left leg + 2) 90 deg elbow + 3) bottom leg + 4) second 90 degree elbow + 5) up the right leg + + the two leg-top meet the filleted mesh as z=Z_AB""" + gmsh.initialize() + gmsh.model.add("A") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) + geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], recombine=True) + geo.synchronize() + + # left elbow: revolve the leg-bottom disk about y through the bend centre + geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # bottom horizontal run: extrude +x + geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, + numElements=[N_HOR], recombine=True) + geo.synchronize() + + # right elbow + geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # right leg: extrude +z up to Z_AB + geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, + numElements=[N_LEG], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + iface = _by(bnd, 2, Z_AB) + legL = [s for s in iface if _cx(s) < 0] + legR = [s for s in iface if _cx(s) > 0] + walls = [s for s in bnd if s not in iface] + gmsh.model.addPhysicalGroup(3, vols, name="pipeU") + gmsh.model.addPhysicalGroup(2, legL, name="int_A_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_A_legR") + gmsh.model.addPhysicalGroup(2, walls, name="wall_A") + + gmsh.model.mesh.generate(3) + vol = _write(path, "A") + gmsh.finalize() + return vol + + +# ---- block B: U-loop <-> tank junction +def build_block_B(path): + '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). + 2. Two cylindrical partial leds + 3. Fillet + + Interface matching (that was the hard part!) + - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + ''' + + gmsh.initialize() + gmsh.model.add("B") + gmsh.option.setNumber("General.Terminal", 0) + occ = gmsh.model.occ + + pen = 0.4 * (Z_BC - Z_BOT) + slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) + stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG)] + S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) + occ.synchronize() + vol = S[0][1] + + ring = [] + for _, e in gmsh.model.getEntities(1): + ex, _ey, ez = occ.getCenterOfMass(1, e) + x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) + if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ + and (x1 - x0) < 3 * R: + ring.append(e) + occ.fillet([vol], ring, [FILLET_R]) + occ.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C + walls = [s for s in bnd if s not in bot and s not in top] + legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] + legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] + + for s in bot: # match each stub rim to A (4*N_SIDE) + rc = _rims([s]) + per = max(1, round(4 * N_SIDE / len(rc))) + for cc in rc: + gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) + + gmsh.model.addPhysicalGroup(3, vols, name="juncB") + gmsh.model.addPhysicalGroup(2, legL, name="int_B_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_B_legR") + gmsh.model.addPhysicalGroup(2, top, name="int_B_top") + gmsh.model.addPhysicalGroup(2, walls, name="wall_B") + gmsh.option.setNumber("Mesh.MeshSizeMax", R / N_SIDE * JUNCTION_RES) + gmsh.option.setNumber("Mesh.Optimize", 1) + gmsh.option.setNumber("Mesh.OptimizeNetgen", 1) + gmsh.model.mesh.generate(3) + gmsh.model.mesh.optimize("Netgen") + vol = _write(path, "B") + gmsh.finalize() + return vol + + +# --- block C: hex tank +def build_block_C(path): + """Structured-hex tank extruded from Z_BC to Z_TOP. + + 1) N_TANK nodes per edge, matching block B's top + 2) Extrude +z to Z_TOP with N_HC uniform layers. + + Top face is the open outlet boundary; + Sides are wall_C; + Bottom is for stitching to block B. + """ + gmsh.initialize() + gmsh.model.add("C") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] + sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) + for e in l: + geo.mesh.setTransfiniteCurve(e, N_TANK + 1) + geo.mesh.setTransfiniteSurface(sq) + geo.mesh.setRecombine(2, sq) + geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_BC) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + walls = [s for s in bnd if s not in bot and s not in top] + gmsh.model.addPhysicalGroup(3, vols, name="tank") + gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") + gmsh.model.addPhysicalGroup(2, top, name="outlet") + gmsh.model.addPhysicalGroup(2, walls, name="wall_C") + gmsh.model.mesh.generate(3) + vol = _write(path, "C") + gmsh.finalize() + return vol + + +# ---- verify that the junction that stitch mesh will operate on has consistent +# face perimeter +def _plane_nodes(path, zval): + """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" + gmsh.initialize() + gmsh.open(path) + _, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + pts = [(x, y) for x, y, z in coords if abs(z - zval) < 1e-6] + gmsh.finalize() + return pts + + +def _circle_rim(pts, cx, r): + """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4) + + +def _square_rim(pts, hx, hy): + """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + + +def _verify(name, a, b, tol=1e-9): + """Assert two rim point sets have the same count and are coincident within tol.""" + assert len(a) == len(b), \ + f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + ok = worst < tol + print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." + + +def verify_interfaces(): + """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" + A_ab = _plane_nodes("blockA.msh", Z_AB) + B_ab = _plane_nodes("blockB.msh", Z_AB) + _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) + _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + B_bc = _plane_nodes("blockB.msh", Z_BC) + C_bc = _plane_nodes("blockC.msh", Z_BC) + _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) + + +# ---- main +if __name__ == "__main__": + print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + vols = { + "A": build_block_A("blockA.msh"), + "B": build_block_B("blockB.msh"), + "C": build_block_C("blockC.msh"), + } + verify_interfaces() + + box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) + print("=" * 70) + print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m") + print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L") + print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") + print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/fvModels b/experimental_cases/uloop_valadbeigy_exp2/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/fvModels @@ -0,0 +1,266 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include + #include + #}; + + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + const double pi = 3.14159265358979; + // ===== ball mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Vtip = 5; + const double sigma = 0.35; + const double startT = 0.1; + const double px = 0.063, py = 0.47, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 4.0*9.75/(rhoM*area); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dy)*(dy)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][0] -= -1.0*fth*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fth*V[i]*((-dx)/rr); + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = 0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= 1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= -1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= 1.0*fcp*V[i]; + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = -0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= 1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= 1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= -1.0*fcp*V[i]; + } + } + } + } + } + #}; +}; diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/g b/experimental_cases/uloop_valadbeigy_exp2/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars b/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA 0.000251007; +inletA_dye 0.000251007; +liqVol 0.00588087; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars_temp b/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/globalVars_temp @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA ; // sparger patch area [m2], filled by writeGlobalVars.py +inletA_dye ; // dye_inlet patch area [m2], filled by writeGlobalVars.py +liqVol ; // liquid volume [m3], filled by writeGlobalVars.py +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.gas b/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType laminar; +//simulationType RAS; +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.liquid b/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties b/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties_constantd b/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas b/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas @@ -0,0 +1,89 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + O2 + N2 +); + +defaultSpecie N2; + +O2 +{ + specie + { + molWeight 31.9988; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.28253784 0.00148308754 -7.57966669e-07 2.09470555e-10 -2.16717794e-14 -1088.45772 5.45323129 ); + lowCpCoeffs ( 3.78245636 -0.00299673416 9.84730201e-06 -9.68129509e-09 3.24372837e-12 -1063.94356 3.65767573 ); + } + transport + { + As 1.693411300e-06; + Ts 127; + } + elements + { + O 2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid b/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid @@ -0,0 +1,132 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + O2 + N2 + water + Z +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +// Passive dye tracer: identical to water, no interphase mass transfer (Z is +// deliberately absent from every Henry / diffusiveMassTransfer list). +Z +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +O2 +{ + specie + { + molWeight 31.9988; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrO2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrN2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py new file mode 100644 index 00000000..2f86cf69 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py @@ -0,0 +1,209 @@ +"""Volume-averaged dye tracer (Z.liquid) in the bottom U-bend box vs time. + +For every time folder this reads the ``Z.liquid`` with BiRD +then computes the cell-volume-weighted average over the +cells whose centres lie inside the box + + x in [-0.01, 0.01], y in [-0.1, 0.1], z in [-0.1, 0.1] [m] + +and plots that average versus time. +""" + +import os + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.utilities.ofio import ( + get_case_times, + read_cell_centers, + read_cell_volumes, + read_field, +) + +CASE = os.path.dirname(os.path.abspath(__file__)) + +# Averaging box [m]. The mesh is y-up after the presteps transformPoints. +X_BOUNDS = (-0.01, 0.01) +Y_BOUNDS = (-0.1, 0.1) +Z_BOUNDS = (-0.1, 0.1) + +# Mixing-time criterion. +BAND = 0.05 # within +/-5% of the final well-mixed value +TAIL_WINDOW = 0.5 # s, tail used to define the final value + + +def read_dye_start(): + """Dye injection start time [s], read from constant/globalVars.""" + with open(os.path.join(CASE, "constant", "globalVars")) as f: + for line in f: + if line.startswith("dyeStart"): + return float(line.split()[1].rstrip(";")) + return 1.0 + + +def box_mask(cell_centers): + """Boolean mask of cells whose centres lie inside the averaging box.""" + x, y, z = cell_centers[:, 0], cell_centers[:, 1], cell_centers[:, 2] + return ( + (x >= X_BOUNDS[0]) + & (x <= X_BOUNDS[1]) + & (y >= Y_BOUNDS[0]) + & (y <= Y_BOUNDS[1]) + & (z >= Z_BOUNDS[0]) + & (z <= Z_BOUNDS[1]) + ) + + +def box_volume_average(z_field, cell_volumes, mask): + """Cell-volume-weighted average of z_field over the masked cells. + + read_field returns a bare float for a uniform OpenFOAM field (e.g. the dye + tracer before injection starts); the volume average is then exactly that + value. Otherwise it is the volume-weighted mean over the box cells. + """ + if np.ndim(z_field) == 0: + return float(z_field) + else: + vol = cell_volumes[mask] + return float(np.sum(z_field[mask] * vol) / np.sum(vol)) + + +def mixing_time(t_arr, z_arr, t_start, continuous=True): + """Mixing time from the box-averaged dye signal. + + The final well-mixed value is the mean of the signal over the last + TAIL_WINDOW seconds. The mixing time is the interval from dye injection + (t_start) to the last instant the signal leaves the +/-BAND envelope of + that final value (after which it stays inside for good). + + Parameters + ---------- + t_arr : array-like + Time array. + z_arr : array-like + Box-averaged dye signal. + t_start : float + Injection time. + continuous : bool, optional + If True, linearly interpolates between the last timestep outside the + band and the first timestep inside to find the exact crossing time. + + Returns + ------- + t_mix : float + Mixing time measured from injection [s]. + t_settle : float + Absolute simulation time at which the signal settles [s]. + z_final : float + Final well-mixed box-averaged value. + """ + # Calculate final value and allowable band + z_final = float(np.mean(z_arr[t_arr >= t_arr[-1] - TAIL_WINDOW])) + band = BAND * abs(z_final) + + post = t_arr >= t_start + outside = post & (np.abs(z_arr - z_final) > band) + + if not np.any(outside): + # already within the band from injection onward + t_settle = t_start + else: + last_out = np.nonzero(outside)[0][-1] + + # Check if we have a subsequent point to interpolate with + if last_out + 1 < len(t_arr): + if continuous: + # Extract time and Z values for the crossing interval + t0, t1 = t_arr[last_out], t_arr[last_out + 1] + z0, z1 = z_arr[last_out], z_arr[last_out + 1] + + # Determine which boundary of the band was crossed + if z0 > z_final: + z_target = z_final + band # Crossed the top boundary + else: + z_target = z_final - band # Crossed the bottom boundary + + # Linearly interpolate to find the exact time t_settle at z_target + if z1 != z0: # Safety check to prevent division by zero + t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) + else: + t_settle = t1 + else: + # Original discrete behavior + t_settle = t_arr[last_out + 1] + else: + # The signal was outside the band up to the very last recorded timestep + t_settle = t_arr[last_out] + + return t_settle - t_start, t_settle, z_final + +if __name__ == "__main__": + os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) + + # Geometry is time-independent: read the cell centres and cell volumes once + # and keep them in the shared field_dict cache. + cell_centers, geom = read_cell_centers(CASE) + n_cells = cell_centers.shape[0] + cell_volumes, geom = read_cell_volumes(CASE, field_dict=geom) + + mask = box_mask(cell_centers) + if mask.sum() == 0: + raise RuntimeError("averaging box contains no cell centres") + + times_float, times_str = get_case_times(CASE) + + t_list, z_list = [], [] + for t_val, t_str in zip(times_float, times_str): + try: + # Fresh field_dict per time so Z.liquid is never served stale. + z_field, _ = read_field(CASE, t_str, "Z.liquid", n_cells=n_cells) + except FileNotFoundError: + continue + t_list.append(t_val) + z_list.append(box_volume_average(z_field, cell_volumes, mask)) + + order = np.argsort(t_list) + t_arr = np.asarray(t_list)[order] + z_arr = np.asarray(z_list)[order] + + np.savetxt( + os.path.join(CASE, "Z_box_average.dat"), + np.column_stack([t_arr, z_arr]), + header="time[s] volAvg(Z.liquid)_box", + ) + + dye_start = read_dye_start() + t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + + with open(os.path.join(CASE, "mix_time.txt"), "w") as f: + f.write(f"Continuous: {t_mix:.4f}\n") + f.write(f"Discrete: {t_mix_disc:.4f}\n") + + fig, ax = plt.subplots(figsize=(6, 4)) + ax.plot(t_arr, z_arr, color="k") + ax.axhline(z_final, color="b", ls="--", label=r"$Z_{final}$") + ax.axhspan( + (1 - BAND) * z_final, (1 + BAND) * z_final, color="b", alpha=0.15 + ) + ax.axvline( + t_settle, color="r", ls=":", label=f"$t_{{mix}}$={t_mix_disc:.2f} s" + ) + ax.set_xlim(left=dye_start) + pretty_labels("time [s]", r"box-averaged $Z_{liquid}$ [-]", 14, ax=ax) + ax.legend() + fig.savefig( + os.path.join(CASE, "Figures", "Z_box_average.png"), + dpi=150, + bbox_inches="tight", + ) + + print(f"box cells : {int(mask.sum())}") + print(f"time folders averaged : {len(t_arr)}") + print(f"final well-mixed Z discrete : {z_final_disc:.6g}") + print(f"final well-mixed Z continous : {z_final:.6g}") + print(f"dye injection start : {dye_start:.3f} s") + print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") + print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") + print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") diff --git a/experimental_cases/uloop_valadbeigy_exp2/presteps.sh b/experimental_cases/uloop_valadbeigy_exp2/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/presteps.sh @@ -0,0 +1,77 @@ +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +# setup IC +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + +conda deactivate diff --git a/experimental_cases/uloop_valadbeigy_exp2/run.sh b/experimental_cases/uloop_valadbeigy_exp2/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/run.sh @@ -0,0 +1,75 @@ +#!/bin/bash +### OpenFOAM command +./Allclean +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + +### BiRD command +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + + +birdmultiphaseEulerFoam diff --git a/experimental_cases/uloop_valadbeigy_exp2/script b/experimental_cases/uloop_valadbeigy_exp2/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/script @@ -0,0 +1,16 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=14:59:00 +#SBATCH --account=gas2fuels + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes -fields "(U.liquid alpha.gas Z.liquid)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp2/script_post b/experimental_cases/uloop_valadbeigy_exp2/script_post new file mode 100755 index 00000000..dcbf59d8 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/script_post @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=01:59:00 +#SBATCH --account=gas2fuels +#SBATCH --dependency=afterany:15800966 + +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp2/stitch_and_check.sh b/experimental_cases/uloop_valadbeigy_exp2/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/stitch_and_check.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# +# Stitch a list of gmsh block meshes into ONE OpenFOAM mesh and run checkMesh. +# +# Each mesh is converted with gmshToFoam; mesh #0 becomes the master case that +# the rest are merged into; then each --stitch pair is coupled with integral +# (non -perfect) stitchMesh +# +# Options: +# --mesh (repeatable; order = stack order, #0 is master) +# --stitch (repeatable; integral, for non-matching faces) +# --stitch-perfect (repeatable; -perfect, for conformal faces) +# --case (output case dir, default: stitched_case) + +set -euo pipefail + +CASE="stitched_case" +MESHES=() +STITCHES=() # entries: "integral m:s" or "perfect m:s" (order preserved) +while [[ $# -gt 0 ]]; do + case "$1" in + --mesh) MESHES+=("$2"); shift 2;; + --stitch) STITCHES+=("integral $2"); shift 2;; + --stitch-perfect) STITCHES+=("perfect $2"); shift 2;; + --case) CASE="$2"; shift 2;; + *) echo "unknown argument: $1" >&2; exit 1;; + esac +done + +# >=1 mesh: with a single --mesh and no --stitch this just gmshToFoam+checkMesh +# one block (useful to isolate which block owns a checkMesh failure). +[[ ${#MESHES[@]} -ge 1 ]] || { echo "need at least one --mesh file" >&2; exit 1; } +command -v gmshToFoam >/dev/null 2>&1 || { + echo "OpenFOAM not found on PATH — source OpenFOAM-9 first." >&2; exit 1; } + +# minimal case skeleton (mesh utilities need controlDict/fvSchemes/fvSolution) +write_system() { + local d="$1"; mkdir -p "$d/system" "$d/constant" + cat > "$d/system/controlDict" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object controlDict; } +application checkMesh; +startFrom startTime; startTime 0; +stopAt endTime; endTime 1; +deltaT 1; writeControl timeStep; writeInterval 1; +EOF + cat > "$d/system/fvSchemes" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSchemes; } +ddtSchemes { default steadyState; } +gradSchemes { default Gauss linear; } +divSchemes { default none; } +laplacianSchemes { default Gauss linear corrected; } +interpolationSchemes { default linear; } +snGradSchemes { default corrected; } +EOF + cat > "$d/system/fvSolution" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSolution; } +solvers {} +EOF +} + +echo "==> master case: $CASE (from ${MESHES[0]})" +rm -rf "$CASE"; write_system "$CASE" +gmshToFoam "${MESHES[0]}" -case "$CASE" + +# convert + merge the remaining blocks into the master +for ((i=1; i<${#MESHES[@]}; i++)); do + sub="${CASE}_add${i}" + echo "==> add block $i: ${MESHES[$i]}" + rm -rf "$sub"; write_system "$sub" + gmshToFoam "${MESHES[$i]}" -case "$sub" + # merge into master (OF-9 foundation syntax) + mergeMeshes "$CASE" "$sub" -overwrite + rm -rf "$sub" +done + +# couple each interface with its chosen mode +for spec in "${STITCHES[@]}"; do + mode="${spec%% *}"; pair="${spec#* }" + master="${pair%%:*}"; slave="${pair##*:}" + flags="-overwrite"; [[ "$mode" == perfect ]] && flags="$flags -perfect" + echo "==> stitchMesh ($mode) $master $slave" + stitchMesh $flags "$master" "$slave" -case "$CASE" +done + +echo "==> checkMesh" +checkMesh -allGeometry -allTopology -case "$CASE" +echo "==> done. Mesh in $CASE/constant/polyMesh" diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/controlDict b/experimental_cases/uloop_valadbeigy_exp2/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/controlDict @@ -0,0 +1,95 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt writeNow;//endTime; + +// ~20 s spin-up for steady circulation, dye pulse at t=20-21 s, then ~24 s to +// capture a ~10 s mixing time. +endTime 20; + +deltaT 1e-6; + +writeControl adjustableRunTime; +//writeControl timeStep; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 1.0; + +maxDeltaT 0.001; + + +functions +{ + + limitNut + { + type coded; + libs ("libutilityFunctionObjects.so"); + name limitNut; + codeExecute + #{ + const scalar nutMaxLiq = 1e-3; // [m2/s] liquid nut ceiling (tune) + //const scalar nutMaxGas = 1e-3; // [m2/s] gas nut ceiling (tune) + + volScalarField& nutLiq = + mesh().lookupObjectRef("nut.liquid"); + //volScalarField& nutGas = + // mesh().lookupObjectRef("nut.gas"); + + nutLiq = min(nutLiq, dimensionedScalar(nutLiq.dimensions(), nutMaxLiq)); + //nutGas = min(nutGas, dimensionedScalar(nutGas.dimensions(), nutMaxGas)); + nutLiq.correctBoundaryConditions(); + //nutGas.correctBoundaryConditions(); + + //Info<< "limitNut: max nut.liq=" << max(nutLiq).value() + // << " nut.gas=" << max(nutGas).value() << endl; + Info<< "limitNut: max nut.liq=" << max(nutLiq).value() << endl; + #}; + } + + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) + + // Mixing time is post-processed offline from the written time folders + // (Z.liquid + alpha.liquid), so no sensor/dyeMean function objects here. + // Set writeInterval to the temporal resolution the offline analysis needs. +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/createPatchDict b/experimental_cases/uloop_valadbeigy_exp2/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/createPatchDict @@ -0,0 +1,35 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object createPatchDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Consolidate the per-block wall patches (wall_A/B/C) into a single "walls" patch. +// createPatch also drops the now-empty stitch interface patches (int_*, 0 faces). +// The open tank roof is already its own "outlet" mesh patch (block C physical +// group), so it is NOT merged here and needs no surfaceToPatch. sparger and +// dye_inlet are still carved from "walls" with surfaceToPatch in presteps.sh. + +pointSync false; + +patches +( + { + name walls; + patchInfo { type wall; } + constructFrom patches; + patches (wall_A wall_B wall_C); + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/decomposeParDict b/experimental_cases/uloop_valadbeigy_exp2/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/fvConstraints b/experimental_cases/uloop_valadbeigy_exp2/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/fvSchemes b/experimental_cases/uloop_valadbeigy_exp2/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/fvSchemes @@ -0,0 +1,76 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + //default Gauss linear; + //limited cellLimited Gauss linear 1; + default cellLimited 1.5 leastSquares 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + //"div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + //"div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,U.*\)" Gauss Minmod; + "div\(phi.*,U.*\)" Gauss Minmod; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon)m\)" Gauss limitedLinear 1; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + //default Gauss linear corrected; + default Gauss linear corrected 0.33; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + //default uncorrected; + default limited corrected 0.33; +} + +wallDist +{ + //method Poisson; + //nRequired true; + method meshWave; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/fvSolution b/experimental_cases/uloop_valadbeigy_exp2/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/fvSolution @@ -0,0 +1,121 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega|epsilon|omega).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 1e-3; + minIter 0; + maxIter 5; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 1e-3; + minIter 0; + maxIter 0; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 2; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/inlets_outlets.json b/experimental_cases/uloop_valadbeigy_exp2/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/inlets_outlets.json @@ -0,0 +1,24 @@ +{ + "sparger": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.23, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ], + "dye_inlet": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.65, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ] +} diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/mixers.json b/experimental_cases/uloop_valadbeigy_exp2/system/mixers.json new file mode 100644 index 00000000..eccd2af9 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/mixers.json @@ -0,0 +1,45 @@ +{ + "mixers": [ + { + "x": 0.063, + "y": 0.47, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "power": 14.95, + "Vtip": 5, + "sign": "-", + "swirl_sign": "-" + } + ], + "static_mixers": [ + { + "x": 0.063, + "y": 0.05, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "-", + "swirl_sign": "-" + }, + { + "x": -0.063, + "y": 0.275, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "+", + "swirl_sign": "+" + } + ], + "volumetric_source": "ball", + "power": "from_P", + "momentum_source": "axial_and_swirl" +} diff --git a/experimental_cases/uloop_valadbeigy_exp2/system/setFieldsDict b/experimental_cases/uloop_valadbeigy_exp2/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/system/setFieldsDict @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Applied AFTER the z->y rotation, so the vertical coordinate is y. +// Liquid fills everything below y = 0.8 m (loop + lower half of the degassing +// tank, whose axis is at y = 0.8); gas headspace above. + +// 0.99/0.01 (not 1/0) for numerical stability. +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 + volScalarFieldValue Z.liquid 0 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (1.0 0.8 1.0); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp2/writeGlobalVars.py b/experimental_cases/uloop_valadbeigy_exp2/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp2/writeGlobalVars.py @@ -0,0 +1,75 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, inletA_dye, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + # match on the first whitespace-delimited token so "inletA" does not + # also capture "inletA_dye" + token = line.split()[0] if line.split() else "" + if token == "inletA": + f.write(f"inletA\t{inletA:g};\n") + elif token == "inletA_dye": + f.write(f"inletA_dye\t{inletA_dye:g};\n") + elif token == "liqVol": + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + # sparger patch area (alpha.gas = 1 there, so the integral is the area); + # used only for the nominal gas velocity in the turbulence inlet BCs. + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=sparger,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def readDyeInletArea(): + # dye_inlet patch area. Unlike the sparger (alpha.gas = 1 there, so a single + # integral gives the area), no field is uniformly 1 at the dye port, so use + # area = integral(alpha.liquid) + integral(alpha.gas): the phase fractions sum + # to 1 pointwise, hence their integrals sum to the exact patch area. + base = os.path.join("postProcessing") + a_liq = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.liquid)", + "0", + "surfaceFieldValue.dat", + ) + ) + a_gas = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + ) + return a_liq + a_gas + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + A_dye = readDyeInletArea() + V = getLiqVol() + writeGvars(A, A_dye, V) diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_N2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_N2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/N2.liquid @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeN2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.gas @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $f_O2; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $f_O2; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/O2.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object O2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeO2liq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform $T0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/T.liquid @@ -0,0 +1,67 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $T0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $T0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $T0; + name dyeTliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0.0 0.0 0.0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name spargerInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar Q = 4.0*1e-3/60; // 4 L/min + + vectorField Up(this->size(), Foam::vector::zero); + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + this->operator==(Up); + #}; + } + + dye_inlet + { + type slip; + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + walls + { + type slip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/U.liquid @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0.0 0.0 0.0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type noSlip; + } + dye_inlet + { + type codedFixedValue; + value uniform (0.0 0.0 0.0); + name dyeInjection; + codeInclude + #{ + #include "volFields.H" + #}; + code + #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + vectorField Up(this->size(), Foam::vector::zero); + if (t >= tStart && t < tStop) + { + const scalar dyeVol = 50.0e-6; // m3 (50 mL) + const scalar Q = dyeVol/(tStop - tStart); // m3/s + const scalar area = gSum(this->patch().magSf()); + if (area > SMALL) + { + Up = -(Q/area)*this->patch().nf(); + } + } + this->operator==(Up); + #}; + + } + + outlet + { + type noSlip; + } + walls + { + type noSlip; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid @@ -0,0 +1,64 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Ydefault = the inert specie (water). At the dye inlet the injected fluid is +// pure tracer Z, so water = 0 there. + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeYdliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/Z.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/Z.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Z.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeZliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.gas @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 1.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 0.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaGas; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1.0; + value uniform 1.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alpha.liquid @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform 0.0; + } + dye_inlet + { + type codedMixed; + refValue uniform 1.0; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform 0.0; + name dyeAlphaliq; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + outlet + { + type fixedValue; + value uniform 0.0; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/alphat.liquid @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $k_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/k.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0.0; + +boundaryField +{ + sparger + { + type zeroGradient; + } + + dye_inlet + { + type codedMixed; + refValue uniform $k_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $k_inlet_liq; + name dyekinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = __DYE_START__; + const scalar tStop = __DYE_STOP__; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + outlet + { + type zeroGradient; + } + walls + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/nut.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-2; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.gas b/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_gas; + +boundaryField +{ + sparger + { + type fixedValue; + value uniform $omega_inlet_gas; + } + dye_inlet + { + type zeroGradient; + } + outlet + { + type zeroGradient; + } + walls + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.liquid b/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/omega.liquid @@ -0,0 +1,63 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_liq; + +boundaryField +{ + sparger + { + type zeroGradient; + } + dye_inlet + { + type codedMixed; + refValue uniform $omega_inlet_liq; + refGradient uniform 0.0; + valueFraction uniform 0.0; + value uniform $omega_inlet_liq; + name dyeepsinlet; + code #{ + const scalar t = this->db().time().value(); + const scalar tStart = 1.0; + const scalar tStop = 2.0; + if (t >= tStart && t < tStop) + { + this->valueFraction() = 1.0; + } + else + { + this->valueFraction() = 0.0; + } + #}; + } + + + outlet + { + type zeroGradient; + } + walls + { + type omegaWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/p b/experimental_cases/uloop_valadbeigy_exp3/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/p @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type calculated; + value $internalField; + } + dye_inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + walls + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/0.orig/p_rgh b/experimental_cases/uloop_valadbeigy_exp3/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/0.orig/p_rgh @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + sparger + { + type fixedFluxPressure; + value $internalField; + } + dye_inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + value $internalField; + } + walls + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/Allclean b/experimental_cases/uloop_valadbeigy_exp3/Allclean new file mode 100755 index 00000000..dc2f77db --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/Allclean @@ -0,0 +1,24 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +if [ -n "$WM_PROJECT_DIR" ]; then + . $WM_PROJECT_DIR/bin/tools/CleanFunctions + cleanCase +else + echo "WARNING: could not run cleanCase, OpenFOAM env not found" +fi + +# Remove 0 +[ -d "0" ] && rm -rf 0 + +# rm -f constant/triSurface/*.eMesh +# [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" +[ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" +[ -d "dynamicCode" ] && rm -rf "dynamicCode" +[ -d "processor*" ] && rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py new file mode 100644 index 00000000..bef692ab --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py @@ -0,0 +1,418 @@ +""" +Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 + +Open-top U-loop reactor as 3 stitchable gmsh blocks + +Structured hex mesh everywhere except the U-loop<->tank junction + +Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): + A hex : the U pipe + B tet : U-loop <-> tank junction + Two down-stubs (filleted where they meet the tank floor) + C hex : structured-hex tank, extruded up to the open top (Z_TOP). + Flat top face is the `outlet` boundary; sides = wall. + +This output block{A,B,C}.{msh,vtk} +""" + +import math +import gmsh +import numpy as np + +# Geometrical parameters +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +TANK_LEN = 2 * R_TANK +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] + + +def loop_pipe_length(include_tank=False): + ''' Compute pipe length which is reported in the paper''' + r_bend = R_BEND + z_bend_top = Z_HORIZ + r_bend + leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) + leg = leg_top - z_bend_top + arc = 0.5 * math.pi * r_bend + horiz = 2.0 * (X_LEG - r_bend) + return 2.0 * leg + 2.0 * arc + horiz + + +def reactor_volume(tank_fraction=1.0): + v_pipe = math.pi * R**2 * loop_pipe_length(include_tank=False) + v_tank = math.pi * R_TANK**2 * TANK_LEN + return v_pipe + tank_fraction * v_tank + +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] + +# --- resolution +RI_FRAC = 0.5 +N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge +# FINER mesh at the junction is obtained with SMALLER JUNCTION_RES +JUNCTION_RES = 1.8 + + +# ---- iterative mesh cleanup +N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) +N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) +N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells + + +def _pillow(geo, cx, cy, cz, r, n_side, n_rad): + '''Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)''' + ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] + ri = RI_FRAC * r + c = geo.addPoint(cx, cy, cz) + Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] + A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] + Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] + Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] + surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] + for i in range(4): + surfs.append(geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + for e in Qe + Arc: + geo.mesh.setTransfiniteCurve(e, n_side + 1) + for e in Rad: + geo.mesh.setTransfiniteCurve(e, n_rad + 1) + for s in surfs: + geo.mesh.setTransfiniteSurface(s) + geo.mesh.setRecombine(2, s) + return surfs + + +def _isflat(s, idx, val, tol=1e-6): + ''' + True if surface *s* lies entirely on the plane coord[idx] == val. + I.e. is a constant coordinate plane + useful to check if what we extruded gives us a flat surface + ''' + bb = gmsh.model.getBoundingBox(2, s) + return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol + + +def _tip(idx, val): + ''' + Find flat boundary surface after gmesh extrusion + ''' + vols = [t for _, t in gmsh.model.getEntities(3)] + bnd = {t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)} + return [(2, s) for s in bnd if _isflat(s, idx, val)] + + +def _by(surfs, idx, val): + '''Filter surface to those lying on the plane coord[idx] == val.''' + return [s for s in surfs if _isflat(s, idx, val)] + + +def _cx(s): + '''Bounding box used to distinguish the left and right leg''' + bb = gmsh.model.getBoundingBox(2, s) + return 0.5 * (bb[0] + bb[3]) + + +def _rims(surfs): + ''' find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block''' + rim = set() + for s in surfs: + for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): + rim.add(cc) + return rim + + +def _boundary_surfs(): + """Returns volume IDs and their boundary surface IDs.""" + vols = [t for _, t in gmsh.model.getEntities(3)] + return vols, [t for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False)] + + +def _cell_volume(): + """Sum of all 3-D cell volumes""" + tags, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + idx = {int(t): i for i, t in enumerate(tags)} + npe = {4: 4, 5: 8, 6: 6, 7: 5} + fans = { + 4: [(0, 1, 2, 3)], + 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), + (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], + 7: [(0, 1, 2, 4), (0, 2, 3, 4)], + } + total = 0.0 + ets, _, enodes = gmsh.model.mesh.getElements(3) + for et, en in zip(ets, enodes): + conn = np.array([idx[int(t)] for t in en]).reshape(-1, npe[et]) + P = coords[conn] + for a, b, c, d in fans[et]: + v = P[:, a], P[:, b], P[:, c], P[:, d] + total += np.abs(np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + return total / 6.0 + + +def _write(path, tag): + ''' Write Gmesh object to .msh and print summary''' + TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} + ets, etags, _ = gmsh.model.mesh.getElements(3) + counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} + vol = _cell_volume() + print(f"[block {tag}] cells={counts} volume={vol * 1e3:.3f} L") + gmsh.option.setNumber("Mesh.MshFileVersion", 2.2) + gmsh.write(path) + gmsh.write(path.rsplit(".", 1)[0] + ".vtk") + return vol + + +# --- U pipe (structured hex) +def build_block_A(path): + """Extrude the pillow cross-section down in sequence + 1) left leg + 2) 90 deg elbow + 3) bottom leg + 4) second 90 degree elbow + 5) up the right leg + + the two leg-top meet the filleted mesh as z=Z_AB""" + gmsh.initialize() + gmsh.model.add("A") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) + geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], recombine=True) + geo.synchronize() + + # left elbow: revolve the leg-bottom disk about y through the bend centre + geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # bottom horizontal run: extrude +x + geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, + numElements=[N_HOR], recombine=True) + geo.synchronize() + + # right elbow + geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, + math.pi / 2, numElements=[N_ARC], recombine=True) + geo.synchronize() + + # right leg: extrude +z up to Z_AB + geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, + numElements=[N_LEG], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + iface = _by(bnd, 2, Z_AB) + legL = [s for s in iface if _cx(s) < 0] + legR = [s for s in iface if _cx(s) > 0] + walls = [s for s in bnd if s not in iface] + gmsh.model.addPhysicalGroup(3, vols, name="pipeU") + gmsh.model.addPhysicalGroup(2, legL, name="int_A_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_A_legR") + gmsh.model.addPhysicalGroup(2, walls, name="wall_A") + + gmsh.model.mesh.generate(3) + vol = _write(path, "A") + gmsh.finalize() + return vol + + +# ---- block B: U-loop <-> tank junction +def build_block_B(path): + '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). + 2. Two cylindrical partial leds + 3. Fillet + + Interface matching (that was the hard part!) + - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + ''' + + gmsh.initialize() + gmsh.model.add("B") + gmsh.option.setNumber("General.Terminal", 0) + occ = gmsh.model.occ + + pen = 0.4 * (Z_BC - Z_BOT) + slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) + stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG)] + S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) + occ.synchronize() + vol = S[0][1] + + ring = [] + for _, e in gmsh.model.getEntities(1): + ex, _ey, ez = occ.getCenterOfMass(1, e) + x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) + if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ + and (x1 - x0) < 3 * R: + ring.append(e) + occ.fillet([vol], ring, [FILLET_R]) + occ.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C + walls = [s for s in bnd if s not in bot and s not in top] + legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] + legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] + + for s in bot: # match each stub rim to A (4*N_SIDE) + rc = _rims([s]) + per = max(1, round(4 * N_SIDE / len(rc))) + for cc in rc: + gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) + + gmsh.model.addPhysicalGroup(3, vols, name="juncB") + gmsh.model.addPhysicalGroup(2, legL, name="int_B_legL") + gmsh.model.addPhysicalGroup(2, legR, name="int_B_legR") + gmsh.model.addPhysicalGroup(2, top, name="int_B_top") + gmsh.model.addPhysicalGroup(2, walls, name="wall_B") + gmsh.option.setNumber("Mesh.MeshSizeMax", R / N_SIDE * JUNCTION_RES) + gmsh.option.setNumber("Mesh.Optimize", 1) + gmsh.option.setNumber("Mesh.OptimizeNetgen", 1) + gmsh.model.mesh.generate(3) + gmsh.model.mesh.optimize("Netgen") + vol = _write(path, "B") + gmsh.finalize() + return vol + + +# --- block C: hex tank +def build_block_C(path): + """Structured-hex tank extruded from Z_BC to Z_TOP. + + 1) N_TANK nodes per edge, matching block B's top + 2) Extrude +z to Z_TOP with N_HC uniform layers. + + Top face is the open outlet boundary; + Sides are wall_C; + Bottom is for stitching to block B. + """ + gmsh.initialize() + gmsh.model.add("C") + gmsh.option.setNumber("General.Terminal", 0) + geo = gmsh.model.geo + + p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] + sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) + for e in l: + geo.mesh.setTransfiniteCurve(e, N_TANK + 1) + geo.mesh.setTransfiniteSurface(sq) + geo.mesh.setRecombine(2, sq) + geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.synchronize() + + vols, bnd = _boundary_surfs() + bot = _by(bnd, 2, Z_BC) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + walls = [s for s in bnd if s not in bot and s not in top] + gmsh.model.addPhysicalGroup(3, vols, name="tank") + gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") + gmsh.model.addPhysicalGroup(2, top, name="outlet") + gmsh.model.addPhysicalGroup(2, walls, name="wall_C") + gmsh.model.mesh.generate(3) + vol = _write(path, "C") + gmsh.finalize() + return vol + + +# ---- verify that the junction that stitch mesh will operate on has consistent +# face perimeter +def _plane_nodes(path, zval): + """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" + gmsh.initialize() + gmsh.open(path) + _, coords, _ = gmsh.model.mesh.getNodes() + coords = coords.reshape(-1, 3) + pts = [(x, y) for x, y, z in coords if abs(z - zval) < 1e-6] + gmsh.finalize() + return pts + + +def _circle_rim(pts, cx, r): + """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4) + + +def _square_rim(pts, hx, hy): + """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" + return sorted((round(x, 9), round(y, 9)) for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + + +def _verify(name, a, b, tol=1e-9): + """Assert two rim point sets have the same count and are coincident within tol.""" + assert len(a) == len(b), \ + f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + ok = worst < tol + print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." + + +def verify_interfaces(): + """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" + A_ab = _plane_nodes("blockA.msh", Z_AB) + B_ab = _plane_nodes("blockB.msh", Z_AB) + _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) + _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + B_bc = _plane_nodes("blockB.msh", Z_BC) + C_bc = _plane_nodes("blockC.msh", Z_BC) + _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) + + +# ---- main +if __name__ == "__main__": + print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + vols = { + "A": build_block_A("blockA.msh"), + "B": build_block_B("blockB.msh"), + "C": build_block_C("blockC.msh"), + } + verify_interfaces() + + box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) + print("=" * 70) + print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m") + print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L") + print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") + print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/fvModels b/experimental_cases/uloop_valadbeigy_exp3/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/fvModels @@ -0,0 +1,266 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include + #include + #}; + + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + const double pi = 3.14159265358979; + // ===== ball mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Vtip = 5; + const double sigma = 0.35; + const double startT = 0.1; + const double px = 0.063, py = 0.47, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double rhs = 4.0*9.75/(rhoM*area); + double V2 = (V1>1e-6) ? 2.0*V1 : std::cbrt(std::abs(rhs)); + for (int it = 0; it < 100; ++it) + { + const double F = (V2-V1)*(V2+V1)*(V2+V1) + 0.35*(V1+V2)*Vtip*Vtip - rhs; + const double dF = 3.0*V2*V2 + 2.0*V1*V2 - V1*V1 + 0.35*Vtip*Vtip; + const double dV = F/dF; + V2 -= dV; + if (std::abs(dV) < 1e-10) break; + } + const double Tax = 0.5*rhoM*area*(V2*V2 - V1*V1); + const double Qsw = 0.25*rhoM*(V1+V2)*sigma*Rmix*area*Vtip; + scalar Sax = 0.0, Sth = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + Sax += alphaL[i]*g*V[i]; + const double rr = std::sqrt(d2-(dy)*(dy)); + Sth += alphaL[i]*g*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Sth, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fax = Tax/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fax*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Sth > 1e-30) + { + const double fth = Qsw/Sth*alphaL[i]*g; + Usource[i][0] -= -1.0*fth*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fth*V[i]*((-dx)/rr); + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = 0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && -1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? -1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= 1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= -1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= -1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= 1.0*fcp*V[i]; + } + } + } + } + } + // ===== static mixer ===== + { + const double Rmix = 0.018; + const double area = pi*Rmix*Rmix; + const double Snum = 0.6; + const double Kloss = 0.5; + const double startT = 0.1; + const double px = -0.063, py = 0.05, pz = 0.0; + if (time.value() > startT) + { + scalar sV = 0.0, sVU = 0.0, sVrho = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix && 1.0*dy < 0.0) + { + const double w = V[i]*alphaL[i]; + sV += w; sVU += w*UL[i][1]; sVrho += w*rhoL[i]; + } + } + reduce(sV, sumOp()); + reduce(sVU, sumOp()); + reduce(sVrho, sumOp()); + double V1 = (sV>1e-30) ? 1.0*(sVU/sV) : 0.0; + if (V1 < 0.0) V1 = 0.0; + const double rhoM = (sV>1e-30) ? sVrho/sV : 1000.0; + const double Qsw = Snum*Rmix*rhoM*area*V1*V1; + const double Tls = 0.5*Kloss*rhoM*area*V1*V1; + scalar Sax = 0.0, Ssw = 0.0; + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + const double rr = std::sqrt(d2-(dy)*(dy)); + const double ux = UL[i][1]; + Sax += alphaL[i]*g*V[i]; + Ssw += alphaL[i]*g*rhoL[i]*ux*ux*rr*V[i]; + } + } + reduce(Sax, sumOp()); + reduce(Ssw, sumOp()); + forAll(C, i) + { + const double dx=C[i].x()-px, dy=C[i].y()-py, dz=C[i].z()-pz; + const double d2 = dx*dx + dy*dy + dz*dz; + if (d2 <= Rmix*Rmix) + { + const double epsi = std::max(0.6123724356957945*Rmix, 2.0*std::cbrt(V[i])); + const double g = std::exp(-d2/(epsi*epsi)); + if (Sax > 1e-30) + { + const double fvisc = Tls/Sax*alphaL[i]*g; + Usource[i][1] -= -1.0*fvisc*V[i]; + } + const double rr = std::sqrt(d2-(dy)*(dy)); + if (rr > 1e-3*Rmix && Ssw > 1e-30) + { + const double ux = UL[i][1]; + const double uth = UL[i][0]*((dz)/rr) + UL[i][2]*((-dx)/rr); + const double A0 = Qsw/Ssw; + const double fsw = A0*rhoL[i]*ux*ux*alphaL[i]*g; + Usource[i][0] -= 1.0*fsw*V[i]*((dz)/rr); + Usource[i][2] -= 1.0*fsw*V[i]*((-dx)/rr); + const double fcp = A0*rhoL[i]*ux*uth*alphaL[i]*g; + Usource[i][1] -= -1.0*fcp*V[i]; + } + } + } + } + } + #}; +}; diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/g b/experimental_cases/uloop_valadbeigy_exp3/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars b/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA 0.000251007; +inletA_dye 0.000251007; +liqVol 0.00588087; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars_temp b/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/globalVars_temp @@ -0,0 +1,70 @@ +T0 300; //initial T(K) which stays constant +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_N2 31.2e-3; +//****** diffusion coeff *********** +D_O2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_O2,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_N2_298 0.015; +DH_N2 1300; +He_O2 #calc "$H_O2_298 * exp($DH_O2 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas mass frac (air)************* +f_O2 0.233; +f_N2 0.767; +//*******aeration / dye injection************** +gasFlowRate 6.6667e-5; // 4 L/min air sparged = 4e-3/60 m3/s +// Dye = 50 mL over [dyeStart, dyeStop]; injected by the codedFixedValue BC on +// U.liquid at dye_inlet (which recomputes the patch area at runtime). presteps.sh +// substitutes these values into the __DYE_START__/__DYE_STOP__ tokens of the +// coded dye BCs in 0/ ($vars do not expand inside the #{ #} code blocks). +// dyeStart is also read by get_mixing_time.py. +dyeStart 1.0; // s, dye injection start (after steady circulation) +dyeStop 2.0; // s, dye injection stop (1 s window, 50 mL total) +dyeVol 50.0e-6; // m3 (50 mL); MUST match the literal in 0.orig/U.liquid +//********************************* +inletA ; // sparger patch area [m2], filled by writeGlobalVars.py +inletA_dye ; // dye_inlet patch area [m2], filled by writeGlobalVars.py +liqVol ; // liquid volume [m3], filled by writeGlobalVars.py +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$gasFlowRate / ($inletA * $alphaGas)"; // nominal sparger gas velocity (turbulence BCs) +//********************************* +LeLiqO2 #calc "$kThermLiq / $rho0MixLiq / $D_O2 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_O2*$LeLiqO2+$f_N2*$LeLiqN2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kO2 #calc "$D_O2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrO2 #calc "$muMixLiq*$CpMixLiq / $kO2"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.04; // mixing length = DN40 pipe diameter (was 0.5 m, too large -> eps too small) +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; +//********************************* +// Dye-inlet (liquid) turbulence: the dye is injected at its OWN velocity through +// its OWN (smaller) pipe, so k/eps there must not reuse the sparger-gas values. +// uDye = injected volumetric flow / dye_inlet area; l_scale_dye = dye pipe diameter. +l_scale_dye 0.02; // dye pipe diameter [m] +uDye #calc "$dyeVol / (($dyeStop - $dyeStart) * $inletA_dye)"; // nominal dye injection velocity +k_inlet_dye #calc "1.5 * Foam::pow(($uDye), 2) * Foam::pow($intensity, 2)"; +eps_inlet_dye #calc "pow(0.09,0.75) * Foam::pow($k_inlet_dye, 1.5) / ($l_scale_dye * 0.07)"; diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.gas b/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType laminar; +//simulationType RAS; +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.liquid b/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties b/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties_constantd b/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( O2 N2 ); + k ( $He_O2 $He_N2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas b/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas @@ -0,0 +1,89 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + O2 + N2 +); + +defaultSpecie N2; + +O2 +{ + specie + { + molWeight 31.9988; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.28253784 0.00148308754 -7.57966669e-07 2.09470555e-10 -2.16717794e-14 -1088.45772 5.45323129 ); + lowCpCoeffs ( 3.78245636 -0.00299673416 9.84730201e-06 -9.68129509e-09 3.24372837e-12 -1063.94356 3.65767573 ); + } + transport + { + As 1.693411300e-06; + Ts 127; + } + elements + { + O 2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid b/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid @@ -0,0 +1,132 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + O2 + N2 + water + Z +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +// Passive dye tracer: identical to water, no interphase mass transfer (Z is +// deliberately absent from every Henry / diffusiveMassTransfer list). +Z +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +O2 +{ + specie + { + molWeight 31.9988; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrO2; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrN2; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py new file mode 100644 index 00000000..2f86cf69 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py @@ -0,0 +1,209 @@ +"""Volume-averaged dye tracer (Z.liquid) in the bottom U-bend box vs time. + +For every time folder this reads the ``Z.liquid`` with BiRD +then computes the cell-volume-weighted average over the +cells whose centres lie inside the box + + x in [-0.01, 0.01], y in [-0.1, 0.1], z in [-0.1, 0.1] [m] + +and plots that average versus time. +""" + +import os + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.utilities.ofio import ( + get_case_times, + read_cell_centers, + read_cell_volumes, + read_field, +) + +CASE = os.path.dirname(os.path.abspath(__file__)) + +# Averaging box [m]. The mesh is y-up after the presteps transformPoints. +X_BOUNDS = (-0.01, 0.01) +Y_BOUNDS = (-0.1, 0.1) +Z_BOUNDS = (-0.1, 0.1) + +# Mixing-time criterion. +BAND = 0.05 # within +/-5% of the final well-mixed value +TAIL_WINDOW = 0.5 # s, tail used to define the final value + + +def read_dye_start(): + """Dye injection start time [s], read from constant/globalVars.""" + with open(os.path.join(CASE, "constant", "globalVars")) as f: + for line in f: + if line.startswith("dyeStart"): + return float(line.split()[1].rstrip(";")) + return 1.0 + + +def box_mask(cell_centers): + """Boolean mask of cells whose centres lie inside the averaging box.""" + x, y, z = cell_centers[:, 0], cell_centers[:, 1], cell_centers[:, 2] + return ( + (x >= X_BOUNDS[0]) + & (x <= X_BOUNDS[1]) + & (y >= Y_BOUNDS[0]) + & (y <= Y_BOUNDS[1]) + & (z >= Z_BOUNDS[0]) + & (z <= Z_BOUNDS[1]) + ) + + +def box_volume_average(z_field, cell_volumes, mask): + """Cell-volume-weighted average of z_field over the masked cells. + + read_field returns a bare float for a uniform OpenFOAM field (e.g. the dye + tracer before injection starts); the volume average is then exactly that + value. Otherwise it is the volume-weighted mean over the box cells. + """ + if np.ndim(z_field) == 0: + return float(z_field) + else: + vol = cell_volumes[mask] + return float(np.sum(z_field[mask] * vol) / np.sum(vol)) + + +def mixing_time(t_arr, z_arr, t_start, continuous=True): + """Mixing time from the box-averaged dye signal. + + The final well-mixed value is the mean of the signal over the last + TAIL_WINDOW seconds. The mixing time is the interval from dye injection + (t_start) to the last instant the signal leaves the +/-BAND envelope of + that final value (after which it stays inside for good). + + Parameters + ---------- + t_arr : array-like + Time array. + z_arr : array-like + Box-averaged dye signal. + t_start : float + Injection time. + continuous : bool, optional + If True, linearly interpolates between the last timestep outside the + band and the first timestep inside to find the exact crossing time. + + Returns + ------- + t_mix : float + Mixing time measured from injection [s]. + t_settle : float + Absolute simulation time at which the signal settles [s]. + z_final : float + Final well-mixed box-averaged value. + """ + # Calculate final value and allowable band + z_final = float(np.mean(z_arr[t_arr >= t_arr[-1] - TAIL_WINDOW])) + band = BAND * abs(z_final) + + post = t_arr >= t_start + outside = post & (np.abs(z_arr - z_final) > band) + + if not np.any(outside): + # already within the band from injection onward + t_settle = t_start + else: + last_out = np.nonzero(outside)[0][-1] + + # Check if we have a subsequent point to interpolate with + if last_out + 1 < len(t_arr): + if continuous: + # Extract time and Z values for the crossing interval + t0, t1 = t_arr[last_out], t_arr[last_out + 1] + z0, z1 = z_arr[last_out], z_arr[last_out + 1] + + # Determine which boundary of the band was crossed + if z0 > z_final: + z_target = z_final + band # Crossed the top boundary + else: + z_target = z_final - band # Crossed the bottom boundary + + # Linearly interpolate to find the exact time t_settle at z_target + if z1 != z0: # Safety check to prevent division by zero + t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) + else: + t_settle = t1 + else: + # Original discrete behavior + t_settle = t_arr[last_out + 1] + else: + # The signal was outside the band up to the very last recorded timestep + t_settle = t_arr[last_out] + + return t_settle - t_start, t_settle, z_final + +if __name__ == "__main__": + os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) + + # Geometry is time-independent: read the cell centres and cell volumes once + # and keep them in the shared field_dict cache. + cell_centers, geom = read_cell_centers(CASE) + n_cells = cell_centers.shape[0] + cell_volumes, geom = read_cell_volumes(CASE, field_dict=geom) + + mask = box_mask(cell_centers) + if mask.sum() == 0: + raise RuntimeError("averaging box contains no cell centres") + + times_float, times_str = get_case_times(CASE) + + t_list, z_list = [], [] + for t_val, t_str in zip(times_float, times_str): + try: + # Fresh field_dict per time so Z.liquid is never served stale. + z_field, _ = read_field(CASE, t_str, "Z.liquid", n_cells=n_cells) + except FileNotFoundError: + continue + t_list.append(t_val) + z_list.append(box_volume_average(z_field, cell_volumes, mask)) + + order = np.argsort(t_list) + t_arr = np.asarray(t_list)[order] + z_arr = np.asarray(z_list)[order] + + np.savetxt( + os.path.join(CASE, "Z_box_average.dat"), + np.column_stack([t_arr, z_arr]), + header="time[s] volAvg(Z.liquid)_box", + ) + + dye_start = read_dye_start() + t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + + with open(os.path.join(CASE, "mix_time.txt"), "w") as f: + f.write(f"Continuous: {t_mix:.4f}\n") + f.write(f"Discrete: {t_mix_disc:.4f}\n") + + fig, ax = plt.subplots(figsize=(6, 4)) + ax.plot(t_arr, z_arr, color="k") + ax.axhline(z_final, color="b", ls="--", label=r"$Z_{final}$") + ax.axhspan( + (1 - BAND) * z_final, (1 + BAND) * z_final, color="b", alpha=0.15 + ) + ax.axvline( + t_settle, color="r", ls=":", label=f"$t_{{mix}}$={t_mix_disc:.2f} s" + ) + ax.set_xlim(left=dye_start) + pretty_labels("time [s]", r"box-averaged $Z_{liquid}$ [-]", 14, ax=ax) + ax.legend() + fig.savefig( + os.path.join(CASE, "Figures", "Z_box_average.png"), + dpi=150, + bbox_inches="tight", + ) + + print(f"box cells : {int(mask.sum())}") + print(f"time folders averaged : {len(t_arr)}") + print(f"final well-mixed Z discrete : {z_final_disc:.6g}") + print(f"final well-mixed Z continous : {z_final:.6g}") + print(f"dye injection start : {dye_start:.3f} s") + print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") + print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") + print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") diff --git a/experimental_cases/uloop_valadbeigy_exp3/presteps.sh b/experimental_cases/uloop_valadbeigy_exp3/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/presteps.sh @@ -0,0 +1,77 @@ +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + + +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +# setup IC +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + +conda deactivate diff --git a/experimental_cases/uloop_valadbeigy_exp3/run.sh b/experimental_cases/uloop_valadbeigy_exp3/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/run.sh @@ -0,0 +1,75 @@ +#!/bin/bash +### OpenFOAM command +./Allclean +set -e # Exit on any error +trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR + +### BiRD command +echo PRESTEP 1 +BIRD_DIR=$(python -c "import bird; print(bird.BIRD_DIR)") +APPLICATIONS=$(dirname "$BIRD_DIR")/applications + +python "$APPLICATIONS/write_stl_patch.py" -i system/inlets_outlets.json +python "$APPLICATIONS/write_dynMix_fvModels.py" -i system/mixers.json -o constant + +echo PRESTEP 2 +python build_uloop_hex.py +bash stitch_and_check.sh \ + --mesh blockC.msh \ + --mesh blockB.msh --mesh blockA.msh \ + --stitch int_B_top:int_C_bot \ + --stitch int_A_legL:int_B_legL \ + --stitch int_A_legR:int_B_legR \ + --case stitched_case_uloop +touch stitched_case_uloop/test.foam +cp -r stitched_case_uloop/constant/polyMesh constant/polyMesh +createPatch -overwrite +transformPoints "rotate=((0 0 1) (0 1 0))" + +# Make a local tmp folder to preprocess the mesh +mkdir tmp + +# --- sparger --- +surfaceToPatch -tol 1e-3 sparger.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/sparger\.stl/sparger/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# --- dye_inlet --- +surfaceToPatch -tol 1e-3 dye_inlet.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/dye_inlet\.stl/dye_inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +foamDictionary constant/polyMesh/boundary -entry entry0/walls/type -set wall +foamDictionary constant/polyMesh/boundary -entry entry0/dye_inlet/type -set wall + +cp -r 0.orig 0 + +DYE_START=$(grep -E '^[[:space:]]*dyeStart[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStart[[:space:]]+([0-9.eE+-]+).*/\1/') +DYE_STOP=$(grep -E '^[[:space:]]*dyeStop[[:space:]]' constant/globalVars_temp | head -1 | sed -E 's/^[[:space:]]*dyeStop[[:space:]]+([0-9.eE+-]+).*/\1/') +echo "Dye injection window: dyeStart=$DYE_START dyeStop=$DYE_STOP" +grep -rl '__DYE_START__\|__DYE_STOP__' 0 | xargs -r sed -i "s/__DYE_START__/${DYE_START}/g; s/__DYE_STOP__/${DYE_STOP}/g" + +setFields + +postProcess -func 'patchIntegrate(patch="sparger", field="alpha.gas")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.liquid")' +postProcess -func 'patchIntegrate(patch="dye_inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + + +birdmultiphaseEulerFoam diff --git a/experimental_cases/uloop_valadbeigy_exp3/script b/experimental_cases/uloop_valadbeigy_exp3/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/script @@ -0,0 +1,16 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=14:59:00 +#SBATCH --account=gas2fuels + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes -fields "(U.liquid alpha.gas Z.liquid)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp3/script_post b/experimental_cases/uloop_valadbeigy_exp3/script_post new file mode 100755 index 00000000..dcbf59d8 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/script_post @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=01:59:00 +#SBATCH --account=gas2fuels +#SBATCH --dependency=afterany:15800966 + +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" +module load conda +conda activate /projects/gas2fuels/conda_env/bird_mixer +python get_mixing_time.py diff --git a/experimental_cases/uloop_valadbeigy_exp3/stitch_and_check.sh b/experimental_cases/uloop_valadbeigy_exp3/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/stitch_and_check.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# +# Stitch a list of gmsh block meshes into ONE OpenFOAM mesh and run checkMesh. +# +# Each mesh is converted with gmshToFoam; mesh #0 becomes the master case that +# the rest are merged into; then each --stitch pair is coupled with integral +# (non -perfect) stitchMesh +# +# Options: +# --mesh (repeatable; order = stack order, #0 is master) +# --stitch (repeatable; integral, for non-matching faces) +# --stitch-perfect (repeatable; -perfect, for conformal faces) +# --case (output case dir, default: stitched_case) + +set -euo pipefail + +CASE="stitched_case" +MESHES=() +STITCHES=() # entries: "integral m:s" or "perfect m:s" (order preserved) +while [[ $# -gt 0 ]]; do + case "$1" in + --mesh) MESHES+=("$2"); shift 2;; + --stitch) STITCHES+=("integral $2"); shift 2;; + --stitch-perfect) STITCHES+=("perfect $2"); shift 2;; + --case) CASE="$2"; shift 2;; + *) echo "unknown argument: $1" >&2; exit 1;; + esac +done + +# >=1 mesh: with a single --mesh and no --stitch this just gmshToFoam+checkMesh +# one block (useful to isolate which block owns a checkMesh failure). +[[ ${#MESHES[@]} -ge 1 ]] || { echo "need at least one --mesh file" >&2; exit 1; } +command -v gmshToFoam >/dev/null 2>&1 || { + echo "OpenFOAM not found on PATH — source OpenFOAM-9 first." >&2; exit 1; } + +# minimal case skeleton (mesh utilities need controlDict/fvSchemes/fvSolution) +write_system() { + local d="$1"; mkdir -p "$d/system" "$d/constant" + cat > "$d/system/controlDict" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object controlDict; } +application checkMesh; +startFrom startTime; startTime 0; +stopAt endTime; endTime 1; +deltaT 1; writeControl timeStep; writeInterval 1; +EOF + cat > "$d/system/fvSchemes" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSchemes; } +ddtSchemes { default steadyState; } +gradSchemes { default Gauss linear; } +divSchemes { default none; } +laplacianSchemes { default Gauss linear corrected; } +interpolationSchemes { default linear; } +snGradSchemes { default corrected; } +EOF + cat > "$d/system/fvSolution" <<'EOF' +FoamFile { version 2.0; format ascii; class dictionary; object fvSolution; } +solvers {} +EOF +} + +echo "==> master case: $CASE (from ${MESHES[0]})" +rm -rf "$CASE"; write_system "$CASE" +gmshToFoam "${MESHES[0]}" -case "$CASE" + +# convert + merge the remaining blocks into the master +for ((i=1; i<${#MESHES[@]}; i++)); do + sub="${CASE}_add${i}" + echo "==> add block $i: ${MESHES[$i]}" + rm -rf "$sub"; write_system "$sub" + gmshToFoam "${MESHES[$i]}" -case "$sub" + # merge into master (OF-9 foundation syntax) + mergeMeshes "$CASE" "$sub" -overwrite + rm -rf "$sub" +done + +# couple each interface with its chosen mode +for spec in "${STITCHES[@]}"; do + mode="${spec%% *}"; pair="${spec#* }" + master="${pair%%:*}"; slave="${pair##*:}" + flags="-overwrite"; [[ "$mode" == perfect ]] && flags="$flags -perfect" + echo "==> stitchMesh ($mode) $master $slave" + stitchMesh $flags "$master" "$slave" -case "$CASE" +done + +echo "==> checkMesh" +checkMesh -allGeometry -allTopology -case "$CASE" +echo "==> done. Mesh in $CASE/constant/polyMesh" diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/controlDict b/experimental_cases/uloop_valadbeigy_exp3/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/controlDict @@ -0,0 +1,95 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt writeNow;//endTime; + +// ~20 s spin-up for steady circulation, dye pulse at t=20-21 s, then ~24 s to +// capture a ~10 s mixing time. +endTime 20; + +deltaT 1e-6; + +writeControl adjustableRunTime; +//writeControl timeStep; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 1.0; + +maxDeltaT 0.001; + + +functions +{ + + limitNut + { + type coded; + libs ("libutilityFunctionObjects.so"); + name limitNut; + codeExecute + #{ + const scalar nutMaxLiq = 1e-3; // [m2/s] liquid nut ceiling (tune) + //const scalar nutMaxGas = 1e-3; // [m2/s] gas nut ceiling (tune) + + volScalarField& nutLiq = + mesh().lookupObjectRef("nut.liquid"); + //volScalarField& nutGas = + // mesh().lookupObjectRef("nut.gas"); + + nutLiq = min(nutLiq, dimensionedScalar(nutLiq.dimensions(), nutMaxLiq)); + //nutGas = min(nutGas, dimensionedScalar(nutGas.dimensions(), nutMaxGas)); + nutLiq.correctBoundaryConditions(); + //nutGas.correctBoundaryConditions(); + + //Info<< "limitNut: max nut.liq=" << max(nutLiq).value() + // << " nut.gas=" << max(nutGas).value() << endl; + Info<< "limitNut: max nut.liq=" << max(nutLiq).value() << endl; + #}; + } + + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) + + // Mixing time is post-processed offline from the written time folders + // (Z.liquid + alpha.liquid), so no sensor/dyeMean function objects here. + // Set writeInterval to the temporal resolution the offline analysis needs. +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/createPatchDict b/experimental_cases/uloop_valadbeigy_exp3/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/createPatchDict @@ -0,0 +1,35 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object createPatchDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Consolidate the per-block wall patches (wall_A/B/C) into a single "walls" patch. +// createPatch also drops the now-empty stitch interface patches (int_*, 0 faces). +// The open tank roof is already its own "outlet" mesh patch (block C physical +// group), so it is NOT merged here and needs no surfaceToPatch. sparger and +// dye_inlet are still carved from "walls" with surfaceToPatch in presteps.sh. + +pointSync false; + +patches +( + { + name walls; + patchInfo { type wall; } + constructFrom patches; + patches (wall_A wall_B wall_C); + } +); + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/decomposeParDict b/experimental_cases/uloop_valadbeigy_exp3/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/fvConstraints b/experimental_cases/uloop_valadbeigy_exp3/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/fvSchemes b/experimental_cases/uloop_valadbeigy_exp3/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/fvSchemes @@ -0,0 +1,76 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + //default Gauss linear; + //limited cellLimited Gauss linear 1; + default cellLimited 1.5 leastSquares 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + //"div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + //"div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,U.*\)" Gauss Minmod; + "div\(phi.*,U.*\)" Gauss Minmod; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon)m\)" Gauss limitedLinear 1; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + //default Gauss linear corrected; + default Gauss linear corrected 0.33; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + //default uncorrected; + default limited corrected 0.33; +} + +wallDist +{ + //method Poisson; + //nRequired true; + method meshWave; +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/fvSolution b/experimental_cases/uloop_valadbeigy_exp3/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/fvSolution @@ -0,0 +1,121 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega|epsilon|omega).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 1e-3; + minIter 0; + maxIter 5; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 1e-3; + minIter 0; + maxIter 0; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 2; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/inlets_outlets.json b/experimental_cases/uloop_valadbeigy_exp3/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/inlets_outlets.json @@ -0,0 +1,24 @@ +{ + "sparger": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.23, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ], + "dye_inlet": [ + { + "type": "circle", + "centx": 0.083, + "centy": 0.65, + "centz": 0.0, + "normal_dir": 0, + "radius": 0.01, + "nelements": 50 + } + ] +} diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/mixers.json b/experimental_cases/uloop_valadbeigy_exp3/system/mixers.json new file mode 100644 index 00000000..41606a06 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/mixers.json @@ -0,0 +1,45 @@ +{ + "mixers": [ + { + "x": 0.063, + "y": 0.47, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "power": 20.8, + "Vtip": 5, + "sign": "-", + "swirl_sign": "-" + } + ], + "static_mixers": [ + { + "x": 0.063, + "y": 0.05, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "-", + "swirl_sign": "-" + }, + { + "x": -0.063, + "y": 0.50, + "z": 0.0, + "normal_dir": 1, + "radius": 0.018, + "start_time": 0.1, + "K": 0.5, + "S": 0.6, + "sign": "+", + "swirl_sign": "+" + } + ], + "volumetric_source": "ball", + "power": "from_P", + "momentum_source": "axial_and_swirl" +} diff --git a/experimental_cases/uloop_valadbeigy_exp3/system/setFieldsDict b/experimental_cases/uloop_valadbeigy_exp3/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/system/setFieldsDict @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Applied AFTER the z->y rotation, so the vertical coordinate is y. +// Liquid fills everything below y = 0.8 m (loop + lower half of the degassing +// tank, whose axis is at y = 0.8); gas headspace above. + +// 0.99/0.01 (not 1/0) for numerical stability. +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 + volScalarFieldValue Z.liquid 0 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (1.0 0.8 1.0); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/experimental_cases/uloop_valadbeigy_exp3/writeGlobalVars.py b/experimental_cases/uloop_valadbeigy_exp3/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/uloop_valadbeigy_exp3/writeGlobalVars.py @@ -0,0 +1,75 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, inletA_dye, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + # match on the first whitespace-delimited token so "inletA" does not + # also capture "inletA_dye" + token = line.split()[0] if line.split() else "" + if token == "inletA": + f.write(f"inletA\t{inletA:g};\n") + elif token == "inletA_dye": + f.write(f"inletA_dye\t{inletA_dye:g};\n") + elif token == "liqVol": + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + # sparger patch area (alpha.gas = 1 there, so the integral is the area); + # used only for the nominal gas velocity in the turbulence inlet BCs. + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=sparger,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def readDyeInletArea(): + # dye_inlet patch area. Unlike the sparger (alpha.gas = 1 there, so a single + # integral gives the area), no field is uniformly 1 at the dye port, so use + # area = integral(alpha.liquid) + integral(alpha.gas): the phase fractions sum + # to 1 pointwise, hence their integrals sum to the exact patch area. + base = os.path.join("postProcessing") + a_liq = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.liquid)", + "0", + "surfaceFieldValue.dat", + ) + ) + a_gas = read_surface_field_value( + os.path.join( + base, + "patchIntegrate(patch=dye_inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + ) + return a_liq + a_gas + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + A_dye = readDyeInletArea() + V = getLiqVol() + writeGvars(A, A_dye, V) diff --git a/pyproject.toml b/pyproject.toml index 28e99d65..ce43724a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -151,3 +151,4 @@ scikit-learn = ">=1.8.0,<2" [tool.pixi.feature.optim.dependencies] optuna = ">=4.7.0,<5" pandas = ">=3.0.1,<4" +scikit-learn = ">=1.8.0,<2" From f9b1f625792cf5b14055c2ff4393e617ffcb8a5e Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 16:02:42 -0600 Subject: [PATCH 31/52] format --- .../uloop_valadbeigy_exp1/build_uloop_hex.py | 310 ++++++++++++------ .../uloop_valadbeigy_exp1/get_mixing_time.py | 19 +- .../uloop_valadbeigy_exp2/build_uloop_hex.py | 310 ++++++++++++------ .../uloop_valadbeigy_exp2/get_mixing_time.py | 19 +- .../uloop_valadbeigy_exp3/build_uloop_hex.py | 310 ++++++++++++------ .../uloop_valadbeigy_exp3/get_mixing_time.py | 19 +- 6 files changed, 666 insertions(+), 321 deletions(-) diff --git a/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py index bef692ab..43cb6cba 100644 --- a/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py +++ b/experimental_cases/uloop_valadbeigy_exp1/build_uloop_hex.py @@ -1,14 +1,14 @@ """ Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 -Open-top U-loop reactor as 3 stitchable gmsh blocks +Open-top U-loop reactor as 3 stitchable gmsh blocks Structured hex mesh everywhere except the U-loop<->tank junction Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): - A hex : the U pipe + A hex : the U pipe B tet : U-loop <-> tank junction - Two down-stubs (filleted where they meet the tank floor) + Two down-stubs (filleted where they meet the tank floor) C hex : structured-hex tank, extruded up to the open top (Z_TOP). Flat top face is the `outlet` boundary; sides = wall. @@ -16,23 +16,26 @@ """ import math + import gmsh import numpy as np # Geometrical parameters -R = 0.020 # DN40 pipe [m] -R_BEND = 0.045 # elbow centerline bend radius [m] -X_LEG = 0.063 # leg half spacing [m] -Z_HORIZ = 0.000 # bottom height [m] -Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] -R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = ( + 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +) +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] TANK_LEN = 2 * R_TANK -Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] -FILLET_R = 0.01 # junction fillet radius [m] +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] def loop_pipe_length(include_tank=False): - ''' Compute pipe length which is reported in the paper''' + """Compute pipe length which is reported in the paper""" r_bend = R_BEND z_bend_top = Z_HORIZ + r_bend leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) @@ -47,50 +50,62 @@ def reactor_volume(tank_fraction=1.0): v_tank = math.pi * R_TANK**2 * TANK_LEN return v_pipe + tank_fraction * v_tank -# --- derived helper dimensions (I need that later) -Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows -Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 -Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 -HX = TANK_LEN / 2.0 # tank box half-width along x -HY = R_TANK # tank box half-width along y (cross-section) -STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] -B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] -Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] -Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = ( + 0.03 # how far do we extend the filletted junction into the hex tank [m] +) +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] # --- resolution RI_FRAC = 0.5 -N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_SIDE = 6 # even -> circle/Pillow rims share nodes N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) -H_AX = 0.004 # target axial cell size for the pipe sweeps -N_TANK = 30 # structured cells per tank-square edge +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge # FINER mesh at the junction is obtained with SMALLER JUNCTION_RES JUNCTION_RES = 1.8 -# ---- iterative mesh cleanup +# ---- iterative mesh cleanup N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) -N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells def _pillow(geo, cx, cy, cz, r, n_side, n_rad): - '''Pillow shape cylindrical mesh cross-section - Normal direction is z (consistently with the block cylindrical meshing)''' + """Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)""" ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] ri = RI_FRAC * r c = geo.addPoint(cx, cy, cz) - Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] - A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Q = [ + geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) + for a in ang + ] + A = [ + geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) + for a in ang + ] Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] for i in range(4): - surfs.append(geo.addSurfaceFilling( - [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + surfs.append( + geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])] + ) + ) for e in Qe + Arc: geo.mesh.setTransfiniteCurve(e, n_side + 1) for e in Rad: @@ -102,39 +117,43 @@ def _pillow(geo, cx, cy, cz, r, n_side, n_rad): def _isflat(s, idx, val, tol=1e-6): - ''' + """ True if surface *s* lies entirely on the plane coord[idx] == val. I.e. is a constant coordinate plane useful to check if what we extruded gives us a flat surface - ''' + """ bb = gmsh.model.getBoundingBox(2, s) return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol def _tip(idx, val): - ''' + """ Find flat boundary surface after gmesh extrusion - ''' + """ vols = [t for _, t in gmsh.model.getEntities(3)] - bnd = {t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)} + bnd = { + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + } return [(2, s) for s in bnd if _isflat(s, idx, val)] def _by(surfs, idx, val): - '''Filter surface to those lying on the plane coord[idx] == val.''' + """Filter surface to those lying on the plane coord[idx] == val.""" return [s for s in surfs if _isflat(s, idx, val)] def _cx(s): - '''Bounding box used to distinguish the left and right leg''' + """Bounding box used to distinguish the left and right leg""" bb = gmsh.model.getBoundingBox(2, s) return 0.5 * (bb[0] + bb[3]) def _rims(surfs): - ''' find the rims at the junction between the legs and the filleted tets - and for the junction between tet block and hex tank block''' + """find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block""" rim = set() for s in surfs: for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): @@ -145,8 +164,12 @@ def _rims(surfs): def _boundary_surfs(): """Returns volume IDs and their boundary surface IDs.""" vols = [t for _, t in gmsh.model.getEntities(3)] - return vols, [t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)] + return vols, [ + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + ] def _cell_volume(): @@ -157,8 +180,14 @@ def _cell_volume(): npe = {4: 4, 5: 8, 6: 6, 7: 5} fans = { 4: [(0, 1, 2, 3)], - 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), - (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 5: [ + (0, 1, 2, 6), + (0, 2, 3, 6), + (0, 3, 7, 6), + (0, 7, 4, 6), + (0, 4, 5, 6), + (0, 5, 1, 6), + ], 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], 7: [(0, 1, 2, 4), (0, 2, 3, 4)], } @@ -169,13 +198,16 @@ def _cell_volume(): P = coords[conn] for a, b, c, d in fans[et]: v = P[:, a], P[:, b], P[:, c], P[:, d] - total += np.abs(np.einsum( - "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + total += np.abs( + np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0] + ) + ).sum() return total / 6.0 def _write(path, tag): - ''' Write Gmesh object to .msh and print summary''' + """Write Gmesh object to .msh and print summary""" TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} ets, etags, _ = gmsh.model.mesh.getElements(3) counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} @@ -203,28 +235,66 @@ def build_block_A(path): geo = gmsh.model.geo disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) - geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), - numElements=[N_LEG], recombine=True) + geo.extrude( + [(2, s) for s in disk], + 0, + 0, + -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() # left elbow: revolve the leg-bottom disk about y through the bend centre - geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(2, Z_BEND_TOP), + -X_LEG + R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # bottom horizontal run: extrude +x - geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, - numElements=[N_HOR], recombine=True) + geo.extrude( + _tip(0, -X_LEG + R_BEND), + 2 * (X_LEG - R_BEND), + 0, + 0, + numElements=[N_HOR], + recombine=True, + ) geo.synchronize() # right elbow - geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(0, X_LEG - R_BEND), + X_LEG - R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # right leg: extrude +z up to Z_AB - geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, - numElements=[N_LEG], recombine=True) + geo.extrude( + _tip(2, Z_BEND_TOP), + 0, + 0, + Z_AB - Z_BEND_TOP, + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() vols, bnd = _boundary_surfs() @@ -243,17 +313,17 @@ def build_block_A(path): return vol -# ---- block B: U-loop <-> tank junction +# ---- block B: U-loop <-> tank junction def build_block_B(path): - '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + """Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). - 2. Two cylindrical partial leds + 2. Two cylindrical partial leds 3. Fillet - + Interface matching (that was the hard part!) - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. - - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. - ''' + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + """ gmsh.initialize() gmsh.model.add("B") @@ -262,8 +332,10 @@ def build_block_B(path): pen = 0.4 * (Z_BC - Z_BOT) slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) - stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) - for sx in (-X_LEG, X_LEG)] + stubs = [ + occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG) + ] S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) occ.synchronize() vol = S[0][1] @@ -272,25 +344,28 @@ def build_block_B(path): for _, e in gmsh.model.getEntities(1): ex, _ey, ez = occ.getCenterOfMass(1, e) x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) - if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ - and (x1 - x0) < 3 * R: + if ( + abs(ez - Z_BOT) < 1e-3 + and abs(abs(ex) - X_LEG) < 0.02 + and (x1 - x0) < 3 * R + ): ring.append(e) occ.fillet([vol], ring, [FILLET_R]) occ.synchronize() vols, bnd = _boundary_surfs() - bot = _by(bnd, 2, Z_AB) # two pipe circles -> A - top = _by(bnd, 2, Z_BC) # tank square -> C + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C walls = [s for s in bnd if s not in bot and s not in top] legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] - for s in bot: # match each stub rim to A (4*N_SIDE) + for s in bot: # match each stub rim to A (4*N_SIDE) rc = _rims([s]) per = max(1, round(4 * N_SIDE / len(rc))) for cc in rc: gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) - for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) gmsh.model.addPhysicalGroup(3, vols, name="juncB") @@ -308,15 +383,15 @@ def build_block_B(path): return vol -# --- block C: hex tank +# --- block C: hex tank def build_block_C(path): """Structured-hex tank extruded from Z_BC to Z_TOP. 1) N_TANK nodes per edge, matching block B's top 2) Extrude +z to Z_TOP with N_HC uniform layers. - - Top face is the open outlet boundary; - Sides are wall_C; + + Top face is the open outlet boundary; + Sides are wall_C; Bottom is for stitching to block B. """ gmsh.initialize() @@ -324,20 +399,26 @@ def build_block_C(path): gmsh.option.setNumber("General.Terminal", 0) geo = gmsh.model.geo - p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), - geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + p = [ + geo.addPoint(-HX, -HY, Z_BC), + geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), + geo.addPoint(-HX, HY, Z_BC), + ] l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) for e in l: geo.mesh.setTransfiniteCurve(e, N_TANK + 1) geo.mesh.setTransfiniteSurface(sq) geo.mesh.setRecombine(2, sq) - geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.extrude( + [(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True + ) geo.synchronize() vols, bnd = _boundary_surfs() bot = _by(bnd, 2, Z_BC) - top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) walls = [s for s in bnd if s not in bot and s not in top] gmsh.model.addPhysicalGroup(3, vols, name="tank") gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") @@ -350,7 +431,7 @@ def build_block_C(path): # ---- verify that the junction that stitch mesh will operate on has consistent -# face perimeter +# face perimeter def _plane_nodes(path, zval): """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" gmsh.initialize() @@ -364,23 +445,34 @@ def _plane_nodes(path, zval): def _circle_rim(pts, cx, r): """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(math.hypot(x - cx, y) - r) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4 + ) def _square_rim(pts, hx, hy): """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4 + ) def _verify(name, a, b, tol=1e-9): """Assert two rim point sets have the same count and are coincident within tol.""" - assert len(a) == len(b), \ - f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." - worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + assert len(a) == len( + b + ), f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max( + min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a + ) ok = worst < tol - print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + print( + f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}" + ) assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." @@ -388,8 +480,12 @@ def verify_interfaces(): """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" A_ab = _plane_nodes("blockA.msh", Z_AB) B_ab = _plane_nodes("blockB.msh", Z_AB) - _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) - _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + _verify( + "A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R) + ) + _verify( + "A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R) + ) B_bc = _plane_nodes("blockB.msh", Z_BC) C_bc = _plane_nodes("blockC.msh", Z_BC) _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) @@ -397,8 +493,10 @@ def verify_interfaces(): # ---- main if __name__ == "__main__": - print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " - f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + print( + f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}" + ) vols = { "A": build_block_A("blockA.msh"), "B": build_block_B("blockB.msh"), @@ -408,11 +506,19 @@ def verify_interfaces(): box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) print("=" * 70) - print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " - f"excl. tank = {loop_pipe_length(False):.4f} m") - print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " - f"= {sum(vols.values()) * 1e3:.3f} L") - print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") - print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " - f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print( + f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m" + ) + print( + f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L" + ) + print( + f" of which the box tank alone = {box_tank * 1e3:.3f} L" + ) + print( + f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)" + ) print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py index 2f86cf69..ffe78675 100644 --- a/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py +++ b/experimental_cases/uloop_valadbeigy_exp1/get_mixing_time.py @@ -125,7 +125,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): z_target = z_final - band # Crossed the bottom boundary # Linearly interpolate to find the exact time t_settle at z_target - if z1 != z0: # Safety check to prevent division by zero + if z1 != z0: # Safety check to prevent division by zero t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) else: t_settle = t1 @@ -138,6 +138,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): return t_settle - t_start, t_settle, z_final + if __name__ == "__main__": os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) @@ -175,7 +176,9 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): dye_start = read_dye_start() t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) - t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time( + t_arr, z_arr, dye_start, continuous=False + ) with open(os.path.join(CASE, "mix_time.txt"), "w") as f: f.write(f"Continuous: {t_mix:.4f}\n") @@ -204,6 +207,12 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): print(f"final well-mixed Z discrete : {z_final_disc:.6g}") print(f"final well-mixed Z continous : {z_final:.6g}") print(f"dye injection start : {dye_start:.3f} s") - print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") - print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") - print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") + print( + f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)" + ) + print( + f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)" + ) + print( + "wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png" + ) diff --git a/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py index bef692ab..43cb6cba 100644 --- a/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py +++ b/experimental_cases/uloop_valadbeigy_exp2/build_uloop_hex.py @@ -1,14 +1,14 @@ """ Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 -Open-top U-loop reactor as 3 stitchable gmsh blocks +Open-top U-loop reactor as 3 stitchable gmsh blocks Structured hex mesh everywhere except the U-loop<->tank junction Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): - A hex : the U pipe + A hex : the U pipe B tet : U-loop <-> tank junction - Two down-stubs (filleted where they meet the tank floor) + Two down-stubs (filleted where they meet the tank floor) C hex : structured-hex tank, extruded up to the open top (Z_TOP). Flat top face is the `outlet` boundary; sides = wall. @@ -16,23 +16,26 @@ """ import math + import gmsh import numpy as np # Geometrical parameters -R = 0.020 # DN40 pipe [m] -R_BEND = 0.045 # elbow centerline bend radius [m] -X_LEG = 0.063 # leg half spacing [m] -Z_HORIZ = 0.000 # bottom height [m] -Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] -R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = ( + 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +) +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] TANK_LEN = 2 * R_TANK -Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] -FILLET_R = 0.01 # junction fillet radius [m] +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] def loop_pipe_length(include_tank=False): - ''' Compute pipe length which is reported in the paper''' + """Compute pipe length which is reported in the paper""" r_bend = R_BEND z_bend_top = Z_HORIZ + r_bend leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) @@ -47,50 +50,62 @@ def reactor_volume(tank_fraction=1.0): v_tank = math.pi * R_TANK**2 * TANK_LEN return v_pipe + tank_fraction * v_tank -# --- derived helper dimensions (I need that later) -Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows -Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 -Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 -HX = TANK_LEN / 2.0 # tank box half-width along x -HY = R_TANK # tank box half-width along y (cross-section) -STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] -B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] -Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] -Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = ( + 0.03 # how far do we extend the filletted junction into the hex tank [m] +) +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] # --- resolution RI_FRAC = 0.5 -N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_SIDE = 6 # even -> circle/Pillow rims share nodes N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) -H_AX = 0.004 # target axial cell size for the pipe sweeps -N_TANK = 30 # structured cells per tank-square edge +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge # FINER mesh at the junction is obtained with SMALLER JUNCTION_RES JUNCTION_RES = 1.8 -# ---- iterative mesh cleanup +# ---- iterative mesh cleanup N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) -N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells def _pillow(geo, cx, cy, cz, r, n_side, n_rad): - '''Pillow shape cylindrical mesh cross-section - Normal direction is z (consistently with the block cylindrical meshing)''' + """Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)""" ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] ri = RI_FRAC * r c = geo.addPoint(cx, cy, cz) - Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] - A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Q = [ + geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) + for a in ang + ] + A = [ + geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) + for a in ang + ] Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] for i in range(4): - surfs.append(geo.addSurfaceFilling( - [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + surfs.append( + geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])] + ) + ) for e in Qe + Arc: geo.mesh.setTransfiniteCurve(e, n_side + 1) for e in Rad: @@ -102,39 +117,43 @@ def _pillow(geo, cx, cy, cz, r, n_side, n_rad): def _isflat(s, idx, val, tol=1e-6): - ''' + """ True if surface *s* lies entirely on the plane coord[idx] == val. I.e. is a constant coordinate plane useful to check if what we extruded gives us a flat surface - ''' + """ bb = gmsh.model.getBoundingBox(2, s) return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol def _tip(idx, val): - ''' + """ Find flat boundary surface after gmesh extrusion - ''' + """ vols = [t for _, t in gmsh.model.getEntities(3)] - bnd = {t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)} + bnd = { + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + } return [(2, s) for s in bnd if _isflat(s, idx, val)] def _by(surfs, idx, val): - '''Filter surface to those lying on the plane coord[idx] == val.''' + """Filter surface to those lying on the plane coord[idx] == val.""" return [s for s in surfs if _isflat(s, idx, val)] def _cx(s): - '''Bounding box used to distinguish the left and right leg''' + """Bounding box used to distinguish the left and right leg""" bb = gmsh.model.getBoundingBox(2, s) return 0.5 * (bb[0] + bb[3]) def _rims(surfs): - ''' find the rims at the junction between the legs and the filleted tets - and for the junction between tet block and hex tank block''' + """find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block""" rim = set() for s in surfs: for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): @@ -145,8 +164,12 @@ def _rims(surfs): def _boundary_surfs(): """Returns volume IDs and their boundary surface IDs.""" vols = [t for _, t in gmsh.model.getEntities(3)] - return vols, [t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)] + return vols, [ + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + ] def _cell_volume(): @@ -157,8 +180,14 @@ def _cell_volume(): npe = {4: 4, 5: 8, 6: 6, 7: 5} fans = { 4: [(0, 1, 2, 3)], - 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), - (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 5: [ + (0, 1, 2, 6), + (0, 2, 3, 6), + (0, 3, 7, 6), + (0, 7, 4, 6), + (0, 4, 5, 6), + (0, 5, 1, 6), + ], 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], 7: [(0, 1, 2, 4), (0, 2, 3, 4)], } @@ -169,13 +198,16 @@ def _cell_volume(): P = coords[conn] for a, b, c, d in fans[et]: v = P[:, a], P[:, b], P[:, c], P[:, d] - total += np.abs(np.einsum( - "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + total += np.abs( + np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0] + ) + ).sum() return total / 6.0 def _write(path, tag): - ''' Write Gmesh object to .msh and print summary''' + """Write Gmesh object to .msh and print summary""" TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} ets, etags, _ = gmsh.model.mesh.getElements(3) counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} @@ -203,28 +235,66 @@ def build_block_A(path): geo = gmsh.model.geo disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) - geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), - numElements=[N_LEG], recombine=True) + geo.extrude( + [(2, s) for s in disk], + 0, + 0, + -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() # left elbow: revolve the leg-bottom disk about y through the bend centre - geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(2, Z_BEND_TOP), + -X_LEG + R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # bottom horizontal run: extrude +x - geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, - numElements=[N_HOR], recombine=True) + geo.extrude( + _tip(0, -X_LEG + R_BEND), + 2 * (X_LEG - R_BEND), + 0, + 0, + numElements=[N_HOR], + recombine=True, + ) geo.synchronize() # right elbow - geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(0, X_LEG - R_BEND), + X_LEG - R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # right leg: extrude +z up to Z_AB - geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, - numElements=[N_LEG], recombine=True) + geo.extrude( + _tip(2, Z_BEND_TOP), + 0, + 0, + Z_AB - Z_BEND_TOP, + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() vols, bnd = _boundary_surfs() @@ -243,17 +313,17 @@ def build_block_A(path): return vol -# ---- block B: U-loop <-> tank junction +# ---- block B: U-loop <-> tank junction def build_block_B(path): - '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + """Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). - 2. Two cylindrical partial leds + 2. Two cylindrical partial leds 3. Fillet - + Interface matching (that was the hard part!) - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. - - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. - ''' + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + """ gmsh.initialize() gmsh.model.add("B") @@ -262,8 +332,10 @@ def build_block_B(path): pen = 0.4 * (Z_BC - Z_BOT) slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) - stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) - for sx in (-X_LEG, X_LEG)] + stubs = [ + occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG) + ] S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) occ.synchronize() vol = S[0][1] @@ -272,25 +344,28 @@ def build_block_B(path): for _, e in gmsh.model.getEntities(1): ex, _ey, ez = occ.getCenterOfMass(1, e) x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) - if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ - and (x1 - x0) < 3 * R: + if ( + abs(ez - Z_BOT) < 1e-3 + and abs(abs(ex) - X_LEG) < 0.02 + and (x1 - x0) < 3 * R + ): ring.append(e) occ.fillet([vol], ring, [FILLET_R]) occ.synchronize() vols, bnd = _boundary_surfs() - bot = _by(bnd, 2, Z_AB) # two pipe circles -> A - top = _by(bnd, 2, Z_BC) # tank square -> C + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C walls = [s for s in bnd if s not in bot and s not in top] legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] - for s in bot: # match each stub rim to A (4*N_SIDE) + for s in bot: # match each stub rim to A (4*N_SIDE) rc = _rims([s]) per = max(1, round(4 * N_SIDE / len(rc))) for cc in rc: gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) - for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) gmsh.model.addPhysicalGroup(3, vols, name="juncB") @@ -308,15 +383,15 @@ def build_block_B(path): return vol -# --- block C: hex tank +# --- block C: hex tank def build_block_C(path): """Structured-hex tank extruded from Z_BC to Z_TOP. 1) N_TANK nodes per edge, matching block B's top 2) Extrude +z to Z_TOP with N_HC uniform layers. - - Top face is the open outlet boundary; - Sides are wall_C; + + Top face is the open outlet boundary; + Sides are wall_C; Bottom is for stitching to block B. """ gmsh.initialize() @@ -324,20 +399,26 @@ def build_block_C(path): gmsh.option.setNumber("General.Terminal", 0) geo = gmsh.model.geo - p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), - geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + p = [ + geo.addPoint(-HX, -HY, Z_BC), + geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), + geo.addPoint(-HX, HY, Z_BC), + ] l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) for e in l: geo.mesh.setTransfiniteCurve(e, N_TANK + 1) geo.mesh.setTransfiniteSurface(sq) geo.mesh.setRecombine(2, sq) - geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.extrude( + [(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True + ) geo.synchronize() vols, bnd = _boundary_surfs() bot = _by(bnd, 2, Z_BC) - top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) walls = [s for s in bnd if s not in bot and s not in top] gmsh.model.addPhysicalGroup(3, vols, name="tank") gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") @@ -350,7 +431,7 @@ def build_block_C(path): # ---- verify that the junction that stitch mesh will operate on has consistent -# face perimeter +# face perimeter def _plane_nodes(path, zval): """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" gmsh.initialize() @@ -364,23 +445,34 @@ def _plane_nodes(path, zval): def _circle_rim(pts, cx, r): """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(math.hypot(x - cx, y) - r) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4 + ) def _square_rim(pts, hx, hy): """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4 + ) def _verify(name, a, b, tol=1e-9): """Assert two rim point sets have the same count and are coincident within tol.""" - assert len(a) == len(b), \ - f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." - worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + assert len(a) == len( + b + ), f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max( + min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a + ) ok = worst < tol - print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + print( + f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}" + ) assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." @@ -388,8 +480,12 @@ def verify_interfaces(): """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" A_ab = _plane_nodes("blockA.msh", Z_AB) B_ab = _plane_nodes("blockB.msh", Z_AB) - _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) - _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + _verify( + "A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R) + ) + _verify( + "A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R) + ) B_bc = _plane_nodes("blockB.msh", Z_BC) C_bc = _plane_nodes("blockC.msh", Z_BC) _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) @@ -397,8 +493,10 @@ def verify_interfaces(): # ---- main if __name__ == "__main__": - print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " - f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + print( + f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}" + ) vols = { "A": build_block_A("blockA.msh"), "B": build_block_B("blockB.msh"), @@ -408,11 +506,19 @@ def verify_interfaces(): box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) print("=" * 70) - print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " - f"excl. tank = {loop_pipe_length(False):.4f} m") - print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " - f"= {sum(vols.values()) * 1e3:.3f} L") - print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") - print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " - f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print( + f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m" + ) + print( + f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L" + ) + print( + f" of which the box tank alone = {box_tank * 1e3:.3f} L" + ) + print( + f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)" + ) print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py index 2f86cf69..ffe78675 100644 --- a/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py +++ b/experimental_cases/uloop_valadbeigy_exp2/get_mixing_time.py @@ -125,7 +125,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): z_target = z_final - band # Crossed the bottom boundary # Linearly interpolate to find the exact time t_settle at z_target - if z1 != z0: # Safety check to prevent division by zero + if z1 != z0: # Safety check to prevent division by zero t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) else: t_settle = t1 @@ -138,6 +138,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): return t_settle - t_start, t_settle, z_final + if __name__ == "__main__": os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) @@ -175,7 +176,9 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): dye_start = read_dye_start() t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) - t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time( + t_arr, z_arr, dye_start, continuous=False + ) with open(os.path.join(CASE, "mix_time.txt"), "w") as f: f.write(f"Continuous: {t_mix:.4f}\n") @@ -204,6 +207,12 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): print(f"final well-mixed Z discrete : {z_final_disc:.6g}") print(f"final well-mixed Z continous : {z_final:.6g}") print(f"dye injection start : {dye_start:.3f} s") - print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") - print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") - print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") + print( + f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)" + ) + print( + f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)" + ) + print( + "wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png" + ) diff --git a/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py b/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py index bef692ab..43cb6cba 100644 --- a/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py +++ b/experimental_cases/uloop_valadbeigy_exp3/build_uloop_hex.py @@ -1,14 +1,14 @@ """ Reproduce the case in "Hydrodynamic optimization of a newly designed and fabricated U-Loop bioreactor using Taguchi–ANOVA analysis", Valadbeigy et al., Biochemical Engineering Journal, July 2026 -Open-top U-loop reactor as 3 stitchable gmsh blocks +Open-top U-loop reactor as 3 stitchable gmsh blocks Structured hex mesh everywhere except the U-loop<->tank junction Blocks (all interfaces are perimeter-matched -> OpenFOAM integral `stitchMesh`): - A hex : the U pipe + A hex : the U pipe B tet : U-loop <-> tank junction - Two down-stubs (filleted where they meet the tank floor) + Two down-stubs (filleted where they meet the tank floor) C hex : structured-hex tank, extruded up to the open top (Z_TOP). Flat top face is the `outlet` boundary; sides = wall. @@ -16,23 +16,26 @@ """ import math + import gmsh import numpy as np # Geometrical parameters -R = 0.020 # DN40 pipe [m] -R_BEND = 0.045 # elbow centerline bend radius [m] -X_LEG = 0.063 # leg half spacing [m] -Z_HORIZ = 0.000 # bottom height [m] -Z_TANK = 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] -R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] +R = 0.020 # DN40 pipe [m] +R_BEND = 0.045 # elbow centerline bend radius [m] +X_LEG = 0.063 # leg half spacing [m] +Z_HORIZ = 0.000 # bottom height [m] +Z_TANK = ( + 0.8 # tank axis height (sets the tank floor Z_BOT = Z_TANK-R_TANK) [m] +) +R_TANK = 0.100 # degassing-tank radius (sets the box cross-section) [m] TANK_LEN = 2 * R_TANK -Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] -FILLET_R = 0.01 # junction fillet radius [m] +Z_OUTLET = 1.3 # open-top outlet height (tank roof) [m] +FILLET_R = 0.01 # junction fillet radius [m] def loop_pipe_length(include_tank=False): - ''' Compute pipe length which is reported in the paper''' + """Compute pipe length which is reported in the paper""" r_bend = R_BEND z_bend_top = Z_HORIZ + r_bend leg_top = Z_TANK if include_tank else (Z_TANK - R_TANK) @@ -47,50 +50,62 @@ def reactor_volume(tank_fraction=1.0): v_tank = math.pi * R_TANK**2 * TANK_LEN return v_pipe + tank_fraction * v_tank -# --- derived helper dimensions (I need that later) -Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows -Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 -Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 -HX = TANK_LEN / 2.0 # tank box half-width along x -HY = R_TANK # tank box half-width along y (cross-section) -STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] -B_SLAB = 0.03 # how far do we extend the filletted junction into the hex tank [m] -Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] -Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] +# --- derived helper dimensions (I need that later) +Z_BEND_TOP = Z_HORIZ + R_BEND # where the bottom legs meet the elbows +Z_BOT = Z_TANK - R_TANK # tank floor (box bottom) = 0.7 +Z_TOP = Z_OUTLET # tank roof / open outlet = 1.3 +HX = TANK_LEN / 2.0 # tank box half-width along x +HY = R_TANK # tank box half-width along y (cross-section) + +STUB = 0.03 # how far do we stop before the legs at the filletted junction [m] +B_SLAB = ( + 0.03 # how far do we extend the filletted junction into the hex tank [m] +) +Z_AB = Z_BOT - STUB # A<->B interface (leg tops) [m] +Z_BC = Z_BOT + B_SLAB # B<->C interface (tank square) [m] # --- resolution RI_FRAC = 0.5 -N_SIDE = 6 # even -> circle/Pillow rims share nodes +N_SIDE = 6 # even -> circle/Pillow rims share nodes N_RAD = max(1, round(N_SIDE * (1 - RI_FRAC) / (RI_FRAC * math.sqrt(2)))) -H_AX = 0.004 # target axial cell size for the pipe sweeps -N_TANK = 30 # structured cells per tank-square edge +H_AX = 0.004 # target axial cell size for the pipe sweeps +N_TANK = 30 # structured cells per tank-square edge # FINER mesh at the junction is obtained with SMALLER JUNCTION_RES JUNCTION_RES = 1.8 -# ---- iterative mesh cleanup +# ---- iterative mesh cleanup N_LEG = max(1, round((Z_AB - Z_BEND_TOP) / H_AX)) N_ARC = max(1, round((R_BEND * math.pi / 2) / H_AX)) N_HOR = max(1, round(2 * (X_LEG - R_BEND) / H_AX)) -N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells +N_HC = max(1, round((Z_TOP - Z_BC) / (2 * HX / N_TANK))) # uniform tank cells def _pillow(geo, cx, cy, cz, r, n_side, n_rad): - '''Pillow shape cylindrical mesh cross-section - Normal direction is z (consistently with the block cylindrical meshing)''' + """Pillow shape cylindrical mesh cross-section + Normal direction is z (consistently with the block cylindrical meshing)""" ang = [math.pi / 4 + k * math.pi / 2 for k in range(4)] ri = RI_FRAC * r c = geo.addPoint(cx, cy, cz) - Q = [geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) for a in ang] - A = [geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) for a in ang] + Q = [ + geo.addPoint(cx + ri * math.cos(a), cy + ri * math.sin(a), cz) + for a in ang + ] + A = [ + geo.addPoint(cx + r * math.cos(a), cy + r * math.sin(a), cz) + for a in ang + ] Qe = [geo.addLine(Q[i], Q[(i + 1) % 4]) for i in range(4)] Rad = [geo.addLine(Q[i], A[i]) for i in range(4)] Arc = [geo.addCircleArc(A[i], c, A[(i + 1) % 4]) for i in range(4)] surfs = [geo.addPlaneSurface([geo.addCurveLoop(Qe)])] for i in range(4): - surfs.append(geo.addSurfaceFilling( - [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])])) + surfs.append( + geo.addSurfaceFilling( + [geo.addCurveLoop([Rad[i], Arc[i], -Rad[(i + 1) % 4], -Qe[i]])] + ) + ) for e in Qe + Arc: geo.mesh.setTransfiniteCurve(e, n_side + 1) for e in Rad: @@ -102,39 +117,43 @@ def _pillow(geo, cx, cy, cz, r, n_side, n_rad): def _isflat(s, idx, val, tol=1e-6): - ''' + """ True if surface *s* lies entirely on the plane coord[idx] == val. I.e. is a constant coordinate plane useful to check if what we extruded gives us a flat surface - ''' + """ bb = gmsh.model.getBoundingBox(2, s) return abs(bb[idx] - val) < tol and abs(bb[idx + 3] - val) < tol def _tip(idx, val): - ''' + """ Find flat boundary surface after gmesh extrusion - ''' + """ vols = [t for _, t in gmsh.model.getEntities(3)] - bnd = {t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)} + bnd = { + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + } return [(2, s) for s in bnd if _isflat(s, idx, val)] def _by(surfs, idx, val): - '''Filter surface to those lying on the plane coord[idx] == val.''' + """Filter surface to those lying on the plane coord[idx] == val.""" return [s for s in surfs if _isflat(s, idx, val)] def _cx(s): - '''Bounding box used to distinguish the left and right leg''' + """Bounding box used to distinguish the left and right leg""" bb = gmsh.model.getBoundingBox(2, s) return 0.5 * (bb[0] + bb[3]) def _rims(surfs): - ''' find the rims at the junction between the legs and the filleted tets - and for the junction between tet block and hex tank block''' + """find the rims at the junction between the legs and the filleted tets + and for the junction between tet block and hex tank block""" rim = set() for s in surfs: for _, cc in gmsh.model.getBoundary([(2, s)], oriented=False): @@ -145,8 +164,12 @@ def _rims(surfs): def _boundary_surfs(): """Returns volume IDs and their boundary surface IDs.""" vols = [t for _, t in gmsh.model.getEntities(3)] - return vols, [t for _, t in gmsh.model.getBoundary( - [(3, v) for v in vols], combined=True, oriented=False)] + return vols, [ + t + for _, t in gmsh.model.getBoundary( + [(3, v) for v in vols], combined=True, oriented=False + ) + ] def _cell_volume(): @@ -157,8 +180,14 @@ def _cell_volume(): npe = {4: 4, 5: 8, 6: 6, 7: 5} fans = { 4: [(0, 1, 2, 3)], - 5: [(0, 1, 2, 6), (0, 2, 3, 6), (0, 3, 7, 6), - (0, 7, 4, 6), (0, 4, 5, 6), (0, 5, 1, 6)], + 5: [ + (0, 1, 2, 6), + (0, 2, 3, 6), + (0, 3, 7, 6), + (0, 7, 4, 6), + (0, 4, 5, 6), + (0, 5, 1, 6), + ], 6: [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)], 7: [(0, 1, 2, 4), (0, 2, 3, 4)], } @@ -169,13 +198,16 @@ def _cell_volume(): P = coords[conn] for a, b, c, d in fans[et]: v = P[:, a], P[:, b], P[:, c], P[:, d] - total += np.abs(np.einsum( - "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0])).sum() + total += np.abs( + np.einsum( + "ij,ij->i", np.cross(v[1] - v[0], v[2] - v[0]), v[3] - v[0] + ) + ).sum() return total / 6.0 def _write(path, tag): - ''' Write Gmesh object to .msh and print summary''' + """Write Gmesh object to .msh and print summary""" TYPE = {4: "tet", 5: "hex", 6: "prism", 7: "pyramid"} ets, etags, _ = gmsh.model.mesh.getElements(3) counts = {TYPE.get(e, e): len(t) for e, t in zip(ets, etags)} @@ -203,28 +235,66 @@ def build_block_A(path): geo = gmsh.model.geo disk = _pillow(geo, -X_LEG, 0, Z_AB, R, N_SIDE, N_RAD) - geo.extrude([(2, s) for s in disk], 0, 0, -(Z_AB - Z_BEND_TOP), - numElements=[N_LEG], recombine=True) + geo.extrude( + [(2, s) for s in disk], + 0, + 0, + -(Z_AB - Z_BEND_TOP), + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() # left elbow: revolve the leg-bottom disk about y through the bend centre - geo.revolve(_tip(2, Z_BEND_TOP), -X_LEG + R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(2, Z_BEND_TOP), + -X_LEG + R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # bottom horizontal run: extrude +x - geo.extrude(_tip(0, -X_LEG + R_BEND), 2 * (X_LEG - R_BEND), 0, 0, - numElements=[N_HOR], recombine=True) + geo.extrude( + _tip(0, -X_LEG + R_BEND), + 2 * (X_LEG - R_BEND), + 0, + 0, + numElements=[N_HOR], + recombine=True, + ) geo.synchronize() # right elbow - geo.revolve(_tip(0, X_LEG - R_BEND), X_LEG - R_BEND, 0, Z_BEND_TOP, 0, -1, 0, - math.pi / 2, numElements=[N_ARC], recombine=True) + geo.revolve( + _tip(0, X_LEG - R_BEND), + X_LEG - R_BEND, + 0, + Z_BEND_TOP, + 0, + -1, + 0, + math.pi / 2, + numElements=[N_ARC], + recombine=True, + ) geo.synchronize() # right leg: extrude +z up to Z_AB - geo.extrude(_tip(2, Z_BEND_TOP), 0, 0, Z_AB - Z_BEND_TOP, - numElements=[N_LEG], recombine=True) + geo.extrude( + _tip(2, Z_BEND_TOP), + 0, + 0, + Z_AB - Z_BEND_TOP, + numElements=[N_LEG], + recombine=True, + ) geo.synchronize() vols, bnd = _boundary_surfs() @@ -243,17 +313,17 @@ def build_block_A(path): return vol -# ---- block B: U-loop <-> tank junction +# ---- block B: U-loop <-> tank junction def build_block_B(path): - '''Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). + """Tet-meshed junction connecting the U-pipe (A) to the hex tank (C). 1. Rectangular from Z_BOT to Z_BC (the tank-floor transition layer). - 2. Two cylindrical partial leds + 2. Two cylindrical partial leds 3. Fillet - + Interface matching (that was the hard part!) - Bottom circles (int_B_legL/R at Z_AB): rim nodes match A's pillow perimeter. - - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. - ''' + - Top rectangle (int_B_top at Z_BC): rim nodes match C's structured grid edges. + """ gmsh.initialize() gmsh.model.add("B") @@ -262,8 +332,10 @@ def build_block_B(path): pen = 0.4 * (Z_BC - Z_BOT) slab = occ.addBox(-HX, -HY, Z_BOT, 2 * HX, 2 * HY, Z_BC - Z_BOT) - stubs = [occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) - for sx in (-X_LEG, X_LEG)] + stubs = [ + occ.addCylinder(sx, 0, Z_AB, 0, 0, (Z_BOT - Z_AB) + pen, R) + for sx in (-X_LEG, X_LEG) + ] S, _ = occ.fuse([(3, slab)], [(3, s) for s in stubs]) occ.synchronize() vol = S[0][1] @@ -272,25 +344,28 @@ def build_block_B(path): for _, e in gmsh.model.getEntities(1): ex, _ey, ez = occ.getCenterOfMass(1, e) x0, _, _, x1, _, _ = gmsh.model.getBoundingBox(1, e) - if abs(ez - Z_BOT) < 1e-3 and abs(abs(ex) - X_LEG) < 0.02 \ - and (x1 - x0) < 3 * R: + if ( + abs(ez - Z_BOT) < 1e-3 + and abs(abs(ex) - X_LEG) < 0.02 + and (x1 - x0) < 3 * R + ): ring.append(e) occ.fillet([vol], ring, [FILLET_R]) occ.synchronize() vols, bnd = _boundary_surfs() - bot = _by(bnd, 2, Z_AB) # two pipe circles -> A - top = _by(bnd, 2, Z_BC) # tank square -> C + bot = _by(bnd, 2, Z_AB) # two pipe circles -> A + top = _by(bnd, 2, Z_BC) # tank square -> C walls = [s for s in bnd if s not in bot and s not in top] legL = [s for s in bot if occ.getCenterOfMass(2, s)[0] < 0] legR = [s for s in bot if occ.getCenterOfMass(2, s)[0] > 0] - for s in bot: # match each stub rim to A (4*N_SIDE) + for s in bot: # match each stub rim to A (4*N_SIDE) rc = _rims([s]) per = max(1, round(4 * N_SIDE / len(rc))) for cc in rc: gmsh.model.mesh.setTransfiniteCurve(cc, per + 1) - for cc in _rims(top): # match tank square rim to C (N_TANK/edge) + for cc in _rims(top): # match tank square rim to C (N_TANK/edge) gmsh.model.mesh.setTransfiniteCurve(cc, N_TANK + 1) gmsh.model.addPhysicalGroup(3, vols, name="juncB") @@ -308,15 +383,15 @@ def build_block_B(path): return vol -# --- block C: hex tank +# --- block C: hex tank def build_block_C(path): """Structured-hex tank extruded from Z_BC to Z_TOP. 1) N_TANK nodes per edge, matching block B's top 2) Extrude +z to Z_TOP with N_HC uniform layers. - - Top face is the open outlet boundary; - Sides are wall_C; + + Top face is the open outlet boundary; + Sides are wall_C; Bottom is for stitching to block B. """ gmsh.initialize() @@ -324,20 +399,26 @@ def build_block_C(path): gmsh.option.setNumber("General.Terminal", 0) geo = gmsh.model.geo - p = [geo.addPoint(-HX, -HY, Z_BC), geo.addPoint(HX, -HY, Z_BC), - geo.addPoint(HX, HY, Z_BC), geo.addPoint(-HX, HY, Z_BC)] + p = [ + geo.addPoint(-HX, -HY, Z_BC), + geo.addPoint(HX, -HY, Z_BC), + geo.addPoint(HX, HY, Z_BC), + geo.addPoint(-HX, HY, Z_BC), + ] l = [geo.addLine(p[i], p[(i + 1) % 4]) for i in range(4)] sq = geo.addPlaneSurface([geo.addCurveLoop(l)]) for e in l: geo.mesh.setTransfiniteCurve(e, N_TANK + 1) geo.mesh.setTransfiniteSurface(sq) geo.mesh.setRecombine(2, sq) - geo.extrude([(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True) + geo.extrude( + [(2, sq)], 0, 0, Z_TOP - Z_BC, numElements=[N_HC], recombine=True + ) geo.synchronize() vols, bnd = _boundary_surfs() bot = _by(bnd, 2, Z_BC) - top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) + top = _by(bnd, 2, Z_TOP) # open top -> outlet boundary (no stitch) walls = [s for s in bnd if s not in bot and s not in top] gmsh.model.addPhysicalGroup(3, vols, name="tank") gmsh.model.addPhysicalGroup(2, bot, name="int_C_bot") @@ -350,7 +431,7 @@ def build_block_C(path): # ---- verify that the junction that stitch mesh will operate on has consistent -# face perimeter +# face perimeter def _plane_nodes(path, zval): """All mesh nodes at z == zval from a .msh file, returned as (x, y) pairs.""" gmsh.initialize() @@ -364,23 +445,34 @@ def _plane_nodes(path, zval): def _circle_rim(pts, cx, r): """Subset of (x, y) points lying on a circle centred at (cx, 0) with radius r.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(math.hypot(x - cx, y) - r) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(math.hypot(x - cx, y) - r) < 1e-4 + ) def _square_rim(pts, hx, hy): """Subset of (x, y) points lying on the perimeter of a [-hx,hx] x [-hy,hy] rectangle.""" - return sorted((round(x, 9), round(y, 9)) for x, y in pts - if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4) + return sorted( + (round(x, 9), round(y, 9)) + for x, y in pts + if abs(abs(x) - hx) < 1e-4 or abs(abs(y) - hy) < 1e-4 + ) def _verify(name, a, b, tol=1e-9): """Assert two rim point sets have the same count and are coincident within tol.""" - assert len(a) == len(b), \ - f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." - worst = max(min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a) + assert len(a) == len( + b + ), f"{name}: rim node COUNT differs (A={len(a)}, B={len(b)}) -> areas differ." + worst = max( + min(math.hypot(px - qx, py - qy) for qx, qy in b) for px, py in a + ) ok = worst < tol - print(f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}") + print( + f"[verify {name}] n={len(a)} max rim gap={worst:.2e} m {'OK' if ok else 'FAIL'}" + ) assert ok, f"{name}: rims not coincident (gap {worst:.1e} > {tol})." @@ -388,8 +480,12 @@ def verify_interfaces(): """Check that A-B circle rims and B-C square rim match node-for-node across blocks.""" A_ab = _plane_nodes("blockA.msh", Z_AB) B_ab = _plane_nodes("blockB.msh", Z_AB) - _verify("A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R)) - _verify("A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R)) + _verify( + "A-B legL", _circle_rim(A_ab, -X_LEG, R), _circle_rim(B_ab, -X_LEG, R) + ) + _verify( + "A-B legR", _circle_rim(A_ab, X_LEG, R), _circle_rim(B_ab, X_LEG, R) + ) B_bc = _plane_nodes("blockB.msh", Z_BC) C_bc = _plane_nodes("blockC.msh", Z_BC) _verify("B-C square", _square_rim(B_bc, HX, HY), _square_rim(C_bc, HX, HY)) @@ -397,8 +493,10 @@ def verify_interfaces(): # ---- main if __name__ == "__main__": - print(f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " - f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}") + print( + f"[resolution] N_SIDE={N_SIDE} N_RAD={N_RAD} N_LEG={N_LEG} N_ARC={N_ARC} " + f"N_HOR={N_HOR} N_TANK={N_TANK} N_HC={N_HC}" + ) vols = { "A": build_block_A("blockA.msh"), "B": build_block_B("blockB.msh"), @@ -408,11 +506,19 @@ def verify_interfaces(): box_tank = (2 * HX) * (2 * HY) * (Z_TOP - Z_BOT) print("=" * 70) - print(f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " - f"excl. tank = {loop_pipe_length(False):.4f} m") - print(f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " - f"= {sum(vols.values()) * 1e3:.3f} L") - print(f" of which the box tank alone = {box_tank * 1e3:.3f} L") - print(f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " - f"({2 * HX:.3f} x {2 * HY:.3f} m)") + print( + f"[pipe length] incl. tank = {loop_pipe_length(True):.4f} m " + f"excl. tank = {loop_pipe_length(False):.4f} m" + ) + print( + f"[ieactor volume] this mesh (open-top box tank, blocks A-C) " + f"= {sum(vols.values()) * 1e3:.3f} L" + ) + print( + f" of which the box tank alone = {box_tank * 1e3:.3f} L" + ) + print( + f"[open top] outlet = full tank roof at z={Z_TOP:.3f} m " + f"({2 * HX:.3f} x {2 * HY:.3f} m)" + ) print("[write] block{A,B,C}.{msh,vtk} -> will stitch next") diff --git a/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py b/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py index 2f86cf69..ffe78675 100644 --- a/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py +++ b/experimental_cases/uloop_valadbeigy_exp3/get_mixing_time.py @@ -125,7 +125,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): z_target = z_final - band # Crossed the bottom boundary # Linearly interpolate to find the exact time t_settle at z_target - if z1 != z0: # Safety check to prevent division by zero + if z1 != z0: # Safety check to prevent division by zero t_settle = t0 + (t1 - t0) * (z_target - z0) / (z1 - z0) else: t_settle = t1 @@ -138,6 +138,7 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): return t_settle - t_start, t_settle, z_final + if __name__ == "__main__": os.makedirs(os.path.join(CASE, "Figures"), exist_ok=True) @@ -175,7 +176,9 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): dye_start = read_dye_start() t_mix, t_settle, z_final = mixing_time(t_arr, z_arr, dye_start) - t_mix_disc, t_settle_disc, z_final_disc = mixing_time(t_arr, z_arr, dye_start, continuous=False) + t_mix_disc, t_settle_disc, z_final_disc = mixing_time( + t_arr, z_arr, dye_start, continuous=False + ) with open(os.path.join(CASE, "mix_time.txt"), "w") as f: f.write(f"Continuous: {t_mix:.4f}\n") @@ -204,6 +207,12 @@ def mixing_time(t_arr, z_arr, t_start, continuous=True): print(f"final well-mixed Z discrete : {z_final_disc:.6g}") print(f"final well-mixed Z continous : {z_final:.6g}") print(f"dye injection start : {dye_start:.3f} s") - print(f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)") - print(f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)") - print("wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png") + print( + f"mixing time discrete (+/-5%) : {t_mix_disc:.3f} s (settles at t={t_settle_disc:.3f} s)" + ) + print( + f"mixing time continuous (+/-5%) : {t_mix:.3f} s (settles at t={t_settle:.3f} s)" + ) + print( + "wrote mix_time.txt, Z_box_average.dat and Figures/Z_box_average.png" + ) From d33897572d69afbf24bd7a74d2ff40daf96daf9d Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 16:52:30 -0600 Subject: [PATCH 32/52] missing gmsh --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ce43724a..e5cb07ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ dependencies = [ "corner", "jax>=0.9.0,<0.10", "numpyro>=0.20.0,<0.21", + "gmsh", ] [tool.setuptools.dynamic] From b8535db0f36aac0245fe13ee10df077d9b79c7ed Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 16:55:59 -0600 Subject: [PATCH 33/52] update pixi lock --- pixi.lock | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/pixi.lock b/pixi.lock index d7613d65..c1dd6ca9 100644 --- a/pixi.lock +++ b/pixi.lock @@ -253,6 +253,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -472,6 +473,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -732,6 +734,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -948,6 +951,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -1268,6 +1272,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -1541,6 +1546,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -1824,6 +1830,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -2063,6 +2070,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -2153,6 +2161,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda @@ -2273,6 +2282,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.2-pl5321h16c4a6b_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel_yaml-0.15.80-py312h98912ed_1009.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.17.1-py312h54fa4ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -2282,6 +2292,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.49-py312h5253ce2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.0-h04a0ce9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.3.0-hb700be7_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-w-1.2.0-pyhd8ed1ab_0.conda @@ -2330,6 +2341,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -2409,6 +2421,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-7.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jsoncpp-1.9.6-h726d253_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py312h3093aea_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda @@ -2513,6 +2526,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qt6-main-6.10.2-pl5321h01fc3ab_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel_yaml-0.15.80-py312h02f2b3b_1009.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.1-py312h0f234b1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda @@ -2522,6 +2536,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.49-py312hb3ab3e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.53.0-h85ec8f2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tbb-2022.3.0-h4ddebb9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-w-1.2.0-pyhd8ed1ab_0.conda @@ -2553,6 +2568,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -2813,6 +2829,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py312h5253ce2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/a0/ddb3a71359c1df61f3edc408936b5bda7ed402e78ae7e9ef6afd438577c6/jaxlib-0.9.2-cp312-cp312-manylinux_2_27_x86_64.whl @@ -3029,6 +3046,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py312h37e1c23_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/17/9c/e897231c880f69e32251d3b1145894d7a04e4342d9bef8d29644c440d11b/jax-0.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/15/ff3d9fde15b5146a0164505085312d8c9c0b0bbd7be5a15218ead2593307/jaxlib-0.9.2-cp312-cp312-macosx_11_0_arm64.whl @@ -4274,6 +4292,14 @@ packages: purls: [] size: 558669 timestamp: 1760370890246 +- pypi: https://files.pythonhosted.org/packages/3d/b4/0d25938ad62ea4db6bcbdecbc77c72d05d8a6a679abe4addcd86167ffd77/gmsh-4.15.2-py2.py3-none-macosx_12_0_arm64.whl + name: gmsh + version: 4.15.2 + sha256: f6649b3e59f49272e7ee8ab282ecb4d1a6e0d627e86cf3e3b1a83fd07417e4f8 +- pypi: https://files.pythonhosted.org/packages/ab/d4/336becb1488ac4fbab205043987128839c8c62d54e2036b7e887bd009040/gmsh-4.15.2-py2.py3-none-manylinux_2_24_x86_64.whl + name: gmsh + version: 4.15.2 + sha256: 4076a948ce22625330d1413d4982e22b5c69fc2f0f7951f5df64c778cf54108c - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c md5: 2cd94587f3a401ae05e03a6caf09539d @@ -6924,8 +6950,8 @@ packages: timestamp: 1768670878127 - pypi: ./ name: nlr-bird - version: 0.0.55 - sha256: 29437d15aaad5ae9d209850c35db2ff653a087bc441869fb78696baf1e3d830f + version: 0.0.56 + sha256: fd725f36ff4cff386880348c4c38d5716a281779613033428c6bf8bdaa866776 requires_dist: - numpy - prettyplot>=0.0.36,<0.0.37 @@ -6935,6 +6961,7 @@ packages: - corner - jax>=0.9.0,<0.10 - numpyro>=0.20.0,<0.21 + - gmsh - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - sphinx-autodoc-typehints ; extra == 'docs' From cc91f7041f43c798a21a24137197955059a8b18d Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 17:52:34 -0600 Subject: [PATCH 34/52] fix lib hdf5 link --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edfbcccd..68839231 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview + micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install --upgrade nox pip install .[tests] @@ -154,7 +154,7 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview + micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install --upgrade nox pip install nlr-bird[tests] @@ -196,7 +196,7 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview + micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install . @@ -301,7 +301,7 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview + micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install . From fe1ee1ce81783ba389de7d3a6cbf0d91839eb86d Mon Sep 17 00:00:00 2001 From: Malik Date: Tue, 1 Sep 2026 18:11:28 -0600 Subject: [PATCH 35/52] fix hdf5 lib --- .github/workflows/ci.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68839231..8de6c740 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,8 @@ jobs: environment-name: test-env create-args: >- python=${{ matrix.python-version }} + paraview=6.1 + hdf5=1.14 channels: conda-forge channel-priority: strict cache-downloads: true @@ -89,7 +91,6 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install --upgrade nox pip install .[tests] @@ -147,6 +148,8 @@ jobs: environment-name: test-env create-args: >- python=${{ matrix.python-version }} + paraview=6.1 + hdf5=1.14 channels: conda-forge channel-priority: strict cache-downloads: true @@ -154,7 +157,6 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install --upgrade nox pip install nlr-bird[tests] @@ -189,6 +191,8 @@ jobs: environment-name: test-env create-args: >- python=${{ matrix.python-version }} + paraview=6.1 + hdf5=1.14 channels: conda-forge channel-priority: strict cache-downloads: true @@ -196,7 +200,6 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install . @@ -294,6 +297,8 @@ jobs: environment-name: test-env create-args: >- python=${{ matrix.python-version }} + paraview=6.1 + hdf5=1.14 channels: conda-forge channel-priority: strict cache-downloads: true @@ -301,7 +306,6 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview hdf5 pip install --upgrade pip pip install . From eb5d46dc85feccea9e0ea0411f136b1c394dca65 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 2 Sep 2026 06:49:06 -0600 Subject: [PATCH 36/52] fix application paths and deploy to pypi --- bird/version.py | 2 +- tutorial_cases/OF9/loop_reactor_mixing_static/run.sh | 8 ++++---- tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bird/version.py b/bird/version.py index 4aae0559..cfeacc5a 100644 --- a/bird/version.py +++ b/bird/version.py @@ -1,3 +1,3 @@ """Bio reactor design version""" -__version__ = "0.0.56" +__version__ = "0.0.57" diff --git a/tutorial_cases/OF9/loop_reactor_mixing_static/run.sh b/tutorial_cases/OF9/loop_reactor_mixing_static/run.sh index 25251599..8ec96fb0 100644 --- a/tutorial_cases/OF9/loop_reactor_mixing_static/run.sh +++ b/tutorial_cases/OF9/loop_reactor_mixing_static/run.sh @@ -12,16 +12,16 @@ trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR echo PRESTEP 1 # Generate blockmeshDict -python ../../applications/write_block_rect_mesh.py -i system/mesh.json -o system +python ../../../applications/write_block_rect_mesh.py -i system/mesh.json -o system # Generate boundary stl -python ../../applications/write_stl_patch.py -i system/inlets_outlets.json +python ../../../applications/write_stl_patch.py -i system/inlets_outlets.json # Generate mixers -python ../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant +python ../../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant # Generate species thermo properties -python ../../applications/write_species_thermo_prop.py -cf . +python ../../../applications/write_species_thermo_prop.py -cf . echo PRESTEP 2 # Mesh gen diff --git a/tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh b/tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh index 25251599..8ec96fb0 100644 --- a/tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh +++ b/tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh @@ -12,16 +12,16 @@ trap 'echo "ERROR: Something failed! Running cleanup..."; ./Allclean' ERR echo PRESTEP 1 # Generate blockmeshDict -python ../../applications/write_block_rect_mesh.py -i system/mesh.json -o system +python ../../../applications/write_block_rect_mesh.py -i system/mesh.json -o system # Generate boundary stl -python ../../applications/write_stl_patch.py -i system/inlets_outlets.json +python ../../../applications/write_stl_patch.py -i system/inlets_outlets.json # Generate mixers -python ../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant +python ../../../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant # Generate species thermo properties -python ../../applications/write_species_thermo_prop.py -cf . +python ../../../applications/write_species_thermo_prop.py -cf . echo PRESTEP 2 # Mesh gen From 1064f7bf1daa2dee3f2d03766b14ca52acdc2914 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 2 Sep 2026 07:46:12 -0600 Subject: [PATCH 37/52] remove run all and adjust allclean --- experimental_cases/OF9/deckwer17/Allclean | 2 +- experimental_cases/OF9/deckwer19/Allclean | 2 +- .../bubble_column_pbe_20L/Allclean | 2 +- .../OF9/uloop_valadbeigy_exp1/Allclean | 3 +- .../OF9/uloop_valadbeigy_exp1/script_post | 1 - .../OF9/uloop_valadbeigy_exp2/Allclean | 2 +- .../OF9/uloop_valadbeigy_exp2/script_post | 1 - .../OF9/uloop_valadbeigy_exp3/Allclean | 2 +- .../OF9/uloop_valadbeigy_exp3/script_post | 1 - .../OF9/FlatPanel_250L_ASU/Allclean | 2 +- tutorial_cases/OF9/airlift_40m/Allclean | 2 +- .../OF9/bdofoam_cases/nonreact/Allclean | 2 +- .../OF9/bdofoam_cases/react/Allclean | 2 +- tutorial_cases/OF9/bubble_column_20L/Allclean | 2 +- .../OF9/loop_reactor_mixing/Allclean | 2 +- .../OF9/loop_reactor_mixing_static/Allclean | 2 +- .../OF9/loop_reactor_mixing_swirl/Allclean | 2 +- .../OF9/loop_reactor_reacting/Allclean | 2 +- tutorial_cases/OF9/runall.sh | 61 ------------------- tutorial_cases/OF9/side_sparger/Allclean | 2 +- tutorial_cases/OF9/stirred_tank/Allclean | 2 +- 21 files changed, 17 insertions(+), 82 deletions(-) delete mode 100644 tutorial_cases/OF9/runall.sh diff --git a/experimental_cases/OF9/deckwer17/Allclean b/experimental_cases/OF9/deckwer17/Allclean index dc2f77db..174b6310 100755 --- a/experimental_cases/OF9/deckwer17/Allclean +++ b/experimental_cases/OF9/deckwer17/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/experimental_cases/OF9/deckwer19/Allclean b/experimental_cases/OF9/deckwer19/Allclean index dc2f77db..174b6310 100755 --- a/experimental_cases/OF9/deckwer19/Allclean +++ b/experimental_cases/OF9/deckwer19/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/experimental_cases/OF9/disengagement/bubble_column_pbe_20L/Allclean b/experimental_cases/OF9/disengagement/bubble_column_pbe_20L/Allclean index dc2f77db..174b6310 100755 --- a/experimental_cases/OF9/disengagement/bubble_column_pbe_20L/Allclean +++ b/experimental_cases/OF9/disengagement/bubble_column_pbe_20L/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean index dc2f77db..bf27685b 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean @@ -15,8 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" -# rm -f constant/fvModels +rm -rf "processor*" rm -f *.obj rm -f *.stl rm -f *.txt diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post index dcbf59d8..f1577763 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post @@ -5,7 +5,6 @@ #SBATCH --ntasks-per-node=16 #SBATCH --time=01:59:00 #SBATCH --account=gas2fuels -#SBATCH --dependency=afterany:15800966 source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp2/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp2/Allclean index dc2f77db..174b6310 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp2/Allclean +++ b/experimental_cases/OF9/uloop_valadbeigy_exp2/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post index dcbf59d8..f1577763 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post +++ b/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post @@ -5,7 +5,6 @@ #SBATCH --ntasks-per-node=16 #SBATCH --time=01:59:00 #SBATCH --account=gas2fuels -#SBATCH --dependency=afterany:15800966 source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp3/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp3/Allclean index dc2f77db..174b6310 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp3/Allclean +++ b/experimental_cases/OF9/uloop_valadbeigy_exp3/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post index dcbf59d8..f1577763 100755 --- a/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post +++ b/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post @@ -5,7 +5,6 @@ #SBATCH --ntasks-per-node=16 #SBATCH --time=01:59:00 #SBATCH --account=gas2fuels -#SBATCH --dependency=afterany:15800966 source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc reconstructPar -newTimes -fields "(Z.liquid U.liquid alpha.gas)" diff --git a/tutorial_cases/OF9/FlatPanel_250L_ASU/Allclean b/tutorial_cases/OF9/FlatPanel_250L_ASU/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/FlatPanel_250L_ASU/Allclean +++ b/tutorial_cases/OF9/FlatPanel_250L_ASU/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/airlift_40m/Allclean b/tutorial_cases/OF9/airlift_40m/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/airlift_40m/Allclean +++ b/tutorial_cases/OF9/airlift_40m/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/bdofoam_cases/nonreact/Allclean b/tutorial_cases/OF9/bdofoam_cases/nonreact/Allclean index e9221067..e3bca612 100755 --- a/tutorial_cases/OF9/bdofoam_cases/nonreact/Allclean +++ b/tutorial_cases/OF9/bdofoam_cases/nonreact/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" [ -d "fluentInterface" ] && rm -rf "rm -f fluentInterface" # rm -f constant/fvModels rm -f *.obj diff --git a/tutorial_cases/OF9/bdofoam_cases/react/Allclean b/tutorial_cases/OF9/bdofoam_cases/react/Allclean index e9221067..e3bca612 100755 --- a/tutorial_cases/OF9/bdofoam_cases/react/Allclean +++ b/tutorial_cases/OF9/bdofoam_cases/react/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" [ -d "fluentInterface" ] && rm -rf "rm -f fluentInterface" # rm -f constant/fvModels rm -f *.obj diff --git a/tutorial_cases/OF9/bubble_column_20L/Allclean b/tutorial_cases/OF9/bubble_column_20L/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/bubble_column_20L/Allclean +++ b/tutorial_cases/OF9/bubble_column_20L/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/loop_reactor_mixing/Allclean b/tutorial_cases/OF9/loop_reactor_mixing/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/loop_reactor_mixing/Allclean +++ b/tutorial_cases/OF9/loop_reactor_mixing/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/loop_reactor_mixing_static/Allclean b/tutorial_cases/OF9/loop_reactor_mixing_static/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/loop_reactor_mixing_static/Allclean +++ b/tutorial_cases/OF9/loop_reactor_mixing_static/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/loop_reactor_mixing_swirl/Allclean b/tutorial_cases/OF9/loop_reactor_mixing_swirl/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/loop_reactor_mixing_swirl/Allclean +++ b/tutorial_cases/OF9/loop_reactor_mixing_swirl/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/loop_reactor_reacting/Allclean b/tutorial_cases/OF9/loop_reactor_reacting/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/loop_reactor_reacting/Allclean +++ b/tutorial_cases/OF9/loop_reactor_reacting/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/runall.sh b/tutorial_cases/OF9/runall.sh deleted file mode 100644 index 31e971fb..00000000 --- a/tutorial_cases/OF9/runall.sh +++ /dev/null @@ -1,61 +0,0 @@ -#Compile solver - -conda activate bird -BIRD_HOME=`python -c "import bird; print(bird.BIRD_DIR)"` -cd ${BIRD_HOME}/../OFsolvers/birdmultiphaseEulerFoam -export WM_COMPILE_OPTION=Debug -./Allwmake -cd ../../ - -# Run all tests - -## Run deckwer17 PBE -cd experimental_cases/deckwer17 -bash run.sh -cd ../../ -## Run deckwer17 constantD -cd experimental_cases/deckwer17 -cp constant/phaseProperties_constantd constant/phaseProperties -bash run.sh -cd ../../ -## Run deckwer19 PBE -cd experimental_cases/deckwer19 -bash run.sh -cd ../../ -## Run side sparger tutorial -cd tutorial_cases/side_sparger -bash run.sh -cd ../../ -## Run bubble column tutorial -cd tutorial_cases/bubble_column_20L -bash run.sh -cd ../../ -## Run stirred-tank tutorial -cd tutorial_cases/stirred_tank -bash run.sh -cd ../../ -## Run reactive loop reactor tutorial -cd tutorial_cases/loop_reactor_reacting -bash run.sh -cd ../../ -## Run mixing loop reactor tutorial -cd tutorial_cases/loop_reactor_mixing -bash run.sh -cd ../../ -## Run mixing loop reactor with swirl tutorial -cd tutorial_cases/loop_reactor_mixing_swirl -bash run.sh -cd ../../ -## Run mixing loop reactor with static mixer tutorial -cd tutorial_cases/loop_reactor_mixing_static -bash run.sh -cd ../../ -## Run airlift reactor tutorial -cd tutorial_cases/airlift_40m -bash run.sh -cd ../../ -## Run flat panel reactor tutorial -cd tutorial_cases/FlatPanel_250L_ASU -bash run.sh -cd ../../ - diff --git a/tutorial_cases/OF9/side_sparger/Allclean b/tutorial_cases/OF9/side_sparger/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/side_sparger/Allclean +++ b/tutorial_cases/OF9/side_sparger/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl diff --git a/tutorial_cases/OF9/stirred_tank/Allclean b/tutorial_cases/OF9/stirred_tank/Allclean index dc2f77db..174b6310 100755 --- a/tutorial_cases/OF9/stirred_tank/Allclean +++ b/tutorial_cases/OF9/stirred_tank/Allclean @@ -15,7 +15,7 @@ fi # [ -d "constant/extendedFeatureEdgeMesh" ] && rm -rf "constant/extendedFeatureEdgeMesh" [ -d "constant/polyMesh" ] && rm -rf "constant/polyMesh" [ -d "dynamicCode" ] && rm -rf "dynamicCode" -[ -d "processor*" ] && rm -rf "processor*" +rm -rf "processor*" # rm -f constant/fvModels rm -f *.obj rm -f *.stl From 4e8868fe19c5c995b8734111aaec62c5cb1dd1bd Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 10:23:20 -0600 Subject: [PATCH 38/52] add data to reproduce plots --- bird/version.py | 2 +- papers/scaleup/SA_optimization/README.md | 19 + papers/scaleup/SA_optimization/configs.pkl | Bin 0 -> 70259 bytes .../data/study/study_0_4vvm_lev1/X_data.csv | 289 +++++++ .../data/study/study_0_4vvm_lev1/Y_data.csv | 290 +++++++ .../qoi/best_bootstrap_solution_nn_qoi.csv | 2 + .../qoi/convergence_data_nn_qoi.npz | Bin 0 -> 407046 bytes .../qoi/hyperparams_qoi.json | 50 ++ .../best_bootstrap_solution_nn_qoi_kla.csv | 2 + .../qoi_kla/convergence_data_nn_qoi_kla.npz | Bin 0 -> 407046 bytes .../qoi_kla/hyperparams_qoi_kla.json | 50 ++ .../best_bootstrap_solution_nn_qoi_sum.csv | 2 + .../qoi_sum/convergence_data_nn_qoi_sum.npz | Bin 0 -> 407046 bytes .../qoi_sum/hyperparams_qoi_sum.json | 50 ++ ...best_bootstrap_solution_nn_qoi_sum_kla.csv | 2 + .../convergence_data_nn_qoi_sum_kla.npz | Bin 0 -> 407046 bytes .../qoi_sum_kla/hyperparams_qoi_sum_kla.json | 50 ++ .../data/study/study_0_4vvm_lev1/split.csv | 290 +++++++ .../data/study/study_0_4vvm_lev2/X_data.csv | 161 ++++ .../data/study/study_0_4vvm_lev2/Y_data.csv | 162 ++++ .../data/study/study_0_4vvm_lev3/X_data.csv | 148 ++++ .../data/study/study_0_4vvm_lev3/Y_data.csv | 149 ++++ .../data/study/study_0_4vvm_lev4/X_data.csv | 135 ++++ .../data/study/study_0_4vvm_lev4/Y_data.csv | 136 ++++ .../data/study/study_0_4vvm_lev5/X_data.csv | 165 ++++ .../data/study/study_0_4vvm_lev5/Y_data.csv | 166 ++++ .../data/study/study_0_4vvm_lev6/X_data.csv | 301 +++++++ .../data/study/study_0_4vvm_lev6/Y_data.csv | 302 +++++++ .../qoi/best_bootstrap_solution_nn_qoi.csv | 2 + .../qoi/cfd_all_spargers.txt | 1 + .../qoi/convergence_data_nn_qoi.npz | Bin 0 -> 407046 bytes .../qoi/hyperparams_qoi.json | 50 ++ .../best_bootstrap_solution_nn_qoi_kla.csv | 2 + .../qoi_kla/cfd_all_spargers.txt | 1 + .../qoi_kla/convergence_data_nn_qoi_kla.npz | Bin 0 -> 407046 bytes .../qoi_kla/hyperparams_qoi_kla.json | 50 ++ .../best_bootstrap_solution_nn_qoi_sum.csv | 2 + .../qoi_sum/cfd_all_spargers.txt | 1 + .../qoi_sum/convergence_data_nn_qoi_sum.npz | Bin 0 -> 407046 bytes .../qoi_sum/hyperparams_qoi_sum.json | 50 ++ ...est_bootstrap_solution_rbf_qoi_sum_kla.csv | 2 + .../qoi_sum_kla/cfd_all_spargers.txt | 1 + .../convergence_data_rbf_qoi_sum_kla.npz | Bin 0 -> 407046 bytes .../qoi_sum_kla/hyperparams_qoi_sum_kla.json | 49 ++ .../data/study/study_0_4vvm_lev6/split.csv | 302 +++++++ .../study_fine/study_0_4vvm_lev6/X_data.csv | 30 + .../study_fine/study_0_4vvm_lev6/Y_data.csv | 31 + .../study_op/study_0_1vvm_lev6/X_data.csv | 23 + .../study_op/study_0_1vvm_lev6/Y_data.csv | 24 + .../study_pbe/study_0_4vvm_lev6/X_data.csv | 26 + .../study_pbe/study_0_4vvm_lev6/Y_data.csv | 27 + .../scaleup/SA_optimization/data/transfer.sh | 11 + .../SA_optimization/get_optimal_all_qois.py | 436 ++++++++++ .../get_optimal_constrained.py | 175 ++++ papers/scaleup/SA_optimization/load_data.py | 45 ++ .../SA_optimization/make_hyperparam_tables.py | 158 ++++ .../SA_optimization/make_val_rmse_table.py | 117 +++ .../SA_optimization/marginal_gain_results.csv | 57 ++ .../SA_optimization/model_selection.py | 139 ++++ .../SA_optimization/plot_marginal_gain.py | 72 ++ papers/scaleup/SA_optimization/surrogate.py | 273 +++++++ .../SA_optimization/surrogate_selection.csv | 9 + .../scaleup/generate_scaleup_runs/README.md | 3 + .../scaleup/generate_scaleup_runs/randsim.py | 163 ++++ .../template/0.orig/CO2.gas | 47 ++ .../template/0.orig/CO2.liquid | 42 + .../template/0.orig/H2.gas | 47 ++ .../template/0.orig/H2.liquid | 42 + .../template/0.orig/N2.gas | 47 ++ .../template/0.orig/T.gas | 44 ++ .../template/0.orig/T.liquid | 43 + .../template/0.orig/U.gas | 47 ++ .../template/0.orig/U.liquid | 46 ++ .../template/0.orig/Ydefault.gas | 42 + .../template/0.orig/Ydefault.liquid | 42 + .../template/0.orig/alpha.gas | 43 + .../template/0.orig/alpha.liquid | 40 + .../template/0.orig/alphat.gas | 46 ++ .../template/0.orig/alphat.liquid | 44 ++ .../template/0.orig/f.gas | 41 + .../template/0.orig/k.gas | 43 + .../template/0.orig/k.liquid | 44 ++ .../template/0.orig/nut.gas | 48 ++ .../template/0.orig/nut.liquid | 43 + .../template/0.orig/omega.gas | 48 ++ .../template/0.orig/omega.liquid | 43 + .../generate_scaleup_runs/template/0.orig/p | 39 + .../template/0.orig/p_rgh | 43 + .../generate_scaleup_runs/template/Allclean | 18 + .../template/computeQOI.sh | 13 + .../template/constant/fvModels | 128 +++ .../generate_scaleup_runs/template/constant/g | 21 + .../template/constant/globalVars | 83 ++ .../template/constant/globalVars_temp | 83 ++ .../template/constant/momentumTransport.gas | 26 + .../constant/momentumTransport.liquid | 27 + .../template/constant/phaseProperties | 295 +++++++ .../constant/phaseProperties_constantd | 261 ++++++ .../template/constant/phaseProperties_pbe | 295 +++++++ .../constant/thermophysicalProperties.gas | 142 ++++ .../constant/thermophysicalProperties.liquid | 108 +++ .../generate_scaleup_runs/template/get_qoi.py | 227 ++++++ .../template/presteps.sh | 75 ++ .../template/read_history.py | 100 +++ .../generate_scaleup_runs/template/run.sh | 5 + .../generate_scaleup_runs/template/script | 14 + .../template/script_post | 10 + .../template/system/blockMeshDict | 746 ++++++++++++++++++ .../template/system/controlDict | 67 ++ .../template/system/decomposeParDict | 30 + .../template/system/fvConstraints | 56 ++ .../template/system/fvSchemes | 70 ++ .../template/system/fvSolution | 121 +++ .../template/system/inlets_outlets.json | 28 + .../template/system/mesh.json | 26 + .../template/system/mixers.json | 29 + .../template/system/setFieldsDict | 37 + .../generate_scaleup_runs/template/test.foam | 0 .../template/writeGlobalVars.py | 42 + 119 files changed, 9491 insertions(+), 1 deletion(-) create mode 100644 papers/scaleup/SA_optimization/README.md create mode 100644 papers/scaleup/SA_optimization/configs.pkl create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/best_bootstrap_solution_nn_qoi.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/convergence_data_nn_qoi.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/hyperparams_qoi.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/convergence_data_nn_qoi_kla.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/hyperparams_qoi_kla.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/best_bootstrap_solution_nn_qoi_sum.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/convergence_data_nn_qoi_sum.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/hyperparams_qoi_sum.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/best_bootstrap_solution_nn_qoi_sum_kla.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/convergence_data_nn_qoi_sum_kla.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/hyperparams_qoi_sum_kla.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/split.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/best_bootstrap_solution_nn_qoi.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/cfd_all_spargers.txt create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/convergence_data_nn_qoi.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/hyperparams_qoi.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/cfd_all_spargers.txt create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/convergence_data_nn_qoi_kla.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/hyperparams_qoi_kla.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/best_bootstrap_solution_nn_qoi_sum.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/cfd_all_spargers.txt create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/convergence_data_nn_qoi_sum.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/hyperparams_qoi_sum.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/best_bootstrap_solution_rbf_qoi_sum_kla.csv create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/cfd_all_spargers.txt create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/convergence_data_rbf_qoi_sum_kla.npz create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/hyperparams_qoi_sum_kla.json create mode 100644 papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/split.csv create mode 100644 papers/scaleup/SA_optimization/data/study_fine/study_0_4vvm_lev6/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study_fine/study_0_4vvm_lev6/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study_op/study_0_1vvm_lev6/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study_op/study_0_1vvm_lev6/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study_pbe/study_0_4vvm_lev6/X_data.csv create mode 100644 papers/scaleup/SA_optimization/data/study_pbe/study_0_4vvm_lev6/Y_data.csv create mode 100644 papers/scaleup/SA_optimization/data/transfer.sh create mode 100644 papers/scaleup/SA_optimization/get_optimal_all_qois.py create mode 100644 papers/scaleup/SA_optimization/get_optimal_constrained.py create mode 100644 papers/scaleup/SA_optimization/load_data.py create mode 100644 papers/scaleup/SA_optimization/make_hyperparam_tables.py create mode 100644 papers/scaleup/SA_optimization/make_val_rmse_table.py create mode 100644 papers/scaleup/SA_optimization/marginal_gain_results.csv create mode 100644 papers/scaleup/SA_optimization/model_selection.py create mode 100644 papers/scaleup/SA_optimization/plot_marginal_gain.py create mode 100644 papers/scaleup/SA_optimization/surrogate.py create mode 100644 papers/scaleup/SA_optimization/surrogate_selection.csv create mode 100644 papers/scaleup/generate_scaleup_runs/README.md create mode 100644 papers/scaleup/generate_scaleup_runs/randsim.py create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/H2.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/H2.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/N2.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/T.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/T.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/U.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/U.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/f.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/k.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/k.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/nut.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/nut.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/omega.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/omega.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/p create mode 100644 papers/scaleup/generate_scaleup_runs/template/0.orig/p_rgh create mode 100755 papers/scaleup/generate_scaleup_runs/template/Allclean create mode 100644 papers/scaleup/generate_scaleup_runs/template/computeQOI.sh create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/fvModels create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/g create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/globalVars create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/globalVars_temp create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_constantd create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_pbe create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.gas create mode 100644 papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.liquid create mode 100644 papers/scaleup/generate_scaleup_runs/template/get_qoi.py create mode 100644 papers/scaleup/generate_scaleup_runs/template/presteps.sh create mode 100644 papers/scaleup/generate_scaleup_runs/template/read_history.py create mode 100644 papers/scaleup/generate_scaleup_runs/template/run.sh create mode 100755 papers/scaleup/generate_scaleup_runs/template/script create mode 100755 papers/scaleup/generate_scaleup_runs/template/script_post create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/blockMeshDict create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/controlDict create mode 100755 papers/scaleup/generate_scaleup_runs/template/system/decomposeParDict create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/fvConstraints create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/fvSchemes create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/fvSolution create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/inlets_outlets.json create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/mesh.json create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/mixers.json create mode 100644 papers/scaleup/generate_scaleup_runs/template/system/setFieldsDict create mode 100644 papers/scaleup/generate_scaleup_runs/template/test.foam create mode 100644 papers/scaleup/generate_scaleup_runs/template/writeGlobalVars.py diff --git a/bird/version.py b/bird/version.py index cfeacc5a..30aea71c 100644 --- a/bird/version.py +++ b/bird/version.py @@ -1,3 +1,3 @@ """Bio reactor design version""" -__version__ = "0.0.57" +__version__ = "0.0.58" diff --git a/papers/scaleup/SA_optimization/README.md b/papers/scaleup/SA_optimization/README.md new file mode 100644 index 00000000..ff88756f --- /dev/null +++ b/papers/scaleup/SA_optimization/README.md @@ -0,0 +1,19 @@ + +# Optim + +`python get_optimal_all_qois.py --plot-only` regenerates the optimization plots + +`python get_optimal_all_qois.py` recomputes the optimization + +# Constrained optim + +`python get_optimal_constrained.py` redoes the constrained optimization (constrains the number of spargers) + +`python plot_marginal_gain.py` plots the results of the constrained optimization + +# Latex tables + +`python make_hyperparam_tables.py` makes the latex tables with the optimal hyperpar + +`python make_val_rmse_table.py` makes the surrogate perf tables + diff --git a/papers/scaleup/SA_optimization/configs.pkl b/papers/scaleup/SA_optimization/configs.pkl new file mode 100644 index 0000000000000000000000000000000000000000..b4bd9b37d3c1c3a2b41927cc9bcb5ea574e9a464 GIT binary patch literal 70259 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 literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/hyperparams_qoi.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/hyperparams_qoi.json new file mode 100644 index 00000000..631a1b8d --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi/hyperparams_qoi.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi", + "best": "nn", + "best_params": { + "n_units": 115, + "n_layers": 3, + "lr": 0.007352422228350128 + }, + "amp_physical": 31.847128737940537, + "mean_physical": 1.1587697843637461, + "rbf": { + "params": { + "kernel": "inverse_multiquadric", + "epsilon": 4.061810507250742 + }, + "test_mse": 0.793554500254287, + "val_mse": 0.7742804347958798, + "test_nrmse_amp_pct": 2.7971650679432742, + "test_nrmse_mean_pct": 76.87607773529611, + "val_nrmse_amp_pct": 2.762987112097808, + "val_nrmse_mean_pct": 75.93674554481456 + }, + "rf": { + "params": { + "n_estimators": 101, + "max_depth": 3, + "min_samples_leaf": 4, + "max_features": 0.1685863056814062 + }, + "test_mse": 0.6929890052189214, + "val_mse": 0.8281670290668213, + "test_nrmse_amp_pct": 2.613923592969481, + "test_nrmse_mean_pct": 71.83994810681708, + "val_nrmse_amp_pct": 2.857516091641253, + "val_nrmse_mean_pct": 78.53473922881386 + }, + "nn": { + "params": { + "n_units": 115, + "n_layers": 3, + "lr": 0.007352422228350128 + }, + "test_mse": 0.0707926548581952, + "val_mse": 0.04559337741600136, + "test_nrmse_amp_pct": 0.835456450023289, + "test_nrmse_mean_pct": 22.96132456840312, + "val_nrmse_amp_pct": 0.6704719275922347, + "val_nrmse_mean_pct": 18.426961145633662 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv new file mode 100644 index 00000000..05846359 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +1,2,1,1,1,2,0,2,2,2,2,-4.501358457518286e-12 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/convergence_data_nn_qoi_kla.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_kla/convergence_data_nn_qoi_kla.npz new file mode 100644 index 0000000000000000000000000000000000000000..13949a61067218e3155adda4bc1f67608a15d3b8 GIT binary patch literal 407046 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 literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/hyperparams_qoi_sum.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/hyperparams_qoi_sum.json new file mode 100644 index 00000000..a4e444cd --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum/hyperparams_qoi_sum.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi_sum", + "best": "nn", + "best_params": { + "n_units": 32, + "n_layers": 3, + "lr": 0.003626140666750365 + }, + "amp_physical": 24.227573051899828, + "mean_physical": 7.421273410411606, + "rbf": { + "params": { + "kernel": "multiquadric", + "epsilon": 9.997810687782733 + }, + "test_mse": 2.1611921847299187, + "val_mse": 2.2280892794916007, + "test_nrmse_amp_pct": 6.067877191218115, + "test_nrmse_mean_pct": 19.80926045844739, + "val_nrmse_amp_pct": 6.16107339957327, + "val_nrmse_mean_pct": 20.113509853560206 + }, + "rf": { + "params": { + "n_estimators": 125, + "max_depth": 9, + "min_samples_leaf": 2, + "max_features": 0.15062441354415443 + }, + "test_mse": 2.3346167924905297, + "val_mse": 1.690849119476513, + "test_nrmse_amp_pct": 6.30663781819191, + "test_nrmse_mean_pct": 20.58872109977204, + "val_nrmse_amp_pct": 5.367134960719106, + "val_nrmse_mean_pct": 17.52160945287362 + }, + "nn": { + "params": { + "n_units": 32, + "n_layers": 3, + "lr": 0.003626140666750365 + }, + "test_mse": 0.2684176605898265, + "val_mse": 0.6018713490278378, + "test_nrmse_amp_pct": 2.138432920941118, + "test_nrmse_mean_pct": 6.981152282572348, + "val_nrmse_amp_pct": 3.2021518530766255, + "val_nrmse_mean_pct": 10.45378113072208 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/best_bootstrap_solution_nn_qoi_sum_kla.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/best_bootstrap_solution_nn_qoi_sum_kla.csv new file mode 100644 index 00000000..99d0e9ba --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/best_bootstrap_solution_nn_qoi_sum_kla.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +0,1,0,2,2,1,0,0,0,0,0,-9.208020626300388e-06 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/convergence_data_nn_qoi_sum_kla.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/convergence_data_nn_qoi_sum_kla.npz new file mode 100644 index 0000000000000000000000000000000000000000..98b4d32d098e60fae4d4ddeac34631fc8a8e83d2 GIT binary patch literal 407046 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 K?N%@G=KlemkJYIF literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/hyperparams_qoi_sum_kla.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/hyperparams_qoi_sum_kla.json new file mode 100644 index 00000000..f6f71d3e --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/qoi_sum_kla/hyperparams_qoi_sum_kla.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi_sum_kla", + "best": "nn", + "best_params": { + "n_units": 52, + "n_layers": 2, + "lr": 0.00027717283587404306 + }, + "amp_physical": 4.764162053594671e-06, + "mean_physical": 6.450542874776105e-06, + "rbf": { + "params": { + "kernel": "multiquadric", + "epsilon": 4.897534301342347 + }, + "test_mse": 7.323713661313873e-14, + "val_mse": 4.523472988855829e-13, + "test_nrmse_amp_pct": 5.68040305637199, + "test_nrmse_mean_pct": 4.195361726237645, + "val_nrmse_amp_pct": 14.117229501555634, + "val_nrmse_mean_pct": 10.426528495174603 + }, + "rf": { + "params": { + "n_estimators": 65, + "max_depth": 7, + "min_samples_leaf": 2, + "max_features": 0.37545562583526304 + }, + "test_mse": 7.359651767356893e-14, + "val_mse": 5.478837571693559e-13, + "test_nrmse_amp_pct": 5.694323118829236, + "test_nrmse_mean_pct": 4.205642633539542, + "val_nrmse_amp_pct": 15.53666089984357, + "val_nrmse_mean_pct": 11.474874554829146 + }, + "nn": { + "params": { + "n_units": 52, + "n_layers": 2, + "lr": 0.00027717283587404306 + }, + "test_mse": 1.4491142055612715e-13, + "val_mse": 3.7395053463098084e-13, + "test_nrmse_amp_pct": 7.99033120061973, + "test_nrmse_mean_pct": 5.901399841942351, + "val_nrmse_amp_pct": 12.835729422646637, + "val_nrmse_mean_pct": 9.480054040832073 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/split.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/split.csv new file mode 100644 index 00000000..5b3d4b91 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev1/split.csv @@ -0,0 +1,290 @@ +row_index,set +90,test +159,test +103,test +63,test +31,test +213,test +148,test +5,test +278,test +284,test +141,test +214,test +266,test +196,test +195,test +84,test +164,test +267,test +144,test +44,test +92,val +283,val +190,val +41,val +47,val +36,val +124,val +201,val +160,val +271,val +281,val +130,val +39,val +117,val +74,val +75,val +132,val +17,val +123,val +33,val +185,train +111,train +121,train +285,train +118,train +93,train +68,train +18,train +42,train +64,train +10,train +182,train +257,train +273,train +212,train +0,train +227,train +152,train +138,train +149,train +151,train +83,train +25,train +277,train +8,train +119,train +244,train +147,train +71,train +70,train +236,train +65,train +205,train +173,train +43,train +126,train +6,train +54,train +94,train +235,train +61,train +106,train +226,train +128,train +198,train +162,train +150,train +133,train +13,train +204,train +109,train +97,train +166,train +203,train +170,train +45,train +253,train +282,train +197,train +276,train +72,train +219,train +98,train +155,train +242,train +233,train +37,train +28,train +168,train +258,train +192,train +239,train +206,train +222,train +116,train +99,train +223,train +52,train +228,train +186,train +46,train +161,train +91,train +194,train +265,train +60,train +230,train +140,train +218,train +260,train +208,train +102,train +82,train +274,train +50,train +167,train +35,train +122,train +202,train +14,train +252,train +139,train +15,train +89,train +80,train +142,train +216,train +200,train +261,train +53,train +224,train +100,train +225,train +288,train +181,train +32,train +9,train +87,train +247,train +220,train +215,train +131,train +157,train +16,train +105,train +254,train +231,train +77,train +110,train +113,train +30,train +280,train +129,train +286,train +172,train +179,train +1,train +251,train +2,train +269,train +12,train +177,train +262,train +112,train +11,train +189,train +48,train +165,train +180,train +51,train +243,train +88,train +135,train +23,train +248,train +199,train +38,train +178,train +55,train +20,train +137,train +34,train +27,train +114,train +57,train +229,train +153,train +171,train +154,train +136,train +40,train +221,train +275,train +175,train +211,train +22,train +19,train +287,train +250,train +174,train +249,train +108,train +264,train +4,train +217,train +96,train +81,train +79,train +183,train +232,train +145,train +85,train +238,train +3,train +256,train +26,train +234,train +143,train +259,train +158,train +66,train +163,train +246,train +237,train +107,train +209,train +76,train +156,train +210,train +146,train +134,train +67,train +193,train +255,train +245,train +24,train +272,train +59,train +21,train +188,train +62,train +86,train +125,train +101,train +240,train +49,train +58,train +187,train +169,train +279,train +268,train +207,train +241,train +56,train +270,train +73,train +263,train +115,train +191,train +104,train +176,train +7,train +69,train +127,train +78,train +120,train +29,train +184,train +95,train diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/X_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/X_data.csv new file mode 100644 index 00000000..e6b429db --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/X_data.csv @@ -0,0 +1,161 @@ +1,2,2,0,1,1,1,1,0,1,2 +2,1,1,1,1,0,0,1,0,0,0 +0,0,1,2,0,2,2,1,1,0,2 +1,2,2,0,0,1,1,2,1,1,2 +0,2,0,0,2,2,1,2,0,0,0 +1,2,0,2,1,0,0,0,2,0,0 +0,2,2,1,0,0,2,2,1,2,0 +0,2,0,1,1,0,1,2,1,0,2 +0,0,2,2,0,2,1,1,2,1,1 +0,0,2,1,1,1,1,1,1,1,2 +0,0,1,2,0,2,0,0,0,1,1 +1,0,1,0,2,1,1,2,2,1,0 +1,1,2,0,1,0,0,2,1,0,0 +1,0,1,0,2,2,1,2,1,0,0 +2,2,1,2,2,1,0,0,1,2,0 +2,1,2,2,2,0,2,1,1,0,0 +0,1,2,1,0,0,2,2,0,1,2 +2,1,0,1,1,2,0,1,2,0,2 +1,0,2,1,2,0,2,0,1,0,0 +2,0,1,1,1,1,1,0,2,2,0 +2,2,1,0,1,0,2,1,2,0,0 +1,0,0,2,2,1,1,2,2,2,0 +2,2,0,2,2,2,1,2,1,2,2 +2,1,0,1,2,0,2,1,2,0,1 +1,0,1,2,2,0,1,0,0,0,0 +2,0,2,2,1,2,1,0,1,1,2 +2,2,2,0,2,2,2,0,1,2,0 +2,0,1,0,2,0,2,0,0,2,1 +2,0,1,2,1,2,1,1,1,1,2 +0,1,1,1,1,1,1,2,0,0,0 +2,0,1,2,0,1,0,1,1,2,2 +1,2,2,2,1,0,1,0,0,1,2 +2,0,0,0,1,1,0,1,0,0,2 +2,2,1,2,1,2,0,0,1,0,1 +0,2,1,1,2,0,1,0,2,2,1 +2,1,2,0,0,1,2,0,0,2,2 +2,1,2,0,1,0,2,1,1,0,0 +0,1,0,0,2,0,0,2,0,2,0 +1,0,1,2,0,0,0,0,0,1,2 +2,1,0,1,0,0,2,1,2,0,2 +0,0,0,2,2,1,2,0,1,2,2 +2,0,0,1,0,1,0,0,0,0,0 +1,1,1,1,0,0,2,0,2,1,1 +1,2,2,0,1,0,2,1,1,0,2 +1,1,1,2,0,0,0,1,0,1,1 +1,0,1,2,2,0,1,0,0,1,2 +1,0,0,1,1,0,2,1,0,1,1 +2,0,2,0,1,0,0,1,2,0,1 +0,0,1,0,2,2,1,2,2,2,2 +2,1,2,1,1,1,0,1,0,2,0 +0,0,2,2,2,1,1,2,0,0,1 +1,2,0,0,2,2,1,0,1,1,1 +0,0,0,1,0,0,0,0,2,1,2 +0,1,2,0,1,1,2,0,0,2,1 +1,0,2,1,0,2,0,2,0,0,0 +2,1,0,2,2,0,1,2,2,1,2 +1,0,0,0,2,2,1,2,1,1,2 +2,0,2,2,1,1,0,2,0,1,2 +1,1,1,2,0,1,2,1,0,1,0 +0,0,2,2,2,1,1,2,1,1,2 +1,0,2,2,2,0,0,2,1,2,2 +0,1,2,1,0,0,2,0,1,2,2 +0,0,2,1,1,0,2,2,0,2,1 +1,0,1,2,2,0,2,1,0,2,1 +2,2,2,0,0,2,0,2,2,1,2 +0,0,0,0,2,2,0,2,0,1,1 +1,1,1,0,0,1,1,1,1,2,0 +2,0,2,0,1,2,1,2,1,1,1 +1,2,0,0,1,0,2,0,0,1,2 +2,2,2,1,0,2,0,0,2,2,1 +2,1,1,1,1,1,1,1,0,1,0 +0,2,2,2,1,1,0,1,2,1,1 +0,0,1,2,0,1,2,0,0,2,1 +0,2,0,0,1,2,1,2,0,2,0 +2,0,2,1,0,2,2,0,0,0,1 +1,1,0,0,0,2,2,1,1,2,2 +1,1,0,1,0,0,0,0,0,0,2 +1,1,2,1,2,2,0,0,1,1,1 +0,0,2,0,2,0,1,2,2,1,1 +1,0,0,2,2,1,2,0,2,0,1 +2,0,2,2,1,2,1,2,0,1,0 +2,0,1,0,2,0,1,2,1,1,0 +1,2,0,1,0,1,2,2,1,0,2 +2,0,2,2,1,1,0,2,0,1,0 +2,2,0,0,0,1,2,1,2,0,1 +1,1,2,0,2,2,1,1,2,2,2 +1,0,2,1,0,2,1,1,0,1,0 +1,0,2,1,1,2,2,2,0,2,1 +0,2,0,0,0,0,0,1,0,2,2 +1,0,1,2,2,1,2,1,1,1,0 +0,2,1,2,1,0,0,0,2,2,2 +2,1,2,1,0,0,2,2,0,1,0 +1,0,0,0,1,2,2,1,1,0,1 +0,1,0,0,0,2,2,2,0,2,1 +2,2,2,0,1,1,1,0,0,0,1 +1,1,0,2,0,0,0,1,1,2,0 +2,1,2,1,2,2,1,1,2,1,1 +0,2,1,2,0,0,1,0,2,2,0 +2,1,2,2,0,2,2,0,2,1,0 +1,0,0,2,2,2,2,1,2,2,1 +1,0,0,1,2,1,2,2,0,1,0 +0,0,0,2,2,0,0,2,1,0,1 +1,2,2,0,1,0,2,0,0,2,1 +1,0,0,2,2,0,1,2,1,1,1 +0,2,1,1,1,2,2,0,0,1,1 +1,0,0,1,2,1,2,2,0,2,1 +0,1,2,1,1,1,2,1,1,0,0 +1,2,0,1,2,1,0,0,0,2,2 +2,0,0,1,2,0,2,1,0,1,2 +0,1,2,1,0,0,0,1,0,0,1 +0,2,1,1,2,0,2,2,0,2,2 +2,0,2,1,0,2,0,0,2,0,1 +2,2,1,1,0,0,2,2,1,1,0 +1,0,0,1,0,1,0,2,1,0,2 +2,1,0,0,2,2,1,2,2,2,2 +2,1,0,0,2,2,1,1,0,1,0 +0,0,1,2,1,0,2,1,2,1,0 +1,2,2,1,1,1,1,1,0,2,0 +2,2,2,0,2,2,0,2,0,1,0 +0,0,1,2,1,2,1,2,0,1,0 +1,0,1,0,1,1,1,2,1,1,0 +1,0,0,2,2,2,0,0,2,1,1 +2,2,2,0,2,1,0,2,1,2,0 +0,0,2,0,2,2,1,2,1,1,1 +2,1,2,2,1,1,2,0,0,0,0 +1,0,1,1,0,1,0,0,0,2,2 +0,1,1,2,2,0,2,1,0,2,2 +0,0,1,2,1,2,2,0,0,0,1 +1,1,0,0,1,2,2,1,0,0,0 +1,0,0,2,2,1,2,0,1,1,1 +2,1,1,2,2,1,0,1,1,1,2 +1,2,1,0,1,0,1,0,1,1,1 +1,1,1,0,0,0,1,0,0,2,2 +2,1,2,1,0,1,2,0,2,2,0 +0,2,2,0,2,2,0,1,2,0,1 +0,1,0,1,2,0,1,2,2,1,2 +0,0,0,2,1,2,0,0,1,0,2 +2,1,1,2,0,0,1,2,0,1,2 +2,0,2,2,0,1,0,1,0,2,2 +2,2,2,1,0,1,2,2,1,0,0 +0,2,2,2,0,2,1,0,1,1,1 +1,2,1,2,1,1,2,2,2,2,0 +1,2,2,0,0,0,0,1,0,2,2 +0,1,1,2,1,1,1,1,0,0,1 +1,1,0,1,1,2,2,2,0,1,0 +1,1,1,1,1,2,2,2,0,0,1 +2,1,1,1,0,2,0,0,1,0,0 +2,1,2,1,2,0,2,0,1,2,2 +0,2,0,0,2,0,1,0,2,0,1 +2,2,0,0,1,1,2,2,1,0,1 +0,2,2,0,0,1,1,0,2,0,1 +0,0,0,0,1,2,0,1,0,2,0 +2,1,0,1,2,1,0,0,2,0,2 +2,0,2,2,0,1,2,1,2,1,2 +1,0,2,1,1,2,0,2,0,1,0 +0,1,1,1,0,0,0,2,1,2,0 +2,0,1,2,2,0,0,1,2,1,1 +0,2,0,2,1,0,0,2,2,0,1 +2,2,0,1,0,0,1,0,0,0,1 +1,0,0,2,0,1,1,1,0,1,2 +2,2,2,2,0,1,1,0,2,2,1 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/Y_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/Y_data.csv new file mode 100644 index 00000000..42d53e4e --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev2/Y_data.csv @@ -0,0 +1,162 @@ +sim_id,qoi,qoi_err,qoi_kla,qoi_kla_err,qoi_sum,qoi_sum_err,qoi_sum_kla,qoi_sum_kla_err +0,20.699746947105627,0.522025319804726,1.3268119663586066e-10,3.346076852190392e-12,22.20892850300179,0.5145780355640763,5.622762991776892e-05,1.3027870004443811e-06 +1,3.0462209853016744,0.07504345536944568,1.1021016117077703e-10,2.7150201351067007e-12,9.879101087064722,0.22626073960354154,5.942203834610984e-05,1.3609410640149197e-06 +2,1.5765184147568274,0.099492277029662,3.7142834012118327e-11,2.344041843475984e-12,9.869221388144348,0.2217274526875399,4.7903901539592056e-05,1.076235869521374e-06 +4,14.955183141797058,0.4554825133232335,9.585970307191129e-11,2.919550905370353e-12,23.085415059910748,0.5785598314518794,5.84466816843373e-05,1.464773417175136e-06 +5,1.1341303442039619,0.02639246016713552,5.840167123820818e-11,1.359071106531785e-12,8.532752361825633,0.13556009612388278,6.123085081699178e-05,9.727763880308605e-07 +6,2.6263406106285716,0.06647947911171925,1.352425497306619e-10,3.4233390076862007e-12,7.6797069655337955,0.18356847907359283,5.510941480560249e-05,1.3172835244758623e-06 +7,2.3103692320170888,0.09229388561568158,5.4432387409147404e-11,2.174447472598249e-12,11.521969372356082,0.29850117980934243,5.592612277603266e-05,1.4488854371424347e-06 +9,5.829615667273074,0.15899832360289934,1.3734596745873258e-10,3.746006568177748e-12,11.897164487643233,0.3045587396664628,5.774727038218473e-05,1.4782880328370266e-06 +10,1.206735662113046,0.02241390616495414,1.6456095907142788e-11,3.0565549779006296e-13,11.615009468570765,0.18182134376888226,4.2892059458645325e-05,6.714322453966383e-07 +11,8.877124539448113,0.2526620736384187,5.6900575127059215e-11,1.6195128545211544e-12,23.048997433070326,0.5697633351842403,5.8354481050245845e-05,1.442502817863547e-06 +12,0.2116773999206866,0.004057306191109097,1.0900258374920325e-11,2.0892965335847827e-13,5.641403764565511,0.09069921559725906,4.048259409835247e-05,6.508556528298038e-07 +15,11.304011041804424,0.33373751364173854,1.5415131546945144e-10,4.5511346865391805e-12,17.507062896087504,0.49733467859813657,6.465031169486953e-05,1.8365640301219707e-06 +16,3.7927272013374704,0.10087501418885483,1.3721823803722886e-10,3.649588007303531e-12,9.717382740460334,0.2401276797618196,5.8449314855121856e-05,1.4443496499720653e-06 +17,6.726476802764819,0.17734198196480866,1.584760500166229e-10,4.178183858799621e-12,12.707748911032978,0.3231833123700745,6.168174047492761e-05,1.5686892571611237e-06 +18,13.1354146039178,0.37373109318701203,1.7912592586887367e-10,5.096521892285206e-12,17.250022112322092,0.4713108929625283,6.370110816865496e-05,1.7404630543763324e-06 +20,10.589176463801442,0.28287486766904535,1.4440321036395582e-10,3.857527463285391e-12,15.972832688093094,0.39543940435139224,5.898468629192256e-05,1.460283824954797e-06 +23,3.4308337387793193,0.08496454263425353,8.083057380735472e-11,2.0017678667371643e-12,11.014540946581706,0.24721138830856684,5.346313191866337e-05,1.199931538593856e-06 +24,12.170297434787397,0.33599269125810927,1.6596474944199792e-10,4.58188825029064e-12,16.558065938529595,0.42638910260725243,6.114584328814785e-05,1.5745752761576638e-06 +25,3.6895700182889466,0.09700147447393301,1.3348608284023765e-10,3.509446031127897e-12,9.6415117537299,0.23565248325722585,5.799295668668515e-05,1.4174316853743628e-06 +26,11.901551417615327,0.2513280129483239,1.6229989517595695e-10,3.4273271378654927e-12,18.189756682225305,0.3536362644937482,6.717137227070279e-05,1.3059126400488073e-06 +28,6.933637492082713,0.19861806714356792,1.6335676390329544e-10,4.679449241231496e-12,12.879824142462475,0.34299147568730876,6.251697102559303e-05,1.664835475266766e-06 +30,10.72485936399962,0.325737890576436,1.4625350027527112e-10,4.442044883963916e-12,17.66957306704189,0.4945436573513642,6.525043144342209e-05,1.8262573117838596e-06 +31,21.25566149912942,0.8457221718756711,3.9935684730656154e-11,1.5889646166568804e-12,30.792914594700825,0.5448242826816098,4.22079298858958e-05,7.467920924742941e-07 +32,9.023707907554027,0.23041498962014592,1.230551208743849e-10,3.1421389842684747e-12,15.076137155901634,0.36600159287707124,5.567335722346126e-05,1.3515754874002667e-06 +33,2.4141097738983457,0.06549825479744403,1.2431379207592406e-10,3.372811177130928e-12,8.103447262727446,0.19414670799756592,5.815016616873304e-05,1.3931926703711397e-06 +34,8.58057993498525,0.2100379209430356,5.499978419543279e-11,1.3463006477713309e-12,21.300301491816157,0.41733506041290386,5.3927206347961085e-05,1.0565913317129537e-06 +35,8.19402001165581,0.21875934591453763,1.1174077840915016e-10,2.9831925675059927e-12,17.15714981221738,0.444127267619809,6.335814879686831e-05,1.6400790232982013e-06 +36,1.3225728000995742,0.04440414897125824,4.784976619048802e-11,1.6065112982834202e-12,7.823277566887705,0.1512777997721976,4.705641699543121e-05,9.099244105004746e-07 +37,24.972102807831043,0.8207270783529736,4.6918229784080596e-11,1.5420031684358777e-12,30.544119793277456,0.5543736268774526,4.1866905888704194e-05,7.598813984735043e-07 +39,3.918252355842555,0.11968923512071934,9.231417488458895e-11,2.819882942521926e-12,12.10873475564351,0.3260055606331857,5.8774204595080796e-05,1.5823880782307697e-06 +40,1.7648598264518103,0.058197689349314456,2.4067161913404747e-11,7.936342544393154e-13,11.967123395629981,0.2214561920967044,4.4192350391382683e-05,8.177963336663425e-07 +41,10.600964877198429,0.2696231347806151,1.4456396724197174e-10,3.676815315928435e-12,15.656551478117692,0.36591396750912225,5.7816718852782764e-05,1.3512519032910736e-06 +42,1.2081035202675312,0.03695895199746924,6.221089506721569e-11,1.9031891273685384e-12,8.209010570114794,0.17328530172511664,5.890768622987172e-05,1.2434916601805614e-06 +43,9.815001674666489,0.25365701187473316,1.3384589016310024e-10,3.4590873925285784e-12,15.620100976915849,0.3808148445469073,5.768211396338706e-05,1.4062780576493686e-06 +44,11.361798821725879,0.1798884518554449,1.549393599262567e-10,2.4531152175755653e-12,17.76683233903567,0.25623029393976143,6.560959172179411e-05,9.462105935005135e-07 +45,7.137358365306081,0.19810994800333703,1.6815643587803201e-10,4.667477946764798e-12,12.710247149689124,0.3344047685541384,6.169386670239667e-05,1.623156731167845e-06 +47,6.570357090071081,0.1719971473994165,1.5479786363125336e-10,4.052259352590443e-12,12.702668603615972,0.3172902773377207,6.165708133145363e-05,1.540085240822737e-06 +48,2.100567204050115,0.04239787260274448,1.4600231410610167e-10,2.946912386921514e-12,6.857798874082252,0.13297752263780394,5.717370326305106e-05,1.1086381446214274e-06 +49,1.321605092849144,0.03859371364025942,6.805562137036811e-11,1.987370642705076e-12,7.033687581533451,0.14413270981953316,5.0473593321993224e-05,1.0342932772458933e-06 +50,5.749611481119033,0.17238435548380238,1.3546106590217945e-10,4.061381993440582e-12,12.240408894549223,0.3339864485160489,5.9413333577987907e-05,1.6211262587026723e-06 +52,1.0243800800560219,0.023379045660657637,2.4134433838153876e-11,5.508112093174077e-13,9.809014008332678,0.16665716020507684,4.76116629035667e-05,8.089319197025576e-07 +53,0.572170433293632,0.01606700364649783,5.161761240213892e-11,1.4494638632665393e-12,6.30738769540545,0.15820154812348988,5.9908131803180244e-05,1.50261243705584e-06 +57,8.047627843943523,0.16530997893130409,1.0974444501158441e-10,2.2543104930412314e-12,15.550477942764111,0.2736644253628239,5.7425009084804205e-05,1.0105915824896182e-06 +58,12.082082668136604,0.3580585484727136,1.647617762424741e-10,4.882797450206889e-12,16.289651899664324,0.44757445017260994,6.01546404014264e-05,1.6528088057888017e-06 +59,3.810522296314472,0.10700300658579928,8.977605057496566e-11,2.5209949145846217e-12,11.245697983006874,0.2606813407848263,5.4585137704802856e-05,1.2653129139084125e-06 +60,5.823786652877734,0.14973958044000077,1.3720863565726348e-10,3.5278702261373682e-12,11.454410199085972,0.2749325328223503,5.5598199345910214e-05,1.3344863245558286e-06 +61,3.903456366544696,0.09490292198993255,9.196558081264348e-11,2.235916460197788e-12,10.384540427521506,0.22684319206224374,5.040519228721023e-05,1.1010669942252752e-06 +62,2.1023368341023643,0.043724461243104945,7.606108771591106e-11,1.5819206646601652e-12,8.577965066221855,0.1657474761073444,5.159580460531568e-05,9.969584073889712e-07 +65,9.308262850030102,0.22369058484290183,1.269355598655641e-10,3.050439172288456e-12,16.86640583056452,0.3607910032846275,6.228448503014001e-05,1.3323337567490776e-06 +67,13.484259347058208,0.39724215609388747,1.8388307555549465e-10,5.417139163729897e-12,17.54123050649974,0.4939812061051471,6.477648629515118e-05,1.8241802828755734e-06 +68,1.0027586739019316,0.02675867940267841,2.3625032622721564e-11,6.304355078468769e-13,9.922738787944084,0.2084782803631077,4.8163667953763426e-05,1.0119261310375331e-06 +69,2.623140916317064,0.08252377804277308,3.5771428514764686e-11,1.125365933893486e-12,11.680709368098844,0.2179174677648927,4.31346768985183e-05,8.047284857761883e-07 +73,0.13431882471251483,0.0026954279462518232,9.335982700990944e-12,1.873487854873252e-13,4.849661344679009,0.0906555737142758,4.043179198309317e-05,7.557986090194039e-07 +74,4.9064781254020975,0.11521766428039115,1.1559681176438233e-10,2.714532564773367e-12,11.3577671975315,0.2456737246555779,5.512910693762177e-05,1.1924679210932242e-06 +75,2.324126503379287,0.049238125112136,1.1968013323998938e-10,2.535501129279974e-12,8.452269667414395,0.1457913573515638,6.06533084192979e-05,1.0461956977548163e-06 +76,19.50815016524132,0.531304687793951,1.2504330232927702e-10,3.4055557365533183e-12,25.12744667638502,0.6245416294191704,6.361661141704218e-05,1.5811881988736026e-06 +79,3.7987285548681666,0.1151604677514204,5.180276293040916e-11,1.5704281903050833e-12,14.547597378797075,0.3394375405636293,5.3721558595386813e-05,1.2534794062585502e-06 +80,9.411045893738818,0.19768752419729246,1.2833719832548173e-10,2.695838835114015e-12,16.48513329930951,0.3238007913022165,6.087651671610815e-05,1.195735813990905e-06 +82,8.711357751300618,0.22191923388507775,1.1879564267293161e-10,3.0262834753774616e-12,14.74422828995715,0.3362410928362221,5.4447679782935145e-05,1.2416755216060202e-06 +84,5.286002259975037,0.138971338041154,3.388220676901098e-11,8.907782060802103e-13,19.5708605342915,0.37507255872876716,4.9548680559540635e-05,9.495929096494379e-07 +86,6.346790162765942,0.16831073984535516,8.655034517609743e-11,2.2952314881813175e-12,15.671130074370076,0.348968140753947,5.787055501496912e-05,1.2886741346752905e-06 +87,4.141491469544869,0.11621333384982241,9.75736970631176e-11,2.737990580239843e-12,11.810885958822428,0.29722801892413026,5.7328485785762864e-05,1.442705679948953e-06 +88,4.150705911224189,0.0904183054558466,9.779078966070845e-11,2.1302587269312324e-12,10.426037138407258,0.20491552824773168,5.060661189811447e-05,9.946330012319781e-07 +89,7.6911440302016105,0.190321607804451,1.0488312210399375e-10,2.59539079647939e-12,14.216430293171516,0.32388310264932246,5.2498620433706125e-05,1.1960397737148541e-06 +90,3.6164306114007365,0.0748537280390768,4.9316790904314377e-11,1.0207704918971837e-12,14.351610332398113,0.22308224423411407,5.299781565509545e-05,8.238010496393534e-07 +91,0.12370681553811537,0.0018614545519007905,6.370241957470715e-12,9.585499260378024e-14,5.2438132392649175,0.07844663793087157,3.762949293022589e-05,5.629314151229235e-07 +92,11.62733162040377,0.32513780200560466,1.5856039570479164e-10,4.4338615451654774e-12,17.45095564929202,0.4537489202020626,6.444311810213924e-05,1.6756099689294641e-06 +93,5.54186723227859,0.1421551176541946,3.552224953136513e-11,9.111855895899283e-13,20.651266255862467,0.380827467205199,5.2284006248209764e-05,9.641629442065882e-07 +94,2.5830093417750266,0.06789940105327652,9.345148547504444e-11,2.45655321050215e-12,8.817777656591137,0.20838237224477865,5.3038259017179805e-05,1.2534040507895546e-06 +95,7.5649992960275565,0.17305736922864706,1.0316290337898555e-10,2.3599606506415884e-12,13.577739049760844,0.27762854409432103,5.014005313778647e-05,1.0252303349209485e-06 +96,20.264216468192693,0.5420562293688529,1.298895341866534e-10,3.474470934822849e-12,24.208699304609738,0.5947075916138637,6.129056540552496e-05,1.5056556357008018e-06 +97,14.639911605984942,0.3854110620365902,9.383887621051962e-11,2.470407056681358e-12,23.883431077664486,0.5713603565954053,6.046706503233484e-05,1.4465460899151025e-06 +98,1.055843601967849,0.028002934558406658,3.819968880383979e-11,1.01312673935017e-12,9.661724309179768,0.18794611543477818,5.811453366368549e-05,1.1304815271965252e-06 +100,3.5719681487007087,0.08015727943154177,1.292313290749145e-10,2.9000347496758716e-12,9.475093772173649,0.19776844106680225,5.699196529870695e-05,1.189562066769168e-06 +101,0.7865358064139175,0.020813163165064204,2.8456319708464723e-11,7.530058013122747e-13,8.179465144497192,0.16216324378120908,4.919885806789497e-05,9.753995247462595e-07 +102,8.809072885854842,0.2393702345252385,1.2012817124240945e-10,3.2642604841602627e-12,16.02982326544714,0.37955744592685314,5.919514180970691e-05,1.4016347195168852e-06 +103,1.8299929819663987,0.04599739638257021,1.2719574366325783e-10,3.1971013534532187e-12,6.989606640054441,0.16092271537541603,5.827258883039998e-05,1.3416181638613733e-06 +105,23.724809242245275,0.5939922264403502,1.5207123489298407e-10,3.807370186596638e-12,23.720532269957666,0.5749896814191607,6.0054644678035833e-05,1.4557346613548962e-06 +106,1.0262497757768767,0.021440329913887973,2.4178483879323242e-11,5.051349909410552e-13,10.397959880755714,0.20267375866008044,5.047032858526295e-05,9.837517467360245e-07 +107,4.590278693714299,0.1117359973252791,1.0814714119041358e-10,2.6325043608650085e-12,11.667638569217901,0.2643753063103985,5.6633181812172595e-05,1.2832429373006565e-06 +108,7.990482478046253,0.19269705632164372,1.089651613731434e-10,2.6277844793361754e-12,15.771128102659226,0.366919846746604,5.8239828950223374e-05,1.354966428137834e-06 +109,4.131587336079551,0.1208852243812922,9.734035521410857e-11,2.8480604969076796e-12,12.235660541542172,0.32410655667245036,5.939028567108885e-05,1.573170563476884e-06 +110,11.974643663834982,0.3317739998637638,1.6329664463622038e-10,4.524358509215099e-12,17.057255889049266,0.446340001553176,6.298925849127662e-05,1.6482502177199182e-06 +111,7.009399022632262,0.12250016256894548,1.6514170845412708e-10,2.886108504769779e-12,14.634997753120423,0.23208437848916258,7.103635269949606e-05,1.1265070240878113e-06 +112,1.5675308438137434,0.035918774925056,3.69310864977307e-11,8.462477079062705e-13,10.133011148334607,0.1943358724872508,4.918430231310059e-05,9.432807447630254e-07 +113,98.91350926923914,3.0242475086972513,1.8584124864464788e-10,5.682034106149612e-12,54.084718620611014,1.5053698681452876,7.413406712584054e-05,2.0634144671646934e-06 +114,6.057298213391624,0.1482306210033669,1.4271017687017042e-10,3.492319082821094e-12,12.935487457034288,0.31404147451751413,6.278715338673569e-05,1.524315979264109e-06 +116,16.422744622920362,0.4102434902938302,1.0526647580946718e-10,2.629577907869064e-12,20.0109130907653,0.4629800345852601,5.066278709113258e-05,1.1721533551841126e-06 +117,0.6695112908435135,0.01736010585505986,4.653514421954392e-11,1.206633914439214e-12,6.14756161842107,0.11891281846611759,5.125243102291554e-05,9.913802259277705e-07 +118,22.079192232097068,0.6808418345956829,1.4152316226829326e-10,4.36405863147719e-12,25.304727621366872,0.7302651351493207,6.406544375483272e-05,1.8488545161229025e-06 +119,4.7601834520199,0.1259235605765293,1.1215010406485682e-10,2.9667639000094645e-12,11.972699586221838,0.2617544608249628,5.8113907907626796e-05,1.2705216999095052e-06 +120,3.422863889724437,0.11573452516997011,8.06428038594897e-11,2.7267098294710313e-12,11.774280566161153,0.28911662203104166,5.7150808028126356e-05,1.4033340271271973e-06 +121,3.689511244090249,0.0968616653065597,8.692502559054049e-11,2.2820645279239904e-12,11.396872147827914,0.2588954832402421,5.531891720752726e-05,1.2566445966053282e-06 +122,1.2670749210447911,0.03982965087989824,4.5841891435586486e-11,1.4410091315263763e-12,7.8030896330404005,0.13068404760912983,4.693498811536491e-05,7.860545642626913e-07 +123,3.1522080632475094,0.07524309437571741,7.42661421932923e-11,1.7727301732149573e-12,10.834327219633673,0.2228147447735132,5.258839818606122e-05,1.0815134417060086e-06 +124,3.4305819520655274,0.0921098537011424,1.2411607424302686e-10,3.3324705837742834e-12,9.88298793294515,0.2413362082065652,5.944541743703268e-05,1.4516188562454977e-06 +125,5949.4327257980185,234.66073300260106,2.6148968104697916e-10,1.0313816973007272e-11,534.9555705313503,20.951453844398497,0.00011215204910023849,4.3924180057503616e-06 +126,2.594012458617355,0.06636115452494357,9.384957079920924e-11,2.4009005235177423e-12,9.93677737889465,0.23079333552983067,5.976895692811949e-05,1.3882042844069362e-06 +127,11.619385538911647,0.2946478126127506,1.5845203690942394e-10,4.018073582552771e-12,17.44818546782052,0.41954206365416935,6.443288851761254e-05,1.5492904443120207e-06 +128,12.627653106543557,0.3465837792850204,8.09407058965618e-11,2.2215320226916112e-12,21.78121975115624,0.473954868099975,5.514477499223004e-05,1.1999389775431558e-06 +130,6.522056333513535,0.13253922660853523,1.5365989596459787e-10,3.122629233857651e-12,13.974001570357308,0.2710756130666837,6.782796420463311e-05,1.315765343753706e-06 +131,0.8772212005111121,0.017185669733111416,4.517221846808402e-11,8.849704353384639e-13,6.776193056550139,0.11764312803737806,4.862581809855671e-05,8.442045993599757e-07 +132,4.964940242474994,0.10135861586313384,1.169741815764202e-10,2.38801285761267e-12,10.923244227033297,0.20825943320583024,5.301998965929642e-05,1.010863875742801e-06 +133,2.1736661909537704,0.05421587533898946,2.964200065691982e-11,7.393347787723806e-13,11.6117533270884,0.21253410243676177,4.288003512502208e-05,7.848487236198085e-07 +135,5.82793543903192,0.1341020488573843,7.947479094592246e-11,1.8287320458256233e-12,13.696503459261896,0.2820544628715573,5.0578627781649706e-05,1.041574423294632e-06 +136,9.487693118939124,0.17349428780831938,1.2938242632973145e-10,2.3659188413441286e-12,17.51356335344724,0.24012473152620475,6.467431668665232e-05,8.867357611702902e-07 +137,7.487417746036239,0.20707998222389698,1.021049334092942e-10,2.823922547471347e-12,15.411858731366754,0.39403762627726,5.6913114241242465e-05,1.4551073190168628e-06 +138,7.0655872708003615,0.1898314677074512,1.664655057251291e-10,4.472436623217138e-12,12.259354679631894,0.3067049295142036,5.9505293924959235e-05,1.4887053565142945e-06 +139,3.691169318085947,0.08905288277137473,8.696408999030795e-11,2.098089316380108e-12,10.54084273766798,0.23538072096017135,5.116386316514817e-05,1.1425070365469164e-06 +140,1.6831924230895634,0.041269875302718514,8.667544245259728e-11,2.1251787096693153e-12,6.910600868455261,0.1495001114121594,4.9590325657313885e-05,1.0728096372307066e-06 +142,13.949249074467955,0.3578115597366202,1.9022408042184432e-10,4.879429319230252e-12,17.16741529141435,0.41006091163541697,6.33960567216178e-05,1.5142783215804345e-06 +143,2.1671283981496146,0.04732116282857885,7.840520170112279e-11,1.7120468355609854e-12,9.113183502623906,0.19246046693340446,5.4815102671341836e-05,1.1576350077984749e-06 +144,5.4105000299301516,0.19618937690492036,7.378227908026197e-11,2.6754087938834016e-12,14.91089135001539,0.37161776723606543,5.506313534197736e-05,1.372314969807744e-06 +145,3.9971966928532474,0.07872972920699675,1.4461580234089641e-10,2.8483869652219158e-12,10.385832110727069,0.1872631990434701,6.246998675319897e-05,1.126373836866143e-06 +146,22.856835145440883,0.552272116346571,1.4650769740362053e-10,3.5399527358580772e-12,25.803449906206506,0.5843673777639502,6.532808808806594e-05,1.4794767238148679e-06 +147,5.131361271786244,0.13506011076278684,1.2089506727009085e-10,3.1820213606767095e-12,12.406285831948182,0.30671771826502353,6.0218478371067746e-05,1.4887674307649877e-06 +148,5.338262492495086,0.16021319985880775,1.2576966792107018e-10,3.774629099101546e-12,12.348509133006264,0.33997867188016556,5.9938037879633506e-05,1.6502117214258299e-06 +149,22.752822852487817,0.6156825797602532,1.4584099847336334e-10,3.946400969982219e-12,25.216548850639864,0.6275099297841371,6.384219645650527e-05,1.5887032144238148e-06 +150,4.127823933611996,0.10438225705690558,9.725169097747031e-11,2.4592499995381958e-12,11.938439713529357,0.2920335819702755,5.7947615392766537e-05,1.4174925782477018e-06 +152,3.733949564136969,0.10025672506987829,8.797199414149335e-11,2.362052266373118e-12,13.334072799398605,0.1948046954205631,6.47218341851421e-05,9.455563491497852e-07 +153,10.87219346009702,0.31580728149356524,1.4826267569309827e-10,4.306622461184724e-12,17.621182043483113,0.4839387982293475,6.507173236518693e-05,1.7870955468141604e-06 +155,3.9554164040649225,0.10033489247116076,9.3189761419726e-11,2.3638938954321695e-12,10.988064132884697,0.24396055968674965,5.33346169501019e-05,1.1841524443677723e-06 +157,11.520853706468461,0.2958145284028364,1.571083712311696e-10,4.033983932787248e-12,16.8598292206881,0.40447592375015995,6.226019883878947e-05,1.4936540049460966e-06 +158,1.2890594175182088,0.025551011290756754,1.757873415917831e-11,3.484357888196659e-13,12.043350209261444,0.20474117522843005,4.4473841769540464e-05,7.560708999242295e-07 +159,1.215240514447797,0.03500604067199795,2.8631112894357215e-11,8.247436540739918e-13,11.46823388876018,0.26899075795000116,5.566529774072441e-05,1.3056457320307332e-06 +161,3.66245638149296,0.08747374418969452,1.3250513018164003e-10,3.1647393590544625e-12,9.347294818808152,0.2034514957094254,5.622326427808125e-05,1.223745204658096e-06 +162,13.854112361084047,0.24681299702573267,1.8892671290561404e-10,3.3657564638667414e-12,19.06692418004731,0.3228269026529485,7.041058798232674e-05,1.1921394251986305e-06 +163,0.3743710239658055,0.009398835528604795,1.3544483847811472e-11,3.4004334699004863e-13,7.274242851625962,0.14598506382373724,4.375401507544453e-05,8.780890071474298e-07 +164,3.527142488638985,0.10080516906262824,1.2760956744440092e-10,3.647061059108334e-12,10.130109660058572,0.26309183832466376,6.093183574753649e-05,1.582477309453247e-06 +165,1.9347760205878368,0.05826660304944253,2.6384286746481896e-11,7.945740210966892e-13,11.100999543263187,0.18719044062011458,4.0993916846951975e-05,6.912593165524593e-07 +166,94.502962057401,2.7333689031592545,1.7755459855366895e-10,5.135523879185283e-12,51.22110569521225,1.4206328389768863,7.020890522203899e-05,1.9472651945576286e-06 +167,8.951364490733976,0.18946328798866355,1.220685830666376e-10,2.5836859991415784e-12,14.833513108526885,0.2986839003834352,5.4777391928172724e-05,1.102983828189271e-06 +168,3.949437584511699,0.09974746026989537,1.4288791094534722e-10,3.6087938890244666e-12,9.663141186290515,0.2259237187415257,5.812305605040253e-05,1.3589139095017143e-06 +169,14.399199890710063,0.4287184010513832,1.9636000004332757e-10,5.84637659647585e-12,18.012025104034773,0.5157328699265914,6.65150428224114e-05,1.9045051142199512e-06 +170,1.2058392520720425,0.023918152518625686,2.8409618866261143e-11,5.635125874959183e-13,9.312549224742646,0.16499372532742262,4.5201888190256975e-05,8.008578257528871e-07 +171,8.590658849408383,0.24147560895562267,1.1714968768211137e-10,3.2929711990538457e-12,18.857906496518872,0.4705972834245901,6.963872469522763e-05,1.7378278266877936e-06 +172,1.482503834770882,0.051664362414061096,7.634104951524628e-11,2.660439424654185e-12,7.470539704696282,0.16008169350415355,5.360843496444719e-05,1.148742847832154e-06 +173,4.812948390315452,0.15724260536426274,6.563354576633035e-11,2.1442967799860285e-12,14.437140282529581,0.32999214636541335,5.331366118010237e-05,1.2185993305550848e-06 +175,5.9813821289086135,0.1370646732609571,1.4092159156683935e-10,3.2292489406703793e-12,12.542318825549362,0.2659766917725072,6.087876472026969e-05,1.2910158531857383e-06 +176,7.731829061341249,0.23362292681077684,1.054379386593196e-10,3.1858852065997877e-12,15.663035738089455,0.3537170792607393,5.78406640469653e-05,1.306211074998785e-06 +177,1.4917604400849813,0.028229046763573445,2.034294141066023e-11,3.8495580721891805e-13,11.642034358986923,0.19101203598677932,4.299185732878309e-05,7.053717542832086e-07 +178,85.97128814958492,2.612092328343185,1.6152507028962857e-10,4.907666338609694e-12,51.75715484406759,1.4621540639265738,7.094366928980209e-05,2.004178449809758e-06 +179,3.617307854336876,0.09610825822824816,1.30871688164163e-10,3.4771300943513183e-12,9.536616143417293,0.23494232000073906,5.736201766244281e-05,1.4131601090854543e-06 +180,7.113082284025993,0.18525807382922965,9.700016981168194e-11,2.526340045408466e-12,14.887849320853821,0.3454640850170581,5.497804540633047e-05,1.275734308092459e-06 +181,11.922984883174088,0.31188114283837765,1.6259218053367043e-10,4.253082225490945e-12,17.3089416923462,0.42096005670615927,6.391868711276437e-05,1.5545268237555264e-06 +182,21.12862921345938,0.5246982681993735,1.35430245330085e-10,3.363209911471455e-12,23.425190681186454,0.5471672217436202,5.9306911281059555e-05,1.3852949296124627e-06 +183,3.2827002671664074,0.0833046829221397,1.1876581751149124e-10,3.0139056156728147e-12,9.454638287790242,0.22769885263228068,5.686892704384343e-05,1.3695912042488617e-06 +184,25.588237678935535,0.6590010729462601,1.6401543524416247e-10,4.224063773435578e-12,25.547079433049998,0.6444504832101191,6.467901996027499e-05,1.6315925965702378e-06 +185,1.2958529302382558,0.027733553862182347,6.672952230648675e-11,1.4281302745863205e-12,7.4293192357834075,0.14328328064319618,5.3312637751090463e-05,1.0281977923261303e-06 +186,4.36893771342108,0.09782933500365351,5.957863041728459e-11,1.3340858067732396e-12,14.120931696053482,0.27700406377171444,5.214596196047048e-05,1.022924243474143e-06 +187,2.517237729364589,0.05440792290206276,9.107191418103571e-11,1.968440893564645e-12,9.109365215963692,0.17185665352860285,5.479213591252531e-05,1.0337046428997312e-06 +188,1.0160955805943594,0.03389704262534654,7.062487915067674e-11,2.356052505985801e-12,8.547089044145986,0.21649371019347588,7.125737277986328e-05,1.8049154433834049e-06 +189,7.5882467834672624,0.19501317764064693,1.7877938378841553e-10,4.59451790697894e-12,12.897732347227624,0.31100304824394914,6.260389509427905e-05,1.5095678590702249e-06 +190,6.209448035202119,0.16500267231467733,3.9801307729687e-11,1.0576338025193577e-12,21.31242751969843,0.4077226680005298,5.395790656074683e-05,1.032255082267713e-06 +192,7.304990600082542,0.19470046948398234,1.7210585714557132e-10,4.587150486792865e-12,13.550668008223546,0.3366588327043391,6.577315881804018e-05,1.6340976590615626e-06 +193,2.4184283717473543,0.07007455627548315,8.749706012955311e-11,2.535248815145898e-12,9.830544468177333,0.2342517479174656,5.912997400270702e-05,1.4090063688015204e-06 +194,2.830484119699348,0.07152262528363372,3.8598940596365365e-11,9.753446576171983e-13,14.024790453058147,0.2586151146128142,5.179093031610185e-05,9.550172905922001e-07 +195,1.6293941099183733,0.03734825421950925,5.895034828017222e-11,1.3512339221643428e-12,8.53145235185071,0.19187682450668045,5.131603423410809e-05,1.154124443182386e-06 +196,0.7724738742813941,0.021453045470046176,3.977828913572195e-11,1.1047175496299382e-12,6.707988415833038,0.14149007884232853,4.813638299749212e-05,1.015329813245343e-06 +197,3.8709214984837534,0.10629974371909993,9.119905810116103e-11,2.504426015194071e-12,11.16969380065889,0.27319368233115565,5.421622341440777e-05,1.3260461728858648e-06 +199,16.78271234089075,0.41225535335983904,1.0757379635545425e-10,2.6424735482550352e-12,21.82205620862171,0.4929199351868104,5.524816301568056e-05,1.2479539358037255e-06 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/X_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/X_data.csv new file mode 100644 index 00000000..53023e58 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/X_data.csv @@ -0,0 +1,148 @@ +2,1,1,1,1,0,0,1,0,0,0 +0,0,1,2,0,2,2,1,1,0,2 +1,2,2,0,0,1,1,2,1,1,2 +0,2,0,0,2,2,1,2,0,0,0 +1,2,0,2,1,0,0,0,2,0,0 +0,2,2,1,0,0,2,2,1,2,0 +0,2,0,0,2,1,0,2,1,1,0 +0,2,0,1,1,0,1,2,1,0,2 +0,0,2,1,1,1,1,1,1,1,2 +0,0,1,2,0,2,0,0,0,1,1 +1,1,2,0,1,0,0,2,1,0,0 +1,0,1,0,2,2,1,2,1,0,0 +2,2,1,2,2,1,0,0,1,2,0 +2,2,0,2,2,2,1,0,0,2,2 +2,1,2,2,2,0,2,1,1,0,0 +0,0,1,0,1,0,1,0,1,0,2 +1,0,0,0,2,1,1,0,0,2,0 +0,1,2,1,0,0,2,2,0,1,2 +1,0,2,1,2,0,2,0,1,0,0 +2,0,1,1,1,1,1,0,2,2,0 +1,2,0,2,0,1,0,0,1,1,2 +2,2,1,0,1,0,2,1,2,0,0 +1,0,1,2,0,1,0,0,1,1,2 +2,1,0,1,2,0,2,1,2,0,1 +1,0,1,2,2,0,1,0,0,0,0 +2,0,2,2,1,2,1,0,1,1,2 +2,0,1,0,2,0,2,0,0,2,1 +0,0,0,0,0,1,2,1,0,2,0 +0,1,1,1,1,1,1,2,0,0,0 +2,0,1,2,0,1,0,1,1,2,2 +2,0,0,0,1,1,0,1,0,0,2 +0,2,1,1,2,0,1,0,2,2,1 +2,0,0,1,0,0,1,2,0,2,1 +2,1,2,0,1,0,2,1,1,0,0 +0,1,0,0,2,0,0,2,0,2,0 +1,0,1,2,0,0,0,0,0,1,2 +0,2,0,0,0,0,0,1,2,0,0 +0,0,0,2,2,1,2,0,1,2,2 +2,2,2,0,1,1,0,1,1,1,2 +1,1,1,2,0,0,0,1,0,1,1 +1,0,1,2,2,0,1,0,0,1,2 +1,0,0,1,1,0,2,1,0,1,1 +2,0,2,0,1,0,0,1,2,0,1 +2,2,1,0,2,2,1,0,0,1,1 +0,2,1,2,2,0,2,0,1,1,2 +0,0,2,2,2,1,1,2,0,0,1 +1,2,0,0,2,2,1,0,1,1,1 +1,2,1,2,2,0,2,1,2,0,1 +1,1,1,1,0,0,0,0,1,1,2 +0,0,1,0,1,1,2,2,1,1,0 +0,0,0,1,0,0,0,0,2,1,2 +0,1,2,0,1,1,2,0,0,2,1 +1,0,2,1,0,2,0,2,0,0,0 +2,2,2,0,0,1,1,0,0,2,2 +0,1,0,1,0,0,1,1,0,1,0 +1,0,0,0,2,2,1,2,1,1,2 +2,0,2,2,1,1,0,2,0,1,2 +2,1,2,0,1,2,1,2,1,1,1 +1,1,1,2,0,1,2,1,0,1,0 +0,1,1,1,0,0,2,2,2,1,2 +1,0,2,2,2,0,0,2,1,2,2 +0,1,2,1,0,0,2,0,1,2,2 +0,0,2,1,1,0,2,2,0,2,1 +1,0,1,2,2,0,2,1,0,2,1 +2,2,2,0,0,2,0,2,2,1,2 +0,0,0,0,2,2,0,2,0,1,1 +1,1,1,0,0,1,1,1,1,2,0 +1,2,0,0,1,0,2,0,0,1,2 +2,2,2,1,0,2,0,0,2,2,1 +2,1,1,1,1,1,1,1,0,1,0 +0,2,2,2,1,1,0,1,2,1,1 +0,0,1,2,0,1,2,0,0,2,1 +1,2,2,1,0,0,0,1,2,1,1 +0,2,0,0,1,2,1,2,0,2,0 +2,0,2,1,0,2,2,0,0,0,1 +1,1,0,1,0,0,0,0,0,0,2 +0,2,1,0,0,2,0,1,1,2,2 +1,1,2,1,2,2,0,0,1,1,1 +1,0,0,2,2,1,2,0,2,0,1 +2,0,2,2,1,2,1,2,0,1,0 +2,0,1,0,2,0,1,2,1,1,0 +1,2,0,1,0,1,2,2,1,0,2 +2,0,2,2,1,1,0,2,0,1,0 +2,2,0,0,0,1,2,1,2,0,1 +1,0,2,1,0,2,1,1,0,1,0 +0,2,0,0,0,0,0,1,0,2,2 +0,2,1,2,1,0,0,0,2,2,2 +2,1,2,1,0,0,2,2,0,1,0 +0,1,0,0,0,2,2,2,0,2,1 +2,2,2,0,1,1,1,0,0,0,1 +1,1,0,2,0,0,0,1,1,2,0 +0,2,1,2,0,0,1,0,2,2,0 +2,1,2,2,0,2,2,0,2,1,0 +1,0,0,2,2,2,2,1,2,2,1 +2,0,0,2,0,0,2,1,1,2,2 +1,0,0,1,2,1,2,2,0,1,0 +0,0,0,2,2,0,0,2,1,0,1 +1,2,2,0,1,0,2,0,0,2,1 +1,0,0,2,2,0,1,2,1,1,1 +0,0,1,0,1,1,2,1,0,2,1 +0,2,1,1,1,2,2,0,0,1,1 +1,0,0,1,2,1,2,2,0,2,1 +0,1,2,1,1,1,2,1,1,0,0 +2,0,0,1,2,0,2,1,0,1,2 +0,1,2,1,0,0,0,1,0,0,1 +2,0,2,1,0,2,0,0,2,0,1 +1,0,0,1,0,1,0,2,1,0,2 +2,1,0,0,2,2,1,2,2,2,2 +2,1,0,0,2,2,1,1,0,1,0 +0,0,1,2,1,0,2,1,2,1,0 +2,2,2,0,2,2,0,2,0,1,0 +1,2,2,1,0,0,0,0,1,0,2 +0,0,1,2,1,2,1,2,0,1,0 +1,0,1,0,1,1,1,2,1,1,0 +2,0,0,1,1,0,0,1,0,0,0 +1,0,0,2,2,2,0,0,2,1,1 +0,1,2,2,2,0,2,0,1,0,0 +2,1,2,2,1,1,2,0,0,0,0 +1,0,2,0,2,1,2,0,1,1,2 +1,0,1,1,0,1,0,0,0,2,2 +0,1,1,2,2,0,2,1,0,2,2 +0,0,1,2,1,2,2,0,0,0,1 +1,1,0,0,1,2,2,1,0,0,0 +1,0,0,2,2,1,2,0,1,1,1 +2,1,1,2,2,1,0,1,1,1,2 +1,1,1,0,0,0,1,0,0,2,2 +0,2,2,0,2,2,0,1,2,0,1 +0,0,0,2,1,2,0,0,1,0,2 +2,1,1,2,0,0,1,2,0,1,2 +2,0,2,2,0,1,0,1,0,2,2 +2,2,2,1,0,1,2,2,1,0,0 +0,2,2,2,0,2,1,0,1,1,1 +1,2,2,0,0,0,0,1,0,2,2 +0,1,1,2,1,1,1,1,0,0,1 +1,1,1,1,1,2,2,2,0,0,1 +2,1,1,1,0,2,0,0,1,0,0 +2,1,2,1,2,0,2,0,1,2,2 +0,2,0,0,2,0,1,0,2,0,1 +0,2,2,0,0,1,1,0,2,0,1 +0,0,0,0,1,2,0,1,0,2,0 +2,1,0,1,2,1,0,0,2,0,2 +2,0,2,2,0,1,2,1,2,1,2 +0,1,1,1,0,0,0,2,1,2,0 +0,2,0,2,1,0,0,2,2,0,1 +2,2,0,1,0,0,1,0,0,0,1 +1,0,0,2,0,1,1,1,0,1,2 +1,0,0,1,2,2,0,0,1,1,2 +2,2,2,2,0,1,1,0,2,2,1 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/Y_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/Y_data.csv new file mode 100644 index 00000000..0cdc4075 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev3/Y_data.csv @@ -0,0 +1,149 @@ +sim_id,qoi,qoi_err,qoi_kla,qoi_kla_err,qoi_sum,qoi_sum_err,qoi_sum_kla,qoi_sum_kla_err +1,17.4223991446614,1.103218144362263,1.2304660921109788e-08,7.79153609998264e-10,22.202487028781846,1.3734243616096782,0.0005900413807461475,3.64993888127961e-05 +2,25.848218082263752,1.758737457653605,1.243246038052265e-08,8.459164841627111e-10,24.899955610551423,1.6140517157568066,0.0005460869651392669,3.5398159612058104e-05 +4,80.1616239973741,4.523742158697846,1.2813066392389407e-08,7.230767757817033e-10,55.05028379094841,2.920331409094589,0.0006959897551291124,3.6921167382715545e-05 +5,9.61902893286515,0.5007067376956474,9.375367176798238e-09,4.880232242315582e-10,15.715910274133016,0.7715804613106846,0.0004906457799837457,2.4088499530510554e-05 +6,11.571661508860648,0.7991397368378633,1.1278536382847752e-08,7.788964955467886e-10,17.501503699610872,1.1736497233403653,0.0005463914261980435,3.6640974238524396e-05 +7,25.967936704290313,1.503720500816584,1.2490042805129938e-08,7.232585952447871e-10,26.84011621778851,1.4792231849695188,0.0005886371034468552,3.2441202708906616e-05 +8,15.784502687549685,0.9779104231278233,1.114788803208151e-08,6.906543790596133e-10,20.780987323628676,1.2335849450948546,0.0005522643695861949,3.278309165124267e-05 +9,28.322807480233706,1.919328747203895,1.3622686810957992e-08,9.231575799353377e-10,27.860691750152963,1.8123255737316293,0.0006110195854417977,3.9746551545727074e-05 +11,55.692998354220606,2.9153555525009005,8.901991335135312e-09,4.659916081755522e-10,45.0088144548741,2.0685590980370216,0.0005690374603391518,2.6152379927460287e-05 +12,9.603805526605576,0.3573018112020921,9.360528610193792e-09,3.4825089043773607e-10,18.84009630457271,0.6501755546755569,0.0005881818613166108,2.0298275643039607e-05 +16,18.70165787199468,1.1963728336713932,1.3208144150682702e-08,8.449446008075813e-10,22.671468075391672,1.3880593986855305,0.0006025047701252881,3.688832175067795e-05 +17,30.651097165629224,1.5375901574352677,1.4742546175587104e-08,7.395491839207818e-10,30.360114566970537,1.4760327479049513,0.0006658350332085335,3.237123205020381e-05 +18,39.40018956094681,3.012408772841044,1.1774396553710803e-08,9.002315945318368e-10,33.38332430641881,2.4711869890873412,0.0005770982469589446,4.2719462753919e-05 +19,39.4566135193403,2.5770928813379617,1.1791260144563108e-08,7.701414254840408e-10,33.71628155603178,2.1621174100800977,0.0005828541304072504,3.737657311932029e-05 +20,39.04571607735852,2.5724327991166125,1.1668465302870307e-08,7.687486842599704e-10,32.184739352089025,2.0404511989439422,0.0005563782830144884,3.527332386395722e-05 +21,15.587135224722369,0.47180599504499976,1.519229269545425e-08,4.5985453188504973e-10,20.878607595825798,0.5734352363150347,0.0006518235390426024,1.7902467079333658e-05 +22,11.054861782654873,0.7290205115369429,1.0774827719241958e-08,7.105534714082854e-10,15.81887380001371,0.9962866746216571,0.0004938602481223174,3.110375558651865e-05 +23,23.389104632575368,1.4862762522111954,1.1249677473122185e-08,7.148682575069442e-10,26.812328521193745,1.618028876258382,0.0005880276792241016,3.5485383683544276e-05 +25,18.066554422384844,1.29590759223641,1.2759599070873119e-08,9.152415520554146e-10,21.672135720925667,1.4803644883513976,0.0005759470512690512,3.934137238934698e-05 +26,39.179760011873995,2.8449291697804324,1.1708522999257835e-08,8.501817929854247e-10,33.540903333647634,2.3177390263028115,0.0005798223154744414,4.006680426964589e-05 +27,25.395711311622772,1.4762652309464297,1.2214813866216542e-08,7.100531578702042e-10,26.802900671826272,1.4786220850720224,0.0005878209128474726,3.24280194313852e-05 +28,28.31256805717301,2.118077986078905,1.3617761948673073e-08,1.0187518753121333e-09,28.702543208501112,2.0748127384581267,0.0006294824359392475,4.5503221342963606e-05 +29,32.02527421704423,0.8389375979737489,1.540349697589943e-08,4.035116972231709e-10,32.13784673868751,0.7747395952430323,0.0007048229073989393,1.6991001868800735e-05 +32,43.84494046096217,1.4841270930584078,1.3102670756732871e-08,4.4351819062920955e-10,37.6358791908513,1.2532864720139834,0.0006506122522181449,2.1665590169865418e-05 +33,11.412671865802144,0.7502105515230207,1.1123574006433765e-08,7.312067400517768e-10,17.46738082507193,1.098663687505657,0.0005453261172302642,3.429993362195313e-05 +34,81.30651755082708,5.063566885242135,1.2996066709270487e-08,8.093625826038139e-10,55.843110222240696,3.3159416629821163,0.0007060133033837202,4.192278900642819e-05 +36,16.128946150098578,0.8772767815416485,1.1391153214878637e-08,6.195813500397517e-10,23.083924096280963,1.2224702690341067,0.0006134659864109275,3.2487714234507606e-05 +38,7.477975371015989,0.41852683206080754,9.61831942263456e-09,5.383174666911551e-10,13.427405119149359,0.7052709578039669,0.0004815591896016764,2.5293771050768162e-05 +39,17.511533207575518,1.0521148145965156,8.42268661101196e-09,5.060455447907809e-10,21.789918296615838,1.274664185779694,0.00047787997988887464,2.7954969228134898e-05 +40,47.22275364184555,2.488982628388502,1.4112100203359064e-08,7.43810336064634e-10,42.32408089085892,2.1599025815885793,0.0007316572957370524,3.733828233566886e-05 +42,11.83259238385368,0.6662539293338849,1.1532857390227777e-08,6.493768485739137e-10,17.169418891719758,0.9041939627856487,0.0005360238396979545,2.822865018441671e-05 +44,42.10922356557755,2.667160577689319,1.2583967189844179e-08,7.970572325423949e-10,35.791444715542255,2.181122771254939,0.0006187274738138897,3.7705116210369004e-05 +46,15.204352001137439,0.8735984833125554,1.0738153558852884e-08,6.169835229998239e-10,20.43814090739364,1.1150789954484517,0.0005431530671741273,2.9633741114886324e-05 +47,27.586309933640283,1.7087761435699216,1.3268446666463734e-08,8.218861159909827e-10,27.468726924748463,1.6455626423664615,0.0006024233098261674,3.6089233267215764e-05 +48,7.065810229372046,0.4179306556921122,9.08818504945299e-09,5.375506861166716e-10,15.236139729652184,0.8635084467142478,0.0005464274938117385,3.096878637211769e-05 +49,10.573854337118664,0.5887384988416378,1.0306004819487837e-08,5.738249850085732e-10,17.118088583047015,0.9140851871881895,0.0005344213236593416,2.8537451088920297e-05 +51,5.697203155291737,0.25459179224800943,9.348588552819786e-09,4.1776181220445485e-10,11.388614804755264,0.48619547827485293,0.0004613314624224476,1.9694868503416667e-05 +52,18.92625551383699,1.010923839269738,9.103139159669744e-09,4.862335490489403e-10,24.051566568533314,1.2370124372387605,0.0005274807442479538,2.712922001065592e-05 +54,97.06252707677889,5.4061474529087015,1.5514513574333304e-08,8.641207948012028e-10,61.80031603859736,3.265472960815328,0.0007813290661669102,4.1284723163448794e-05 +59,26.013629829738353,1.51791361016482,1.2512019882757812e-08,7.300851666990122e-10,28.90959203898809,1.6301677317041374,0.0006340232704926133,3.5751603665409574e-05 +60,28.172979269861333,1.4454701898323836,1.355062252895581e-08,6.952413776213711e-10,29.948725324782487,1.4436820277294755,0.000656812755999082,3.166174056278393e-05 +61,25.59417665035086,1.4770648611691515,1.2310271547184028e-08,7.104377602061549e-10,27.29425401445124,1.4872527186896805,0.0005985969007297081,3.261729987337682e-05 +62,15.963977495116453,0.8786767783864134,1.1274643058764223e-08,6.20570095601943e-10,21.602385313807876,1.1427653761639787,0.0005740934018723505,3.0369519514336996e-05 +64,37.268599768517944,1.9896077728061212,1.1137389792241161e-08,5.945765989881127e-10,34.26451214104265,1.775474950483865,0.000592331357590785,3.06926736169353e-05 +66,37.049874134303195,1.8736630482579046,1.107202567255556e-08,5.599275532443155e-10,32.842462182337734,1.5929214494960102,0.0005677483517601114,2.753686743745574e-05 +68,19.50275019782791,0.8984683949744913,9.380421055488508e-09,4.3214478801294095e-10,23.782748456142794,1.0562181072021217,0.0005215852240950235,2.31641754591214e-05 +69,36.22420526328668,1.9131912604444834,1.082528173542894e-08,5.717402012698515e-10,35.46690511848559,1.7522464517693712,0.000613117149647031,3.0291122002297613e-05 +70,75.5996077191277,4.216857324024473,1.208387192943389e-08,6.740241832672172e-10,52.704511145085505,2.7629037587204515,0.0006663326213149604,3.493084109861481e-05 +71,28.827577810310395,1.7986445962035849,1.3865470874119052e-08,8.651109859335039e-10,30.308244798476267,1.826524687496507,0.0006646974631847234,4.0057955658462785e-05 +72,22.51055283232561,1.2296268640318675,1.0827112053080002e-08,5.914251835357957e-10,26.603515628343857,1.365578957233975,0.0005834481502343554,2.9948843142680618e-05 +73,6.407375192409076,0.29450904915826653,8.241292355698413e-09,3.7880334811476275e-10,12.635171469203133,0.5462445067406857,0.0004531465967694843,1.9590461422458104e-05 +74,24.99836634178852,1.4779651457040004,1.2023699122957449e-08,7.108707818421172e-10,26.26440416817624,1.4641135746064566,0.0005760110154704523,3.210982977085751e-05 +75,10.759856369432361,0.805772433815022,1.0487295315710269e-08,7.853611777461428e-10,19.50162803135016,1.4096790161341506,0.0006088346770723519,4.400973432494938e-05 +77,26.228510218372403,1.7218707752475615,1.2615373299494196e-08,8.281843849454217e-10,27.03178417123828,1.693763021521184,0.0005928406198559041,3.7146327937762245e-05 +78,13.030932426192962,0.7083988889716037,1.270084183125939e-08,6.90454216782153e-10,17.527045565691168,0.8907802770657285,0.0005471888297620151,2.7809879055532553e-05 +79,39.44839935897121,2.328185874018291,1.1788803525481374e-08,6.957576552053686e-10,38.76478940650263,2.1384793381504186,0.000670127747371916,3.6967938266052784e-05 +80,44.02426040757055,2.462827933383349,1.3156259038315891e-08,7.359942440468493e-10,37.126228890739,1.971803060236969,0.000641801919197196,3.408660201022106e-05 +81,198.43690865754266,9.686910952479781,1.2695452537431015e-08,6.197421591754535e-10,92.9540345217289,4.405411871601801,0.0007435002366368239,3.523703716435191e-05 +82,45.37190480778461,2.7945145699534684,1.3558990399400327e-08,8.351158362318163e-10,36.069192426639745,2.1397662481768913,0.0006235289026122496,3.699018499751769e-05 +83,47.723813942430816,2.8448625704576886,1.4261837620694226e-08,8.50161893640803e-10,40.07776355317413,2.3080637735540326,0.0006928251596560375,3.989954804457253e-05 +86,41.659747392343,2.0917935065059265,1.244964562964285e-08,6.251139173055405e-10,39.50236666689413,1.8927262316015165,0.0006828782722671803,3.271959955741148e-05 +87,28.65718382828829,1.5602253293939399,1.3783515034911297e-08,7.504362401556795e-10,30.386855376353864,1.5982625431056046,0.0006664214945655244,3.5051883437513404e-05 +88,20.784015365445935,1.0712810864710438,9.996683204881509e-09,5.152641323888147e-10,22.878398107560802,1.1425519302320541,0.000501751697280602,2.505758346934725e-05 +89,40.89338236802751,2.3282074103016783,1.2220623854524704e-08,6.957640911322412e-10,35.553324945817934,1.9491101382323428,0.000614611092238415,3.369430883827533e-05 +90,30.018760300922867,1.4223658170844806,8.970841143068865e-09,4.250614503892069e-10,33.98777088282419,1.5169699851257445,0.0005875473726089287,2.6223894828526502e-05 +91,4.629434601394543,0.18841739617646808,4.512165045949705e-09,1.83644540268528e-10,14.640849177928732,0.5244938122423173,0.00045708269417197537,1.637453141294941e-05 +92,52.3220196804222,3.683216462762814,1.5635970423448902e-08,1.1006964950259486e-09,40.04362043179556,2.683211669020913,0.0006922349242919437,4.638473760702025e-05 +94,18.376349796060552,1.0135002284818593,1.2978393682712091e-08,7.157898662538543e-10,22.98994264485136,1.217400094292704,0.0006109683810424756,3.23529717399075e-05 +95,40.28701050764018,2.4645717264886593,1.2039415399575945e-08,7.365153786136583e-10,38.45129278772119,2.2519811546361703,0.0006647083352432219,3.893004723043622e-05 +96,69.0371782911743,4.286797419681472,1.1034930429748368e-08,6.852034289857012e-10,46.61911158021491,2.822860151007305,0.0005893961252553337,3.56888576110811e-05 +97,84.73065095668295,4.176326276358099,1.3543381509011284e-08,6.675456806739549e-10,58.15591259089866,2.8238988218043803,0.0007352536004565491,3.570198942044653e-05 +98,15.743433812556221,0.91617856159171,1.111888292314058e-08,6.470559272085223e-10,21.540276532482398,1.2340403830837339,0.0005724428322227808,3.27951951268811e-05 +99,37.33732676232825,1.0721501508540536,1.1157928200556517e-08,3.2040254192797483e-10,36.868275839276386,0.9854596186052323,0.0006373426753606414,1.7035661567678652e-05 +100,14.591307061511072,0.8498313661458435,1.0305187505508372e-08,6.001978807845276e-10,20.205347925291772,1.094647292908167,0.0005369664899288984,2.9090759375012406e-05 +101,15.173890842325372,0.7534095591847125,1.0716640370810324e-08,5.32099471494285e-10,22.257199504647705,1.0774346138506392,0.0005914953970526747,2.8633324447884827e-05 +103,7.676269374985747,0.4182690017488218,9.873368968791824e-09,5.379858340995252e-10,14.888687149879463,0.7485696592998057,0.000533966467345555,2.6846631440007046e-05 +104,26.22955875353676,1.3219880235424553,1.2615877387141639e-08,6.358490041328843e-10,29.127499140392374,1.379055512855738,0.0006388022475402806,3.024440089583307e-05 +105,81.47835215359162,4.8891376240317275,1.3023532716069212e-08,7.814817324718726e-10,53.42571209968326,3.0104146696808414,0.0006754506183824746,3.806007201981033e-05 +107,22.346625362594782,1.3186595236642844,1.0748266421099103e-08,6.342480642642158e-10,27.001928692177383,1.532762047578573,0.0005921858465550693,3.3615376185174465e-05 +108,33.750647512557606,2.023904309093415,1.0086081112443683e-08,6.048258190526657e-10,30.420189445603405,1.7306674317295478,0.0005258744707411066,2.9918085201839006e-05 +109,30.024066108575163,1.2209407310691516,1.4440957157021315e-08,5.872473343507646e-10,29.916434455012883,1.1508986192791435,0.0006561045771054237,2.5240636648356682e-05 +110,51.09981345179079,2.409817247498714,1.5270725067705818e-08,7.201524656188113e-10,40.32668242834448,1.83797873045895,0.0006971282255993876,3.1773177804323133e-05 +111,26.45145811234344,1.6993717979116187,1.2722606407225242e-08,8.173628248598956e-10,26.170382280501986,1.6157130280628271,0.0005739490005370851,3.54345942551367e-05 +112,20.39599560824857,1.0875650490794908,9.810053695533379e-09,5.23096382926284e-10,27.40642777340673,1.3852657932722454,0.0006010570140031169,3.0380600061741517e-05 +114,27.634622327298075,1.9180950883119448,1.3291683892034008e-08,9.22564212629792e-10,26.787628328817096,1.7607296668865338,0.0005874859704994076,3.861498914501372e-05 +117,7.794139513227802,0.44444151244730573,1.0024976598297766e-08,5.71649475100444e-10,12.406393527364635,0.6616925237910299,0.00044494174001348486,2.3730878940774233e-05 +119,33.940478138599275,1.256508675702632,1.6324671058969573e-08,6.043547981211049e-10,35.55216020670031,1.272284864970151,0.000779703054768476,2.790278818461128e-05 +120,25.96252740330887,1.9003878616262815,1.2487440808979846e-08,9.140474102354727e-10,26.38912993885366,1.8399799356452666,0.000578746408482261,4.0353046193700244e-05 +122,14.104426072362447,0.7473067192501723,9.961325241155172e-09,5.277893086297507e-10,20.22233638706039,1.007708156525112,0.000537417966177608,2.678031151370024e-05 +123,24.2764356852001,1.4874815789040423,1.1676465352407096e-08,7.154479901267143e-10,26.785589086407036,1.567602787134518,0.0005874412482705461,3.4379476781192296e-05 +124,22.049535089909476,0.8323488127914631,1.5572600029175833e-08,5.878507230881493e-10,25.261025977428467,0.8989768905075458,0.0006713234713802949,2.3890727453644967e-05 +126,19.266372137239077,1.4183076501018073,1.3606976851914022e-08,1.001687252086549e-09,23.869996406655375,1.6580893054848083,0.0006343562225450797,4.406449211598843e-05 +127,43.92592825518536,2.012858950006236,1.3126873660080967e-08,6.015250259207889e-10,35.381106372747915,1.5449328431727423,0.0006116339558706009,2.670728768255784e-05 +128,67.5593479336806,3.6926091887607924,1.07987136702956e-08,5.902281556191735e-10,52.60958728532276,2.8174383793095177,0.0006651325216705764,3.562031163100208e-05 +129,20.676771253674573,0.4890589076347655,9.945101182706132e-09,2.3522726353453843e-10,27.032124591846284,0.5758396926845158,0.0005928480857028855,1.2628880068965264e-05 +130,24.573964758351185,1.2227966314445724,1.1819570706052585e-08,5.88139984190804e-10,27.097807436972836,1.243763641224163,0.0005942885846124007,2.7277281959239085e-05 +131,9.024862558560534,0.42890426539446924,8.796251138091532e-09,4.180395666003545e-10,17.19755200706619,0.7818988435892256,0.0005369021502115183,2.4410635315913828e-05 +132,23.43004962237223,1.4035659823572508,1.1269371169678377e-08,6.75086321678761e-10,26.41099139118363,1.4913546578500785,0.0005792258572950673,3.2707260679073295e-05 +133,32.66863446109656,1.7086881273787575,9.762731007698199e-09,5.106262578410335e-10,35.158820532128246,1.68925349372683,0.0006077912847934002,2.920216138524202e-05 +134,25.009033899831802,1.3678437751569843,1.2028829962092981e-08,6.579046696474494e-10,28.15008610160728,1.4670696333597866,0.0006173663621894417,3.217465976326856e-05 +135,33.01469834674273,1.2722627196565928,9.866149123660946e-09,3.802044042557431e-10,32.06355463008296,1.1796135386246382,0.00055428335674268,2.0392004548195768e-05 +136,39.1416017851382,2.34528194088878,1.1697119797401563e-08,7.008666628373562e-10,36.30857472467887,2.0729998868495607,0.0006276671113929088,3.583599358452092e-05 +137,33.578500050844994,1.3600408537390778,1.0034636230162306e-08,4.064361184914688e-10,33.02350580298785,1.2639923357588543,0.000570878052665749,2.185066260158119e-05 +139,26.674642792448857,1.4095826243692933,1.282995364037375e-08,6.779802025335432e-10,26.9201593537471,1.356763248186954,0.0005903925433635599,2.975550383314517e-05 +140,10.26657477807598,0.5180258033894085,1.000650900628064e-08,5.049035320106363e-10,16.521001460453373,0.7838420040463048,0.0005157804509259369,2.447129995535988e-05 +143,17.184517385330626,0.8926032126076361,1.2136655962413913e-08,6.304057227473803e-10,24.908100354813246,1.2290232556631064,0.0006619443163153392,3.2661862892661646e-05 +145,18.48807964123526,1.112028444532156,1.3057303402839562e-08,7.853759327420315e-10,21.764479032165994,1.261409953424269,0.0005784011160003047,3.352255405315254e-05 +146,95.76224339688635,3.043962119755532,1.5306676456748662e-08,4.865481599109205e-10,62.46156467277945,1.8253397732567291,0.0007896891201131923,2.307740715433758e-05 +147,22.400115807551543,1.397065616891737,1.0773994152536819e-08,6.719597754056025e-10,23.974759953450274,1.4405617387615564,0.0005257962730858385,3.1593308748931865e-05 +148,27.229660397783622,1.896831026707208,1.3096905588424786e-08,9.123366399384563e-10,26.915094443952793,1.8064529929562463,0.0005902814616647333,3.961775855296772e-05 +150,24.361573248682447,1.3426690050594128,1.1717416246841271e-08,6.45796207552574e-10,24.62112656961705,1.3124347961957423,0.0005399719301691506,2.8783327526429794e-05 +151,16.379722375323254,1.08057826916865,1.1568265066767817e-08,7.631640852450916e-10,20.365113827858128,1.3036104050002932,0.000541212338689271,3.4644050703255e-05 +152,19.74123349676713,0.9578333797790023,9.495126546905183e-09,4.6069811966617474e-10,22.151452908240998,1.0168262765552327,0.0004858088842267387,2.2300263594987505e-05 +153,55.91405663349491,1.3505471370712436,1.6709418732616453e-08,4.0359900515501576e-10,43.35282816679306,0.9613265855036333,0.0007494412693027313,1.661847327889331e-05 +154,8.51572569157504,0.4454053125221563,1.0953094228809082e-08,5.728890918708083e-10,14.017344961771693,0.6942257514307398,0.000502716733547715,2.4897646669591447e-05 +155,22.037753485830223,1.139883298339714,1.0599705411658844e-08,5.482603829759566e-10,28.494450286705295,1.441222485564456,0.0006249186996054253,3.160779985081005e-05 +156,15.389387676110095,0.8584591259742521,1.0868836145296684e-08,6.062912816299372e-10,20.217990038207958,1.1027078753325497,0.0005373024599415401,2.930497309047065e-05 +159,17.837521632287295,1.0816467479612968,8.579480421990687e-09,5.202498020154537e-10,21.798328964984524,1.242121429989145,0.00047806443898042595,2.7241266315743325e-05 +160,42.61964026196392,2.460799020365709,1.2736500682903533e-08,7.353879153069126e-10,37.96519751890748,2.102618905586067,0.0006563051852309976,3.634801819781425e-05 +161,20.135445366187966,1.545360129183061,1.422076410311536e-08,1.0914187122165808e-09,25.81295043938796,1.931090362370255,0.0006859911197202088,5.1319621252667814e-05 +162,44.30398897230228,3.573587825443867,1.3239853434313825e-08,1.0679349679574998e-09,36.31570930262649,2.811867839712164,0.0006277904496044067,4.860881996302907e-05 +163,14.60534672578164,0.7664375445895067,1.0315102933028627e-08,5.41300546478836e-10,21.223735032340787,1.0540977410810628,0.0005640305951475574,2.8013136016807627e-05 +164,18.43948511309074,1.3185950665074533,1.3022983261969683e-08,9.312646950348637e-10,23.33404810454675,1.6051773448708782,0.0006201131414415241,4.265833178361745e-05 +165,33.36844468019669,1.8954844745316817,9.971863070859538e-09,5.664486857005844e-10,35.65130517797421,1.8692470923656594,0.0006163048774313049,3.231371458627483e-05 +166,316.45786170124467,15.392842462913949,2.0246111424052103e-08,9.847921045843645e-10,134.69655013792598,6.204738263132205,0.001077381067072473,4.962909238576368e-05 +168,20.54902774191851,1.804412753303364,1.4512858829380834e-08,1.2743759893421214e-09,26.207879410917773,2.199549084957067,0.0006964865401498041,5.845403620993567e-05 +170,24.287608971745325,0.4492428393554987,1.1681839768241514e-08,2.1607655461210578e-10,28.633167652011117,0.49640948613969454,0.0006279609496630093,1.0886876929808158e-05 +172,9.90466440382079,0.6165543288405986,9.653766466712773e-09,6.00936211667295e-10,14.658625954951058,0.8595267443169576,0.00045763767954449803,2.683415389576757e-05 +173,42.89572732606993,2.8142681308083017,1.2819006848110784e-08,8.410190172792861e-10,37.1915138502694,2.303811817059899,0.0006429304990278551,3.982604438130074e-05 +175,31.59862362536986,1.2899603130667865,1.519828726318692e-08,6.204443468341124e-10,30.620793205759664,1.1885505490961628,0.0006715520481218182,2.6066390579056145e-05 +176,37.143879554603245,2.8603490869466373,1.110011835711229e-08,8.547899085525368e-10,32.05231107175396,2.3704673156611764,0.0005540889924774625,4.0978319588097685e-05 +177,30.885006978778538,1.735322993015187,9.229709825302192e-09,5.185858526666426e-10,33.699518601651405,1.8160494680903987,0.0005825643021358564,3.1394086174585044e-05 +179,17.482227820286308,1.1706795186092331,1.2346915525976756e-08,8.267985792684066e-10,21.041701103271087,1.3331752938997177,0.00055919296343388,3.542975160200918e-05 +180,32.62935213314793,1.5515896057423153,9.750991800515365e-09,4.636787595910674e-10,31.907606509373494,1.4201801882023548,0.0005515874773104998,2.4550685339145146e-05 +182,65.73963306811494,4.00391064554442,1.050784950082278e-08,6.399866947010533e-10,45.30754938866478,2.6910678760166764,0.0005728143069926357,3.40226342247566e-05 +183,18.139528103448566,1.1330022545791107,1.2811137047613765e-08,8.001887963066067e-10,22.875223278529077,1.3537097642492009,0.0006079196590693961,3.597546429781576e-05 +184,91.84141127200945,5.578158070160092,1.467996855706564e-08,8.91615056238241e-10,58.81030591187199,3.418437904199642,0.0007435269708396734,4.3218628784585026e-05 +185,10.336028263628643,0.5771903145098206,1.0074203323024476e-08,5.625693386417865e-10,18.718614776533002,1.009419332420171,0.0005843892501893447,3.1513753225969784e-05 +187,15.047884808029401,0.7652423023244316,1.0627647780876217e-08,5.404564003434763e-10,21.20966697301337,1.0327409328006032,0.0005636567299507424,2.744556893841524e-05 +188,8.233275283967266,0.43206232809707956,1.0589801068697602e-08,5.557270886759063e-10,14.388537500518739,0.7168927296304731,0.0005160291505930287,2.5710573178420247e-05 +189,30.673882932856422,2.487447376809254,1.4753505756793315e-08,1.1964109426187443e-09,33.2437107856204,2.592940880162685,0.0007290758833800559,5.686641527318861e-05 +190,39.401253288551274,1.1907583200022294,6.297912361906335e-09,1.903312945064087e-10,41.88742559720661,1.188667508619582,0.0005295743694520746,1.5028086290587478e-05 +193,18.20243685252858,1.1622160120438159,1.2855566682241625e-08,8.208211660364969e-10,22.285845480054146,1.3460177454865316,0.0005922566709556035,3.577104533469479e-05 +195,16.939801822928217,0.9582997841292484,1.1963824306864364e-08,6.768042725925198e-10,25.07745194997855,1.38938792985861,0.0006664449134817925,3.6923628467287724e-05 +196,10.133456572683691,0.5653515284282749,9.876762904661601e-09,5.510304370501021e-10,17.064815403430906,0.9133141863475364,0.0005327581518029828,2.8513380685977522e-05 +197,27.493208364082367,1.6764878600081528,1.32236666897462e-08,8.063561144473813e-10,28.5658061828433,1.639176405708394,0.0006264836200662168,3.59491751082486e-05 +198,27.066939502223367,1.5473555515834687,1.3018640190498995e-08,7.442461372916417e-10,27.9792095295503,1.5431028529622552,0.0006136188275957344,3.3842162784988125e-05 +199,79.01664781804176,4.402176609053915,1.2630053146919627e-08,7.036457008719415e-10,55.631832660065996,3.069794469189407,0.0007033421673062306,3.881079935542421e-05 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/X_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/X_data.csv new file mode 100644 index 00000000..34157e56 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/X_data.csv @@ -0,0 +1,135 @@ +2,1,1,1,1,0,0,1,0,0,0 +0,0,1,2,0,2,2,1,1,0,2 +0,1,2,1,1,0,2,2,1,1,1 +1,2,2,0,0,1,1,2,1,1,2 +0,2,0,0,2,2,1,2,0,0,0 +1,2,0,2,1,0,0,0,2,0,0 +0,2,0,0,2,1,0,2,1,1,0 +0,2,0,1,1,0,1,2,1,0,2 +0,0,1,2,0,2,0,0,0,1,1 +2,2,2,1,0,2,1,2,1,1,2 +0,2,2,0,0,1,0,1,1,1,2 +1,0,1,0,2,1,1,2,2,1,0 +2,2,1,2,2,1,0,0,1,2,0 +0,0,1,0,1,0,1,0,1,0,2 +1,0,0,0,2,1,1,0,0,2,0 +0,1,2,1,0,0,2,2,0,1,2 +2,1,0,1,1,2,0,1,2,0,2 +1,0,2,1,2,0,2,0,1,0,0 +1,2,0,2,0,1,0,0,1,1,2 +2,2,1,0,1,0,2,1,2,0,0 +1,0,1,2,0,1,0,0,1,1,2 +2,2,0,2,2,2,1,2,1,2,2 +1,0,1,2,2,0,1,0,0,0,0 +2,0,1,0,2,0,2,0,0,2,1 +2,0,1,2,1,2,1,1,1,1,2 +0,0,0,0,0,1,2,1,0,2,0 +0,1,1,1,1,1,1,2,0,0,0 +2,0,1,2,0,1,0,1,1,2,2 +2,0,0,0,1,1,0,1,0,0,2 +0,2,1,1,2,0,1,0,2,2,1 +2,1,2,0,0,1,2,0,0,2,2 +2,0,0,1,0,0,1,2,0,2,1 +1,0,1,2,0,0,0,0,0,1,2 +2,1,0,1,0,0,2,1,2,0,2 +0,2,0,0,0,0,0,1,2,0,0 +0,0,0,2,2,1,2,0,1,2,2 +2,0,0,1,0,1,0,0,0,0,0 +2,1,2,1,1,0,0,2,0,1,1 +2,0,2,1,1,1,0,0,2,2,2 +1,2,2,0,1,0,2,1,1,0,2 +1,1,1,2,0,0,0,1,0,1,1 +1,0,0,1,1,0,2,1,0,1,1 +1,0,0,2,0,0,1,2,2,1,2 +2,2,1,0,2,2,1,0,0,1,1 +0,2,1,2,2,0,2,0,1,1,2 +2,1,2,1,1,1,0,1,0,2,0 +0,0,2,2,2,1,1,2,0,0,1 +1,2,0,0,2,2,1,0,1,1,1 +1,2,1,2,2,0,2,1,2,0,1 +0,0,1,0,1,1,2,2,1,1,0 +0,0,0,1,0,0,0,0,2,1,2 +0,1,2,0,1,1,2,0,0,2,1 +1,0,2,1,0,2,0,2,0,0,0 +2,2,2,0,0,1,1,0,0,2,2 +0,1,0,1,0,0,1,1,0,1,0 +1,0,0,0,2,2,1,2,1,1,2 +2,0,2,2,1,1,0,2,0,1,2 +1,1,1,2,0,1,2,1,0,1,0 +0,1,1,1,0,0,2,2,2,1,2 +0,0,2,2,2,1,1,2,1,1,2 +2,1,1,0,1,1,2,0,2,2,2 +1,0,2,2,2,0,0,2,1,2,2 +0,1,2,1,0,0,2,0,1,2,2 +0,0,2,1,1,0,2,2,0,2,1 +1,1,1,0,0,1,1,1,1,2,0 +1,2,0,0,1,0,2,0,0,1,2 +2,1,1,1,1,1,1,1,0,1,0 +0,0,1,2,0,1,2,0,0,2,1 +1,2,2,1,0,0,0,1,2,1,1 +0,2,0,0,1,2,1,2,0,2,0 +2,0,2,1,0,2,2,0,0,0,1 +1,1,0,1,0,0,0,0,0,0,2 +0,2,1,0,0,2,0,1,1,2,2 +1,1,2,1,2,2,0,0,1,1,1 +1,0,0,2,2,1,2,0,2,0,1 +2,0,2,2,1,2,1,2,0,1,0 +1,2,0,1,0,1,2,2,1,0,2 +2,2,0,0,0,1,2,1,2,0,1 +1,1,2,0,2,2,1,1,2,2,2 +1,0,2,1,0,2,1,1,0,1,0 +0,1,2,1,1,2,1,0,2,1,1 +1,0,2,1,1,2,2,2,0,2,1 +0,2,0,0,0,0,0,1,0,2,2 +0,2,1,2,1,0,0,0,2,2,2 +2,1,2,1,0,0,2,2,0,1,0 +1,0,0,0,1,2,2,1,1,0,1 +0,1,0,0,0,2,2,2,0,2,1 +1,1,0,2,0,0,0,1,1,2,0 +2,1,2,1,2,2,1,1,2,1,1 +0,2,1,2,0,0,1,0,2,2,0 +1,0,0,2,2,2,2,1,2,2,1 +1,2,2,0,1,0,2,0,0,2,1 +0,0,1,0,1,1,2,1,0,2,1 +0,2,1,1,1,2,2,0,0,1,1 +0,1,2,1,0,0,0,1,0,0,1 +2,1,1,2,0,0,2,1,1,2,1 +2,2,1,1,0,0,2,2,1,1,0 +2,1,0,0,2,2,1,1,0,1,0 +0,0,1,2,1,0,2,1,2,1,0 +1,2,2,1,1,1,1,1,0,2,0 +1,2,2,1,0,0,0,0,1,0,2 +0,0,1,2,1,2,1,2,0,1,0 +1,0,1,0,1,1,1,2,1,1,0 +1,0,0,2,2,2,0,0,2,1,1 +0,1,2,2,2,0,2,0,1,0,0 +2,2,2,0,2,1,0,2,1,2,0 +0,0,2,0,2,2,1,2,1,1,1 +2,1,2,2,1,1,2,0,0,0,0 +1,0,2,0,2,1,2,0,1,1,2 +1,0,1,1,0,1,0,0,0,2,2 +0,1,1,2,2,0,2,1,0,2,2 +0,0,1,2,1,2,2,0,0,0,1 +1,1,0,0,1,2,2,1,0,0,0 +1,0,0,2,2,1,2,0,1,1,1 +2,1,1,2,2,1,0,1,1,1,2 +1,1,1,0,0,0,1,0,0,2,2 +0,2,2,0,2,2,0,1,2,0,1 +0,0,0,2,1,2,0,0,1,0,2 +2,2,1,1,1,0,0,0,1,1,1 +0,2,2,2,0,2,1,0,1,1,1 +1,2,1,2,1,1,2,2,2,2,0 +1,2,2,0,0,0,0,1,0,2,2 +1,1,0,1,1,2,2,2,0,1,0 +1,1,1,1,1,2,2,2,0,0,1 +2,1,1,1,0,2,0,0,1,0,0 +2,1,2,1,2,0,2,0,1,2,2 +0,2,0,0,2,0,1,0,2,0,1 +0,2,2,0,0,1,1,0,2,0,1 +0,0,0,0,1,2,0,1,0,2,0 +2,1,0,1,2,1,0,0,2,0,2 +2,0,2,2,0,1,2,1,2,1,2 +0,1,1,1,0,0,0,2,1,2,0 +2,0,1,2,2,0,0,1,2,1,1 +0,2,0,2,1,0,0,2,2,0,1 +1,0,0,1,2,2,0,0,1,1,2 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/Y_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/Y_data.csv new file mode 100644 index 00000000..1c41a34c --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev4/Y_data.csv @@ -0,0 +1,136 @@ +sim_id,qoi,qoi_err,qoi_kla,qoi_kla_err,qoi_sum,qoi_sum_err,qoi_sum_kla,qoi_sum_kla_err +1,36.07584001788666,1.4944043441048203,7.748412599841807e-07,3.209699744587803e-08,44.50778213746871,0.9201301317197476,0.006522800513341893,0.00013484889624437832 +2,38.01538204266846,2.9227468123696863,6.226229029726544e-07,4.786928362127673e-08,32.03095642912799,2.287537935583192,0.004099234592655657,0.00029275287668361445 +3,116.13148841916453,8.355945758198212,9.579580949846692e-07,6.892743724619157e-08,73.23612016500374,5.02544765383488,0.006651561153608707,0.00045642877201071885 +4,133.2160874271533,8.695126406821187,1.0988874147601935e-06,7.172530857753779e-08,85.96908583480283,5.387697373052412,0.0078080137830666444,0.0004893295646835308 +5,34.837109352520336,3.573942144871707,9.499479459262051e-07,9.745524420597065e-08,39.65772696195647,3.9742723591147757,0.00654872368788165,0.0006562759273922901 +6,7.323877708646155,0.8850693746780647,1.9970943336660614e-07,2.4134305669580442e-08,21.889723633731418,1.1682004375791348,0.003614673092104825,0.00019290616722978548 +8,33.15185098281714,2.7271263591288895,7.120395046207717e-07,5.8573553036264675e-08,34.42722154658428,2.6808773434537416,0.005045452573424188,0.00039289373013330777 +9,23.504048773390597,1.5154902416974898,3.849536089530675e-07,2.482097631345442e-08,23.169537686801483,1.1056522852514619,0.0029651742917988027,0.00014149836635557036 +12,33.84302096218575,1.3626643799966673,9.228403627112019e-07,3.7157489341593995e-08,36.60030196978353,1.365040377840476,0.00604384610985522,0.00022541054399544485 +13,198.23604461397557,12.577584397134652,1.0347078192729791e-06,6.564963979493945e-08,113.05040898086821,6.457059616660763,0.008167510312785573,0.00046650075382100584 +14,69.51727954626844,4.711426618428412,1.1385667169067434e-06,7.716460672660231e-08,61.1379343044717,3.8332951155968735,0.00782426621988976,0.0004905746624422562 +15,43.712260915607324,1.9727008671102653,5.231678035137411e-07,2.3610162412515213e-08,35.54709342790707,1.208041847161979,0.003888865878434782,0.000132160249013815 +18,60.74526690647444,3.793629608303654,7.270264520399728e-07,4.540385144286578e-08,48.995639426060315,2.6498179547643894,0.005360142230650424,0.0002898911268277823 +21,29.6048570905226,3.118019447545674,8.072729756383452e-07,8.502296869131728e-08,31.717293704266584,3.161687964341966,0.0052375097739832165,0.0005220928295436062 +22,25.237583982235602,1.2174186598400236,6.881850524556869e-07,3.3196890988941804e-08,33.52559851701207,1.0745488538868482,0.005536117115779351,0.0001774413750950761 +23,44.79624628670165,3.5406137816766816,7.336811418598693e-07,5.7988822224073136e-08,42.259558746467135,3.0689626833992936,0.0054082632676665954,0.0003927574883127587 +24,17.84609524415117,1.5588771810480935,2.135900191406819e-07,1.865733665447953e-08,22.21435316998962,0.7790688096964776,0.002430258922119349,8.523043237952855e-05 +25,28.0075659023622,1.5774678955213715,6.015499213328372e-07,3.3881048134065926e-08,28.574803139090196,1.5523014124309884,0.004187756303195383,0.00022749623130295844 +27,71.84284814926004,5.608663020376987,1.1766553047590232e-06,9.185970859369837e-08,59.50096378826024,4.304905428462439,0.0076147711942782725,0.0005509300650557819 +28,16.973882760591902,0.9760930998599804,2.78001366585119e-07,1.5986631904008573e-08,21.173962281950665,0.8018842293289066,0.002709786042193474,0.00010262296036782953 +29,63.82723413307343,5.334109444630809,1.0453740938923328e-06,8.736301835949481e-08,54.04982430217737,4.1816021225162805,0.0069171491563345755,0.0005351500391968 +31,166.42303317004396,12.349002380802748,8.686576629198481e-07,6.44565559416244e-08,100.76884840647195,7.06667100738037,0.007280209993962814,0.000510543185771622 +33,12.399738722731932,0.7418705188621412,3.381193243119695e-07,2.0229519683731833e-08,19.903475305414485,0.9732741676501795,0.0032866816753736256,0.0001607177803295567 +36,44.25742529686018,3.113677768860384,9.505664778895427e-07,6.68759578799665e-08,44.077065423937086,3.0152617063546674,0.006459677659385964,0.0004418991712448141 +37,134.12427938640096,8.703216920304133,7.000716449732768e-07,4.542708757751083e-08,77.95199078346437,4.6596555697910675,0.005631767976706199,0.0003366443724744056 +38,35.94981271970667,1.733489156309015,1.2132560543306371e-06,5.850284201496063e-08,44.08635810539846,1.929136079064044,0.008099013846921934,0.00035439760706891266 +39,50.19680806869854,3.700960592651168,8.221324792416393e-07,6.061500770024561e-08,50.68410262102007,3.5929243905077066,0.0064864132401309385,0.00045981266575119894 +40,74.96198741420584,6.940833895001216,8.971784643966427e-07,8.307099251705894e-08,56.3250071318058,4.934284341902632,0.006161977802055939,0.0005398126362005739 +42,23.334884960018776,2.258949999562732,6.363017569970826e-07,6.159764044918475e-08,28.140074444194955,2.5402106293573086,0.004646799898017067,0.0004194676356257628 +44,68.24029624319373,2.716698374254876,8.167302696384782e-07,3.2514656557530744e-08,54.774284524651584,1.84369081486099,0.005992328142534904,0.00020170049598826594 +45,7.958148946544634,1.426691157010236,1.303400381776236e-07,2.336661215082338e-08,18.388204394612476,0.5899724490153058,0.0023532724625829108,7.550307186911051e-05 +46,52.57299575623597,3.587291648096317,1.1291692241890968e-06,7.704828817445647e-08,50.146357683551145,3.360327418933034,0.007349157383495725,0.0004924699659675462 +49,30.80683651174401,1.8287077034530776,8.400488896144454e-07,4.9865680792298064e-08,37.60572004437191,1.9572914231251457,0.006209871847126342,0.0003232095779776393 +50,15.33486177643806,1.0097229900047433,2.5115718014391574e-07,1.6537428415933188e-08,19.091458990687485,0.6959889912809916,0.0024432729410391687,8.907077612493973e-05 +51,28.88263450696164,0.6528913865518959,1.1818532500624766e-06,2.671576953785743e-08,36.1130211549457,0.6228000130899611,0.00730511735129554,0.00012598301212435385 +52,68.06527526898363,4.660280643314377,1.114785691587461e-06,7.632693997663536e-08,63.951819030299504,4.2254101297588305,0.008184380129045286,0.0005407565136916619 +53,14.90142179192025,1.271304262174914,6.097534878350627e-07,5.202068760855081e-08,35.48157501978784,2.579790228822996,0.007177384005154519,0.0005218524012725409 +55,83.72326585619116,3.966968046434534,1.0020373273655448e-06,4.7478440052990717e-08,64.1871780103725,2.7969088483644495,0.007022102296599886,0.00030598291833778293 +56,2.3629583929974256,0.13796067941256782,2.828094013355779e-08,1.6511749537419981e-09,19.21517547886195,0.6028013652983276,0.002102147757639505,6.59467065371272e-05 +58,32.50615543495209,1.8238266820450901,3.890481512372784e-07,2.1828370329636537e-08,28.154516816515226,1.3323195668729466,0.003080115147522314,0.00014575628152348666 +59,61.5072493030116,1.896329947101721,1.0073769489807637e-06,3.105843779423655e-08,52.26271052856814,1.2855615885003027,0.006688439175344966,0.00016452266642664893 +61,53.923556818724684,4.869721616253522,8.831698500875407e-07,7.97571889453192e-08,45.138532103237594,3.7501178448789223,0.005776706247790783,0.0004799298553820263 +63,61.46086740392494,3.269880418733637,1.0066173644999365e-06,5.3554701525826565e-08,53.96651737469116,2.5352168476648504,0.0069064879582026615,0.00032445014949290135 +64,92.20590646224588,8.013233624759623,1.1035613705249927e-06,9.590595028635752e-08,68.1847083760119,5.5903398004170946,0.007459433755053883,0.0006115853598652811 +66,84.15799387848212,5.757681383288932,1.0072404125654317e-06,6.891049922480454e-08,63.68017754574575,4.205504814360092,0.00696663647860703,0.00046008388135588386 +67,28.138494513155376,2.550000412887383,3.367740322801472e-07,3.051954044530094e-08,41.952273787897255,1.1627293150090345,0.004589595106766883,0.00012720304033197316 +68,60.88893605424962,4.41526979328821,9.972501679047207e-07,7.231409888289551e-08,57.46995899348059,4.116413579773016,0.007354848877704626,0.0005268074021210999 +69,93.10931573582445,6.0705891622859385,1.114373751891344e-06,7.265551430064551e-08,70.15226632520094,4.402473866601842,0.007674685283628992,0.00048163235723480533 +70,101.30653156504461,3.7669011126981786,8.35668405575201e-07,3.1072826185810316e-08,67.95647018191922,2.0236580373164332,0.0061720449550782645,0.00018379572021010653 +72,66.62511047242597,6.422699681617244,1.0911982234006786e-06,1.0519214801028228e-07,53.08735295705006,4.926186057910713,0.0067939746976032585,0.0006304398612642953 +73,30.285471058226154,2.3275228081392916,1.022092421068612e-06,7.855064950087125e-08,35.83999899478591,2.5717074243220925,0.006584092236389454,0.0004724430625460555 +74,45.8207837994003,3.8892530264449667,7.504611762296341e-07,6.369889728771408e-08,40.46827441160794,3.243884633293809,0.005179019475520851,0.0004151435151717881 +75,0.9050474701704486,0.04680128213432722,2.4679073658513115e-08,1.2761897327754424e-09,12.298525298241106,0.3768152628843159,0.0020308684208154427,6.222390077796333e-05 +77,16.963571889255064,1.3555457785643084,2.7783252393565476e-07,2.2201379958627483e-08,22.09353143117038,1.082357019525436,0.0028274701543678908,0.0001385171120611856 +78,42.58358950331254,3.0498922806427258,1.1611804248802944e-06,8.316525815655727e-08,40.84780437985339,2.849356623452479,0.0067452404734255345,0.00047051722636074194 +79,77.21270915612037,3.4982703483663,9.241161050042387e-07,4.186885817006507e-08,57.31110726384917,2.323857003274497,0.0062698575420449,0.00025423086473510046 +80,73.37764992218037,4.150938702487016,8.782164471198987e-07,4.9680286073167133e-08,60.16815312367989,2.920645363453345,0.006582419625019484,0.0003195197518959789 +82,40.87640943730353,2.5351874520291577,4.892270646655656e-07,3.0342251988535147e-08,32.45981755438765,1.705276826124047,0.0035511166741578333,0.00018655794848993238 +83,34.679340263057725,2.181248274025221,4.150577955141375e-07,2.6106151190261997e-08,33.70043182061734,1.7761772225541,0.003686840417301621,0.0001943144825935655 +84,72.2420916906668,4.12527415210092,5.959184728360354e-07,3.402901293717041e-08,55.38684696089749,2.9827179996091466,0.005030427690660917,0.00027090090954734236 +85,4.970209190621199,0.6457173349429254,4.0998805561069664e-08,5.326463826249591e-09,20.433772183771215,0.5469347908140101,0.0018558668539205444,4.967453588103744e-05 +86,63.78019065735429,4.585173175142391,7.63349871982397e-07,5.4877405040470535e-08,54.40630523508966,3.8617682630396337,0.005952071583599909,0.0004224789946967678 +87,51.064665872952546,2.7722541252717363,8.36346468107587e-07,4.54044867763598e-08,48.04255101024316,2.2057321921264954,0.0061483548721487325,0.00028228360036969654 +88,63.76847240719365,2.5821686388148426,1.0444117426923418e-06,4.229123179820587e-08,56.10534561834782,1.8946518381730515,0.0071802093734075305,0.00024247238365367283 +92,32.775285416162426,1.6973721682468492,3.9226920339873687e-07,2.0314905571532874e-08,25.06569745742975,1.0420745459352811,0.0027421970482780725,0.00011400336052099058 +94,50.23807055031827,3.811433930394057,1.0790194154254805e-06,8.18624434906882e-08,48.143945541865826,3.435274107144972,0.00705569555185615,0.0005034537149871084 +96,41.98625340782016,2.7592167647146693,3.46340784310629e-07,2.2760528049314453e-08,33.5142595064229,1.5591302571158896,0.003043882507763087,0.00014160567432646695 +98,51.288151118713465,3.6453524534907773,1.1015731741317306e-06,7.82953252443438e-08,49.15655353727629,3.426887785502158,0.007204097467166114,0.00050222466465387 +99,83.25688188008469,5.861032567981248,9.964554362607881e-07,7.01474476653857e-08,62.24617262575618,4.1854723201776,0.006809755550855363,0.0004578923034616801 +100,50.251362485330695,1.4020273568256438,1.0793050053506007e-06,3.011291772043248e-08,48.955059913132665,0.9930664296323606,0.007174568084177089,0.00014553802455048614 +101,45.204479387565144,3.3469346466010945,9.70907423286476e-07,7.188587807370241e-08,45.218666433806895,3.1819217739002474,0.006626984045790347,0.00046632389881416094 +103,7.644658053967196,0.631720824615439,2.579965304903696e-07,2.1319695379274567e-08,28.154386176339163,1.841988849985986,0.005172183970703118,0.0003383879564782673 +104,70.65101503604848,2.57528631329839,1.1571352888242973e-06,4.2178511807980695e-08,58.200270617536624,1.5712457421866766,0.007448312170921393,0.00020108375203174936 +105,111.77834523045344,6.155988919523123,9.220494123954857e-07,5.078019319624876e-08,70.31569503717229,3.4183661894386317,0.006386317906307507,0.0003104679999875887 +107,55.08350973167135,4.026736383786388,9.021678302893697e-07,6.59506274056296e-08,48.22175240839042,3.2773866067840913,0.006171288579169401,0.00041943101454874166 +108,53.272321883372314,4.18676504538259,6.375869124162418e-07,5.010907172662455e-08,43.82510091695135,3.158163025303419,0.004794483283394437,0.00034550427755421047 +110,24.986425735336066,1.3869809301154379,2.990486758058035e-07,1.6600005735608054e-08,23.339108098143353,0.8924961132123073,0.002553307551013755,9.763942373173604e-05 +112,53.21096761257695,3.735169601807364,8.714989918486425e-07,6.117529314744908e-08,52.60092561188836,3.3317519617141214,0.006731723242515425,0.00042638854465135596 +113,88.569178076686,5.429880962479172,4.6229343044542905e-07,2.8341668643254386e-08,54.26842165194804,2.860755063711893,0.0039207102167661476,0.0002066798934727834 +114,29.881064795929476,1.9742279899402528,4.893975347648161e-07,3.233426646402758e-08,26.04412405379263,1.3939276368788147,0.0033330559914309926,0.00017839105865584322 +115,83.59300522554484,6.298582336297782,6.895511039251564e-07,5.195643333361591e-08,55.33011243790279,3.8598459564700938,0.005025274764522847,0.0003505647399824789 +116,61.651079414736884,3.652094055924139,5.085541715878859e-07,3.012579317025847e-08,43.27394573103627,2.395546640484855,0.003930291519270754,0.00021757194741690847 +117,30.90089230872733,2.0055034956613906,1.0428624635868097e-06,6.768297482551026e-08,36.760153980395536,2.2633295411014713,0.006753133412713277,0.00041579168455455106 +119,2.014718629402948,0.1039101271489487,3.299743506152496e-08,1.701859318116463e-09,18.21059173250343,0.5928123590151805,0.002330542076419175,7.58665158387065e-05 +120,50.824807062172525,2.3374956566646765,8.324180164901915e-07,3.828393279870281e-08,45.00668051628307,1.6712160940264928,0.005759832432139827,0.00021387768546949926 +121,62.663552078884734,2.8749342142426073,1.026315096749514e-06,4.708619745214104e-08,53.57616844963867,2.1672950649059706,0.006856531971670591,0.0002773645136370684 +122,39.492037944226155,2.6738464788805842,8.482148964048858e-07,5.742920680085722e-08,41.57375586317201,2.7085960139601504,0.0060928072089902465,0.00039695603578404946 +124,35.96555109939184,3.0494855758830357,7.724724733113242e-07,6.549722145560028e-08,31.972019636322376,2.6276244921196033,0.00468563243798283,0.0003850892966775991 +125,319.51550017821455,11.34088337895161,9.203454656512178e-07,3.266674257892241e-08,128.82437108679088,3.865048413480344,0.006913970206898754,0.00020743613458839113 +126,16.89379053715062,1.43088802324926,3.628469315914367e-07,3.07327906987593e-08,24.29697977595018,1.4750643359283393,0.0035608236605520985,0.0002161768267761911 +128,112.50491055400711,7.314743643441323,9.280428704050028e-07,6.033866125227768e-08,76.80568931614053,4.872577737737456,0.006975762262369385,0.0004425446110308814 +132,55.88448274382703,4.031428580668274,9.152863132621667e-07,6.602747706718608e-08,50.43934438476128,3.4467219937499487,0.00645508996243589,0.000441102096320747 +134,47.29592972782607,3.936853258076221,7.746213721393614e-07,6.447850143197703e-08,41.04972368517892,3.243664256775448,0.005253431721983679,0.0004151153082709105 +135,81.78377825273544,6.558153596134565,9.788246760821662e-07,7.849090255522404e-08,66.37271659756907,5.040989786518259,0.007261201070033741,0.0005514862477880885 +140,39.55338670658884,2.913025694595634,1.078552079666144e-06,7.943314549354789e-08,42.30627173692466,2.962966902985891,0.006986078755298283,0.0004892778135194379 +141,122.39459812832675,9.147595748626873,1.0096219316709584e-06,7.54576871128779e-08,78.77992535940506,5.633376856748936,0.007155069023499832,0.0005116430367449329 +144,82.06804834289869,2.2253121315984723,9.822269676691888e-07,2.6633527070179926e-08,62.29834094760009,1.225125421888352,0.006815462856945706,0.00013402920015162385 +147,64.69873236910057,1.8724007677142502,1.0596476700801654e-06,3.0666522176133016e-08,55.59549146140483,1.0984657318085127,0.0071149594890356545,0.00014057865083065476 +148,74.28376092685737,2.4431677389171824,1.2166330205957744e-06,4.0014648005608356e-08,59.45767538914564,1.6988453899036293,0.007609231262928635,0.00021741360332591756 +149,81.40837193914159,2.8243427427777976,6.715302624654375e-07,2.3297746634311667e-08,70.26679179435985,1.0090090998868968,0.006381876342370971,9.164174340918305e-05 +151,46.016179667052796,3.9448018680268495,9.883411273672537e-07,8.472693634490523e-08,44.730089909569834,3.650776373194073,0.006555380803482987,0.0005350364688072192 +152,69.64766531089047,3.185752484842829,1.1407021988031298e-06,5.217683676949496e-08,58.34866816525719,2.4249893095338972,0.007467303540669141,0.00031034352328112777 +153,71.92840643656046,2.3333097360460764,8.608711819393152e-07,2.7926089424379458e-08,52.10387718993827,1.247531753365516,0.005700184424421071,0.0001364804589029327 +155,48.73655644689069,3.189930107028017,7.98216264716084e-07,5.224526064971356e-08,44.53725759692319,2.8125730425529487,0.005699756965024656,0.0003599454401529932 +156,40.83673249304287,3.3364985201604136,8.770964129534019e-07,7.166172965370314e-08,47.111750725008996,3.7992266351937785,0.006904423439397791,0.0005567924992796224 +157,53.720559041332734,2.603854053011066,6.429516977666122e-07,3.116409088058524e-08,44.017451097872225,1.5531891660544224,0.004815526780031531,0.00016991951685161206 +158,44.80228413266511,1.4070982266341236,5.362136979840692e-07,1.6840778503527302e-08,44.04520615779452,1.128872035754772,0.00481856277436757,0.00012349904207565766 +159,53.82105546151303,2.117128984742454,8.814911225905244e-07,3.46747270083562e-08,56.193979570763794,1.7473872248643834,0.007191552505312795,0.00022362585940190283 +160,74.2651521526847,6.634979376894386,8.888384295145036e-07,7.941038937205938e-08,55.181248031566795,4.611826744436388,0.006036850109305193,0.0005045356489639532 +161,1.1621800238082571,0.06388180497758605,2.496144365877265e-08,1.3720611635911233e-09,13.448760895340172,0.3971164741460889,0.001970971837834434,5.8199070752551255e-05 +162,24.182187934699297,1.9764609836801488,2.894232125738575e-07,2.3655166727191688e-08,30.505488241226825,0.9123976020504849,0.0033373124160399957,9.981665664911665e-05 +163,45.27252441444197,3.6294441418189,9.723688090206221e-07,7.795364458319259e-08,44.05211235165056,3.3465298152369742,0.006456020371224487,0.0004904478697324153 +164,20.854955981925805,1.3843280490488379,4.4792527670817294e-07,2.97327659172468e-08,23.976179964612943,1.3371458059320562,0.003513808882235094,0.00019596427857407068 +165,93.02071973131784,6.542816849710045,1.1133133954580013e-06,7.830734554463028e-08,69.79536954974826,4.512883751638232,0.007635640637264415,0.0004937112416991774 +166,124.39865607883726,8.650541907822381,6.493080312676516e-07,4.5152146434819956e-08,67.61048796449782,4.359154639731087,0.004884629336351845,0.0003149341955068506 +168,9.210301378124871,0.6485124473058094,1.9781997127865847e-07,1.3928829083115848e-08,16.616196347648987,0.6272530216442666,0.002435172675609915,9.19265388446131e-05 +170,63.94584319663291,4.136836254833012,1.0473168697311612e-06,6.775387078217813e-08,59.57211550536567,3.734791708162097,0.007623877565645254,0.00047796850044128954 +172,36.565307115460286,3.6317227321595573,9.970724601646014e-07,9.903077547676313e-08,39.10791583980101,3.817793784317712,0.006457931285006888,0.0006304363040067246 +174,87.41236592208365,2.669000479031016,1.0461901077961788e-06,3.194378586382681e-08,66.81730145344878,1.575855342075057,0.007309838785014966,0.00017239918776274847 +177,83.37180639203793,5.002726934883134,9.978309248856409e-07,5.987486490230915e-08,68.65647469364771,3.8193013208981674,0.007511045174653475,0.00041783305776889855 +178,87.46859187729096,3.2984968482926402,4.565488386961561e-07,1.7216750300994757e-08,64.44965799552914,0.9957204772508915,0.004656270163720239,7.193744224290876e-05 +179,29.599630987076374,2.220512967072282,6.357445510100987e-07,4.769245332415896e-08,30.240813958825424,2.05708689556552,0.0044319173350725076,0.0003014746588706379 +181,30.01986367498078,1.6130450775068679,3.5929109617421015e-07,1.930564176941511e-08,25.426548010717507,1.0498578404798777,0.0027816742644740313,0.00011485485701748429 +182,66.19150730792924,4.791127850755908,5.460077288943427e-07,3.9521578266284487e-08,50.943562768634074,3.314364419081382,0.004626872947048832,0.00030102219463831265 +183,35.06349634799953,2.810458081739047,7.530980318369091e-07,6.03633599145787e-08,38.63358571805416,2.987988496844758,0.00566191265034914,0.0004379021401960389 +184,81.91402706870191,3.7253985383550114,6.757014287903331e-07,3.0730476882410586e-08,62.43190329847359,2.0249829211354555,0.005670284569737795,0.00018391605581529128 +185,31.220765156813236,2.0785491127023197,8.51336077250207e-07,5.6678426652644924e-08,37.732464758091595,2.40497406801088,0.006230801600879671,0.00039713589793581724 +187,50.80889059536673,3.766697645057404,1.091279558073762e-06,8.090159209007729e-08,50.53677742297116,3.6805199911200295,0.0074063750208907975,0.0005393955197810074 +188,34.510496630378555,3.5433190963807064,1.1646811431596652e-06,1.1958207903966882e-07,39.947578220040285,3.8476444756868298,0.0073386871372231955,0.0007068428245336156 +189,1.272139672012257,0.05918148323753854,2.0835336987694625e-08,9.692851923525543e-10,14.483578614972934,0.3908047086215728,0.00185356895649716,5.001412255980767e-05 +190,41.84391257708448,2.5839046908060013,3.451666646885784e-07,2.1314396983209225e-08,50.58541326326525,2.4919253799545373,0.004594344768078142,0.00022632540871518926 +193,22.56944634776773,1.0846572814740374,4.847493089525375e-07,2.329640078640571e-08,24.70393920590753,0.8814911930748892,0.0036204650255391513,0.00012918620015407275 +194,76.39065691866357,5.221622859578134,9.142774175641622e-07,6.249470885729113e-08,59.89105969270161,3.9598984865168205,0.006552105346465895,0.00043321444265797225 +195,51.13940701231056,3.6855406146354706,1.0983785360080707e-06,7.915849911453033e-08,49.78621750551758,3.400443288632349,0.007296377693762441,0.0004983491376369693 +198,64.55391311794969,4.884569716531635,1.0572757939019842e-06,8.000037604969901e-08,53.5527621980613,3.8056490951689628,0.006853536564735283,0.00048703660008850947 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/X_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/X_data.csv new file mode 100644 index 00000000..ef7b8dc3 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/X_data.csv @@ -0,0 +1,165 @@ +1,2,2,0,1,1,1,1,0,1,2 +2,1,1,1,1,0,0,1,0,0,0 +0,0,1,2,0,2,2,1,1,0,2 +0,1,2,1,1,0,2,2,1,1,1 +1,2,2,0,0,1,1,2,1,1,2 +0,2,0,0,2,2,1,2,0,0,0 +1,2,0,2,1,0,0,0,2,0,0 +0,2,2,1,0,0,2,2,1,2,0 +0,2,0,0,2,1,0,2,1,1,0 +0,2,0,1,1,0,1,2,1,0,2 +0,0,2,2,0,2,1,1,2,1,1 +0,0,1,2,0,2,0,0,0,1,1 +2,2,2,1,0,2,1,2,1,1,2 +0,2,2,0,0,1,0,1,1,1,2 +1,0,1,0,2,1,1,2,2,1,0 +2,2,0,2,2,2,1,0,0,2,2 +2,1,2,2,2,0,2,1,1,0,0 +0,0,1,0,1,0,1,0,1,0,2 +1,0,0,0,2,1,1,0,0,2,0 +0,1,2,1,0,0,2,2,0,1,2 +2,1,0,1,1,2,0,1,2,0,2 +1,0,2,1,2,0,2,0,1,0,0 +2,0,1,1,1,1,1,0,2,2,0 +1,2,0,2,0,1,0,0,1,1,2 +2,2,1,0,1,0,2,1,2,0,0 +1,0,1,2,0,1,0,0,1,1,2 +1,0,0,2,2,1,1,2,2,2,0 +2,2,0,2,2,2,1,2,1,2,2 +2,1,0,1,2,0,2,1,2,0,1 +1,0,1,2,2,0,1,0,0,0,0 +2,0,2,2,1,2,1,0,1,1,2 +2,0,1,0,2,0,2,0,0,2,1 +0,1,1,1,1,1,1,2,0,0,0 +2,0,1,2,0,1,0,1,1,2,2 +2,0,0,0,1,1,0,1,0,0,2 +2,2,1,2,1,2,0,0,1,0,1 +0,2,1,1,2,0,1,0,2,2,1 +2,1,2,0,0,1,2,0,0,2,2 +2,0,0,1,0,0,1,2,0,2,1 +2,1,2,0,1,0,2,1,1,0,0 +0,1,0,0,2,0,0,2,0,2,0 +1,0,1,2,0,0,0,0,0,1,2 +0,0,0,2,2,1,2,0,1,2,2 +2,0,0,1,0,1,0,0,0,0,0 +2,2,2,0,1,1,0,1,1,1,2 +2,1,2,1,1,0,0,2,0,1,1 +2,0,2,1,1,1,0,0,2,2,2 +1,1,1,1,0,0,2,0,2,1,1 +1,2,2,0,1,0,2,1,1,0,2 +1,0,1,2,2,0,1,0,0,1,2 +1,0,0,1,1,0,2,1,0,1,1 +2,0,2,0,1,0,0,1,2,0,1 +1,0,0,2,0,0,1,2,2,1,2 +2,2,1,0,2,2,1,0,0,1,1 +0,0,1,0,2,2,1,2,2,2,2 +2,1,2,1,1,1,0,1,0,2,0 +0,0,2,2,2,1,1,2,0,0,1 +1,2,1,2,2,0,2,1,2,0,1 +1,1,1,1,0,0,0,0,1,1,2 +0,0,1,0,1,1,2,2,1,1,0 +0,0,0,1,0,0,0,0,2,1,2 +0,1,2,0,1,1,2,0,0,2,1 +1,0,2,1,0,2,0,2,0,0,0 +2,2,2,0,0,1,1,0,0,2,2 +0,1,0,1,0,0,1,1,0,1,0 +1,0,0,0,2,2,1,2,1,1,2 +2,0,2,2,1,1,0,2,0,1,2 +2,1,2,0,1,2,1,2,1,1,1 +1,1,1,2,0,1,2,1,0,1,0 +0,1,1,1,0,0,2,2,2,1,2 +0,0,2,2,2,1,1,2,1,1,2 +2,1,1,0,1,1,2,0,2,2,2 +1,0,2,2,2,0,0,2,1,2,2 +0,1,2,1,0,0,2,0,1,2,2 +0,0,2,1,1,0,2,2,0,2,1 +1,0,1,2,2,0,2,1,0,2,1 +0,0,0,0,2,2,0,2,0,1,1 +1,1,1,0,0,1,1,1,1,2,0 +1,2,0,0,1,0,2,0,0,1,2 +2,1,1,1,1,1,1,1,0,1,0 +0,2,2,2,1,1,0,1,2,1,1 +0,0,1,2,0,1,2,0,0,2,1 +1,2,2,1,0,0,0,1,2,1,1 +0,2,0,0,1,2,1,2,0,2,0 +2,0,2,1,0,2,2,0,0,0,1 +1,1,0,0,0,2,2,1,1,2,2 +1,1,0,1,0,0,0,0,0,0,2 +0,2,1,0,0,2,0,1,1,2,2 +1,1,2,1,2,2,0,0,1,1,1 +0,0,2,0,2,0,1,2,2,1,1 +1,0,0,2,2,1,2,0,2,0,1 +2,0,2,2,1,2,1,2,0,1,0 +2,0,1,0,2,0,1,2,1,1,0 +1,2,0,1,0,1,2,2,1,0,2 +2,0,2,2,1,1,0,2,0,1,0 +1,0,2,1,0,2,1,1,0,1,0 +1,0,2,1,1,2,2,2,0,2,1 +0,2,0,0,0,0,0,1,0,2,2 +1,0,1,2,2,1,2,1,1,1,0 +0,2,1,2,1,0,0,0,2,2,2 +2,1,2,1,0,0,2,2,0,1,0 +0,1,0,0,0,2,2,2,0,2,1 +2,2,2,0,1,1,1,0,0,0,1 +2,1,2,1,2,2,1,1,2,1,1 +0,2,1,2,0,0,1,0,2,2,0 +1,0,0,2,2,2,2,1,2,2,1 +2,0,0,2,0,0,2,1,1,2,2 +1,0,0,1,2,1,2,2,0,1,0 +0,0,0,2,2,0,0,2,1,0,1 +1,2,2,0,1,0,2,0,0,2,1 +1,0,0,2,2,0,1,2,1,1,1 +0,0,1,0,1,1,2,1,0,2,1 +0,2,1,1,1,2,2,0,0,1,1 +1,0,0,1,2,1,2,2,0,2,1 +0,1,2,1,1,1,2,1,1,0,0 +1,2,0,1,2,1,0,0,0,2,2 +0,1,2,1,0,0,0,1,0,0,1 +2,1,1,2,0,0,2,1,1,2,1 +2,0,2,1,0,2,0,0,2,0,1 +2,2,1,1,0,0,2,2,1,1,0 +1,0,0,1,0,1,0,2,1,0,2 +2,1,0,0,2,2,1,2,2,2,2 +2,1,0,0,2,2,1,1,0,1,0 +0,0,1,2,1,0,2,1,2,1,0 +2,2,2,0,2,2,0,2,0,1,0 +1,2,2,1,0,0,0,0,1,0,2 +0,0,1,2,1,2,1,2,0,1,0 +1,0,1,0,1,1,1,2,1,1,0 +2,0,0,1,1,0,0,1,0,0,0 +0,1,2,2,2,0,2,0,1,0,0 +2,2,2,0,2,1,0,2,1,2,0 +0,0,2,0,2,2,1,2,1,1,1 +2,1,2,2,1,1,2,0,0,0,0 +1,0,2,0,2,1,2,0,1,1,2 +1,0,1,1,0,1,0,0,0,2,2 +0,1,1,2,2,0,2,1,0,2,2 +1,1,0,0,1,2,2,1,0,0,0 +1,0,0,2,2,1,2,0,1,1,1 +2,1,1,2,2,1,0,1,1,1,2 +1,2,1,0,1,0,1,0,1,1,1 +1,1,1,0,0,0,1,0,0,2,2 +2,1,2,1,0,1,2,0,2,2,0 +0,2,2,0,2,2,0,1,2,0,1 +0,1,0,1,2,0,1,2,2,1,2 +2,1,1,2,0,0,1,2,0,1,2 +2,0,2,2,0,1,0,1,0,2,2 +2,2,2,1,0,1,2,2,1,0,0 +0,2,2,2,0,2,1,0,1,1,1 +1,2,1,2,1,1,2,2,2,2,0 +1,2,2,0,0,0,0,1,0,2,2 +0,1,1,2,1,1,1,1,0,0,1 +1,1,0,1,1,2,2,2,0,1,0 +1,1,1,1,1,2,2,2,0,0,1 +2,1,1,1,0,2,0,0,1,0,0 +2,1,2,1,2,0,2,0,1,2,2 +0,2,0,0,2,0,1,0,2,0,1 +2,2,0,0,1,1,2,2,1,0,1 +0,2,2,0,0,1,1,0,2,0,1 +2,1,0,1,2,1,0,0,2,0,2 +0,1,1,1,0,0,0,2,1,2,0 +2,0,1,2,2,0,0,1,2,1,1 +0,2,0,2,1,0,0,2,2,0,1 +1,0,0,2,0,1,1,1,0,1,2 +1,0,0,1,2,2,0,0,1,1,2 +2,2,2,2,0,1,1,0,2,2,1 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/Y_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/Y_data.csv new file mode 100644 index 00000000..4cbf0284 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev5/Y_data.csv @@ -0,0 +1,166 @@ +sim_id,qoi,qoi_err,qoi_kla,qoi_kla_err,qoi_sum,qoi_sum_err,qoi_sum_kla,qoi_sum_kla_err +0,75.31260976968582,3.238079989011666,7.642122854086134e-05,3.2857452640481335e-06,65.52420630134999,2.6240595440150822,0.06600471010113729,0.002643302365148521 +1,17.125618618661928,1.8934400925948427,2.5920128425771166e-05,2.86577737478525e-06,29.72112730736887,2.9880398691429733,0.03656459086991675,0.0036760535422599543 +2,74.77167153383817,7.167060797859717,9.991116521855821e-05,9.576747193385321e-06,73.1501948890811,6.89286959631731,0.08455785445255344,0.007967801930939619 +3,91.01711824270915,8.594547370800814,9.2356910955918e-05,8.721061065840268e-06,75.50828110485132,6.841107299017686,0.07606200037951794,0.006891274683523081 +4,82.36608997978375,3.843152957199135,8.357854134088118e-05,3.899725219340089e-06,68.20730825957243,2.9440715173526515,0.06870748939509123,0.002965661125155293 +5,19.98026923845076,2.4503164049641413,3.4004225903005566e-05,4.1701696595707025e-06,30.648159746523802,3.579363261462785,0.03998252163514974,0.004669512630614897 +6,3.1491043013869047,0.3255978884604246,5.359418576902211e-06,5.541307003538772e-07,21.52713115885259,1.7221517061604583,0.028083515565034637,0.0022466567369530547 +7,54.73252567106776,4.362459713855856,7.313455397721029e-05,5.829194642575174e-06,54.587010658759624,4.229018033143473,0.06309978443584315,0.004888527930844384 +8,53.52434221013517,2.784535758169979,8.101068649177434e-05,4.214477824774255e-06,59.537524852760626,2.9904941210179503,0.07324639634548537,0.0036790732936686416 +9,31.419958793082095,3.487028974332993,4.198387090959136e-05,4.659426044461732e-06,35.85314315803164,3.8059651118726507,0.04144438206090539,0.004399499132103051 +10,51.081238731014224,4.742231107942143,5.976233563392424e-05,5.548158466141561e-06,57.13364883076858,5.21684254003952,0.06179808707976729,0.005642749871021317 +12,46.57262900416803,3.4712301768653275,7.926130441727679e-05,5.907637976081125e-06,50.69433295927467,3.7054611869516565,0.06613397752022969,0.004834009494450023 +13,80.78105164271268,5.304047424243655,7.032289912029845e-05,4.617369845518886e-06,74.14233953724406,4.671832577492183,0.06917671230476229,0.004358940116623216 +14,61.2407395780285,4.860764380980748,8.183089359805109e-05,6.495034116275401e-06,67.45692387912007,5.223186864047021,0.07797672057863589,0.0060377342933341715 +15,52.425389339401015,2.704944367134757,6.133491571419469e-05,3.1646409661493144e-06,48.892786986077645,2.223168744370267,0.052884432435537046,0.002404669983077991 +19,28.65681137575307,3.127065938661847,3.352705451032754e-05,3.6585127636221233e-06,36.26608413494068,3.69736555585093,0.039226940117743136,0.003999227948435568 +20,64.30397811374857,4.533806217628798,7.523225077427789e-05,5.304313299610672e-06,62.97230211488626,4.120952056782897,0.06811341850406662,0.004457390354996942 +21,24.16671385380193,2.627487407962718,4.1128985849164486e-05,4.471683368897733e-06,29.54451522566868,3.1242355240986814,0.038542694162091426,0.004075763415845709 +22,14.392894894234168,1.367503221287946,2.4495066051686007e-05,2.327334561774688e-06,27.892284312959564,2.1994392501196756,0.036387256643124304,0.0028693082132351766 +23,45.58819910734964,3.1835487991029567,6.0915718474605225e-05,4.2539114550164026e-06,47.50750811412515,3.1891537559956915,0.05491623040251558,0.0036864973433796038 +24,24.269187875479428,2.6470328693923757,2.839366051819254e-05,3.0968878340573434e-06,34.4191273686651,3.459112357881669,0.03722913333679609,0.0037415171459511147 +25,24.826132451854786,2.580181342353536,3.757509106724982e-05,3.905181328463819e-06,30.960916729851284,2.9862786197398825,0.038089853140898654,0.0036738871479870426 +26,26.212929413621122,2.160407590231804,3.0667732494992575e-05,2.5275619146539296e-06,39.864666222737625,2.824241914273352,0.043119248817252445,0.0030548152376654474 +27,66.08858292481996,4.5402660463117295,8.830866241378959e-05,6.066778917148733e-06,60.259287634287965,3.908899368651131,0.069656624760219,0.004518485817490133 +28,27.542079681019636,2.2854240885256285,3.6802190148012534e-05,3.0538221096183615e-06,37.544317306445556,2.655254415255037,0.04339929542406153,0.003069337227605242 +29,50.288733811886146,6.1313864128505084,6.719663670841213e-05,8.192859793296849e-06,46.52391932544596,5.446890003841151,0.053779246341637964,0.006296323344197757 +30,39.42831439906267,4.025726023067068,4.612904090055274e-05,4.709886364731204e-06,42.11186757374552,4.025841576192741,0.045549918991452804,0.0043545149677077614 +31,72.2189972988533,4.119886894845398,6.286936028947973e-05,3.5865168893455937e-06,71.28495400003345,4.068885657808901,0.06651072275033496,0.0037963765241289904 +32,66.7330273333493,5.543513050297672,7.807409680028088e-05,6.485615770742502e-06,58.43165386002456,4.6361884197043235,0.06320206231099283,0.005014690669026578 +33,8.406418359354994,0.835150527788008,1.4306765559234155e-05,1.4213309755678713e-06,23.584697073393922,1.8637585275951123,0.03076773546515124,0.0024313913877934 +34,80.98034484066493,8.089116067135265,8.217240444994661e-05,8.208190745779772e-06,78.61110747430084,7.941759165644607,0.07918758552828141,0.007999998389287269 +36,56.4085531463549,5.609423088833227,8.537606135343415e-05,8.490032505301776e-06,58.177025896110045,5.665090068075801,0.07157264931799195,0.0069695124243939685 +39,28.029478469592917,1.3272877697517365,3.7453450611040196e-05,1.7735437705329637e-06,41.316166091841936,1.6298636680027918,0.04775935181021763,0.0018840381304936033 +40,60.85267617563756,2.4967554911279324,7.119439833832609e-05,2.9210712849458773e-06,58.24048608994043,2.2381906331198893,0.06299528744636801,0.002420918363823705 +42,21.537136809635207,2.82760938052715,3.665375121495202e-05,4.812268765481379e-06,30.90148003682123,3.685675667311236,0.04031294361321846,0.0048081980272752425 +43,62.185184885534284,1.9642192742419466,7.275336273962645e-05,2.298032202077326e-06,59.45672399573429,1.8184294907974763,0.06431082001868091,0.0019668875753687375 +44,67.28423637224662,5.975321407245854,7.871898209291246e-05,6.990808608632756e-06,62.00347866812817,5.355032182818668,0.06706549384463552,0.005792221430299511 +45,14.380988010961161,1.3878642880683594,1.9216126627410848e-05,1.8544884315914635e-06,30.136439928427166,2.041464604664391,0.034836178794164084,0.002359828371862962 +46,56.47520226988218,4.641447598962464,8.547690110199327e-05,7.024969215527278e-06,56.76999319658139,4.650713872924358,0.0698416239588519,0.005721568581631583 +47,41.68474671815817,1.303692702226581,5.569985106089609e-05,1.7420158465678258e-06,48.732764324911216,1.2256205251833852,0.0563325590357128,0.0014167540369751058 +48,0.9381656509138259,0.05372445738640994,1.7837249038055546e-06,1.0214576976916202e-07,15.812347523142105,0.8597194455257232,0.021803214358027487,0.0011854436750222072 +49,33.45478752087507,1.2296516456585427,5.693623389115698e-05,2.0927268977026095e-06,40.10062258585628,1.2647319887424269,0.05231380941082176,0.0016499232168574096 +52,57.15883612253174,4.900649422658998,7.637663225703399e-05,6.548333104136228e-06,63.82946800648272,5.23281249884061,0.07378359106421029,0.0060488628464039655 +53,4.941947434543911,0.8268806287477947,1.0436052565956147e-05,1.7461476111753207e-06,21.938519906242668,2.0145808201051527,0.031880593109987185,0.002927546237733248 +54,79.97961851040743,5.752222973330586,8.115694035908084e-05,5.836897267995567e-06,76.38524633663985,5.4750059665464414,0.07694539832364021,0.005515155545399454 +55,70.15079156369275,7.052698383168905,8.207269306075307e-05,8.251281799526723e-06,64.59361616906159,6.2577232126961455,0.06986708961860703,0.006768608640296083 +56,13.322909376213897,1.507109563266076,1.5587098786661256e-05,1.7632384174954158e-06,32.064617175485715,2.945542802440749,0.03468240187347779,0.0031860196131667227 +57,52.35923482654685,5.739364879303405,6.125751589179134e-05,6.714751208023037e-06,48.525561953824166,5.139533403044051,0.05248722576590783,0.005559128821912357 +58,49.74086928045618,3.363346599333538,5.8194174583650534e-05,3.93493684405405e-06,48.79280982893773,3.072957915763476,0.05277629509724866,0.003323836736444211 +60,45.682876356710615,4.929441404214104,6.104221830364863e-05,6.586801495630433e-06,45.5920838581519,4.784683998362735,0.05270209459855406,0.005530847624566601 +61,66.7527523155093,5.305116269799922,8.919612666757681e-05,7.088783703639952e-06,57.203232868066024,4.3190849315625055,0.0661239795859765,0.004992638868915617 +62,51.20617235296455,4.279649940015467,7.750206735178293e-05,6.47737768030869e-06,53.4528243594244,4.44507282247258,0.06576065714015779,0.005468577448332994 +63,58.2945350236022,5.81717955867183,7.789413825590824e-05,7.773013175577547e-06,52.66511866757536,5.1611466534584975,0.060878162331239605,0.005966019478050213 +64,71.37835357192431,4.943242828572972,8.350888171731617e-05,5.78333150056914e-06,66.13174271197445,4.579867632844314,0.07153079277251521,0.004953771806639803 +65,33.03707571023349,3.7382463493856184,3.865164829915289e-05,4.373552442091248e-06,39.99354134300499,4.453288427469041,0.043258660950912665,0.004816860116194742 +67,22.383485463345366,2.4205029224638235,2.618748685672375e-05,2.831859612413071e-06,35.45218780509604,3.6611406506144557,0.038346532203297104,0.003960039042764148 +68,59.20355585735416,4.7716156836967105,7.910878718437311e-05,6.375913138674938e-06,63.629374728455716,4.986375998374594,0.07355227713820964,0.005763993610073092 +70,84.41275639524054,7.323915284084283,8.565534232896172e-05,7.431725933805962e-06,68.03904050666505,5.641519109130843,0.0685379905269126,0.005682890005204139 +71,40.75938347611847,4.6056177234818,5.446335926711312e-05,6.154102229439813e-06,41.487142023049685,4.5244831573904385,0.047956991146633286,0.0052300685981577924 +72,81.66224790264314,7.084817507419924,0.00010911844441406885,9.46685016911224e-06,74.52459208083998,6.266917847133761,0.08614657694657063,0.007244233151257258 +73,46.97495314848562,4.150403958591455,8.931282547581215e-05,7.891105356424364e-06,53.092016743317416,4.639021883398794,0.07320705888139575,0.006396614199305299 +74,59.74714928383472,6.129209904080076,7.983513343438543e-05,8.189952096542662e-06,56.32264885605274,5.572727654072392,0.06510607361769219,0.006441785396575783 +75,1.598651294907113,0.11517582478093147,2.7207233003176715e-06,1.9601619885028966e-07,18.602084791950666,1.1860383304029811,0.024267606024317344,0.0015472626457660862 +77,36.62156836993086,4.1703822837505236,4.893437742626569e-05,5.572537435409822e-06,48.24548229026312,5.375386902222219,0.05576930291254874,0.006213671543764 +78,29.636339933724045,3.3999565951801793,5.0437661292899284e-05,5.786337298794387e-06,32.100092509337244,3.4695039824256657,0.041876605495470114,0.004526187876086026 +79,77.25335600582294,6.127830820133581,9.038232245655956e-05,7.169236519677038e-06,68.52204732919374,5.017132649950778,0.07411624383165595,0.005426735500663993 +80,62.12697849686431,4.998035186496232,7.26852764514261e-05,5.847436621479496e-06,63.5999050602217,5.012665873117301,0.06879225952836374,0.005421904503567123 +81,84.18336919848605,2.686193307444012,7.328473254167192e-05,2.338430499581426e-06,68.22733711165327,1.976757738188397,0.06365785831684838,0.001844365753545403 +82,37.61408824955905,4.282985157962108,4.400647978022728e-05,5.010864506468066e-06,38.80001951492727,4.182832222074506,0.0419676826399148,0.004524321828356214 +83,37.3613620419326,4.042058105521362,4.371080877361097e-05,4.728993249870536e-06,41.25512871970082,4.170434334924503,0.04462323148060668,0.004510912036329132 +84,66.94836512296996,6.295696456864278,6.793386897736279e-05,6.388371358080027e-06,72.74891210382019,6.676133839915493,0.073282400978691,0.006725091865922268 +85,16.04574595919682,1.6336817821913359,1.6281945072653157e-05,1.6577301617185085e-06,32.95660875593026,2.8323204619509355,0.033198289127722866,0.002853090689474935 +86,54.28752909933302,3.84092351983265,6.351356579442904e-05,4.493679353906313e-06,52.939705179345204,3.568075275395935,0.05726176478230567,0.00385937712446871 +87,46.70664374205604,1.5584965583905261,6.241020300856926e-05,2.0824893163909347e-06,50.369023294862025,1.457990930166669,0.058223994442425715,0.0016853623569030092 +88,65.75873029714259,6.338162109282551,8.786792153372063e-05,8.469158823016994e-06,64.80595579810146,6.220742869990142,0.07491234420282365,0.007190858082948214 +89,61.16262194933814,2.7465995652582897,7.155701842774383e-05,3.2133755787581548e-06,53.34985304592891,2.3551558109088186,0.0577053790838857,0.0025474326752710783 +91,26.496267942978616,1.9740369281634644,4.509364474515422e-05,3.35958709898266e-06,36.680644210050765,2.687968483543622,0.04785223980877928,0.003506626321402662 +92,34.5995200590322,3.424266901261162,4.047959454373668e-05,4.006209783722263e-06,36.9099105637183,3.565454940435814,0.0399232632517657,0.003856541346899103 +94,44.4144692000276,5.126746572367728,6.722262229652754e-05,7.75948366943624e-06,44.831030583930776,4.98417515912689,0.05515364373725573,0.0061318113251025265 +96,57.560138015840536,5.685807939379934,5.840743375010762e-05,5.769504069704928e-06,55.492753940507974,5.308800567235007,0.05589969358665771,0.005347731081057158 +97,57.544049389648926,2.2605551344035466,5.8391113527605e-05,2.2938311239547814e-06,60.68916310895485,2.1838112362848077,0.06113421181842748,0.0021998256665826097 +98,59.307933964393435,5.291337555724581,8.976432491223693e-05,8.008597026116968e-06,59.268911890030246,5.215612253712844,0.07291593364015218,0.006416538196113933 +99,84.27547476233224,7.105122154471195,9.859782075927348e-05,8.3126148222236e-06,72.21658408368367,5.865123216034689,0.07811240260831025,0.006343956472205381 +100,29.687471861191685,2.0585903137954014,4.493289186966563e-05,3.1157390702111748e-06,37.34453190513251,2.498524190880191,0.04594334352470446,0.0030738249845519276 +101,50.164794558848826,2.854574105539793,7.5925942771951e-05,4.320484755922841e-06,53.416650227395714,2.9491146744647585,0.06571616743170199,0.003628166740096689 +102,53.29374067552988,1.6021540394495308,6.235084537025086e-05,1.874435112018851e-06,52.52260906571691,1.2929743837458292,0.056810598222317064,0.0013985338796636128 +103,1.3489001325351777,0.09682389357051299,2.5646441160299294e-06,1.8408985435417209e-07,16.602132769985353,0.9839133935898835,0.022892200356541666,0.0013566897007512798 +104,62.14019471546058,2.4600484441183945,8.303277342302137e-05,3.2871581108727607e-06,59.83821354367979,2.159353032237857,0.06916989024020422,0.0024961007921921927 +105,95.6188063083289,9.039424321240705,9.70263369180765e-05,9.172486706328595e-06,74.86026820968827,6.983513412400134,0.07540923545947716,0.007034725093089421 +106,42.210671386770564,4.049147131523641,5.640260912184288e-05,5.410538506803702e-06,49.294861064963285,4.563475342534108,0.05698231827694274,0.005275142252142027 +107,54.52768157571368,3.4083245056173896,7.286080531756714e-05,4.554260534955298e-06,50.81474206160534,3.0705196156378554,0.058739222360303475,0.0035493623926294033 +108,60.52410899515532,6.312732654238973,7.081000397453975e-05,7.385563071612494e-06,63.75758455692329,6.465191589233407,0.06896281212351506,0.006993015748781508 +109,68.71506305701543,6.552832236409422,9.181820879934941e-05,8.756003294510852e-06,66.47489707660148,6.313152948426793,0.07684154830606171,0.0072976788018352294 +110,38.57601135972646,1.6427272428196142,4.513188394740937e-05,1.9219036045179222e-06,44.99835043553241,1.453619678873063,0.0486720529069963,0.0015722943892826193 +111,36.67731676579148,4.634166146457991,4.9008847602156636e-05,6.192250755013271e-06,40.224508109769225,4.963619431486486,0.04649745783082148,0.005737688191834873 +114,35.48945902998482,4.258416610426264,4.74216013140563e-05,5.6901666085744105e-06,35.82592176361299,4.103140780693136,0.04141291404242892,0.004743018688423916 +116,64.53863514154604,4.408865596618124,6.548866690964702e-05,4.473765673430849e-06,53.933743488165845,3.4536198240272635,0.05432925527382678,0.00347894621999484 +117,42.26001615569936,2.954250729203487,8.034854311572954e-05,5.616887159142015e-06,52.11295767881642,3.575404382964265,0.07185713477642225,0.0049300275031464915 +118,103.9499086654101,9.977380194856135,0.00010548007499958541,1.0124249504059449e-05,79.82328626633517,7.50163760428795,0.08040864844815367,0.007556648806665742 +119,9.487161623982757,1.0499379678004368,1.267691058237527e-05,1.402945397409531e-06,29.60505141394752,2.6476174174346307,0.0342219209274903,0.00306050993253832 +120,39.803352541485985,4.639622698473768,5.318590918788289e-05,6.199541891600007e-06,42.959179026276075,4.846251812347289,0.049658596440011055,0.005602017274325173 +122,48.98632865667196,4.813081523536677,7.41422987755142e-05,7.284745318434062e-06,53.65648885079557,5.187070667847342,0.06601123039549393,0.006381426072904557 +123,54.109153599243946,3.5018967452968637,7.230154993831767e-05,4.679292607017438e-06,55.77788417771532,3.3955384063465543,0.06447635378077898,0.003925067054646216 +125,104.28870514283255,8.426998810390216,7.690216474271921e-05,6.2140425457940025e-06,80.76793982506996,6.401149192487401,0.06935689627990552,0.005496783025258564 +126,18.008277074479345,1.0004436757790824,2.7256075233685406e-05,1.51420194065888e-06,35.68270581525143,1.545105348319121,0.043898871602558634,0.001900875501131325 +128,79.39406602048325,4.413776058530684,8.05627894327286e-05,4.478749219304209e-06,66.23418976324677,3.4348174985014714,0.06671991024979705,0.003460006320657325 +129,53.46709352090576,4.6059362050640225,7.144366150046421e-05,6.154532170308856e-06,58.635656088512434,4.883615778252965,0.06777981088886836,0.005645209348458699 +130,32.894047374809865,3.5406396903307837,4.39535725610839e-05,4.731061573796595e-06,33.401626997500976,3.485359343173008,0.038610555973812195,0.004028895419330892 +131,48.14511974971248,3.349318403632292,8.193753667039574e-05,5.700160285094965e-06,61.764372790971095,4.230407711441945,0.08057556354537915,0.005518836668668989 +132,56.94538258102278,4.74121569373512,7.609137806838758e-05,6.335292160737854e-06,53.121132980507994,4.268098510682875,0.061405291369784315,0.0049337018609823735 +133,80.38175734570504,6.075987738190555,9.404237858568086e-05,7.108582320480982e-06,71.65168416518917,5.277729609125131,0.0775013838177273,0.0057086075908556536 +134,62.35026378238889,5.803282891333765,8.33134522680819e-05,7.754442448756351e-06,59.40653380560084,5.2881530318364165,0.06867088289543254,0.006112831608231754 +135,68.00113356278577,2.3441542679845004,7.955770759357061e-05,2.7425357495598113e-06,61.62782710583062,1.8900121826200025,0.06665917121180495,0.0020443142585136564 +136,53.24175481243696,6.330626046907266,6.22900246721715e-05,7.406496161543325e-06,46.99275127777142,5.4719920517774545,0.050829278280186053,0.005918729999499465 +137,81.84899684477168,6.817351665953486,9.575896671438141e-05,7.975938330659862e-06,74.29917509650255,5.892155329352902,0.08036501630257815,0.006373195375126834 +138,7.522461688812619,0.9838491374137059,1.005163984198351e-05,1.3146357664853313e-06,27.688384131360035,2.3171333344321168,0.03200634473983343,0.0026784866880691922 +140,54.21229112881753,5.6207431812211,9.22631255609105e-05,9.565862705237508e-06,55.30751377328182,5.676666529557577,0.07215215995073124,0.007405571566759959 +141,77.41248975241376,4.752005696570745,7.855202276398796e-05,4.821956519490275e-06,65.82147974730985,3.925437905124919,0.066304165009661,0.003954224116440016 +143,49.112338506107946,2.193212772948186,7.433301851634268e-05,3.3194942578749642e-06,52.54404470228226,2.1600575433396743,0.06464263903660289,0.0026574242783089924 +144,61.170487761029314,3.387474222294758,7.156622100955274e-05,3.9631648811431685e-06,57.506265117054944,3.0409862255372224,0.062201124067225784,0.003289254851038263 +145,21.375696817446233,2.231043017108444,3.235274920882361e-05,3.3767495779456915e-06,28.302671163736658,2.682878254283017,0.03481952807383489,0.00330062679078081 +146,35.580247792922044,3.4777528740046924,3.610402663373602e-05,3.52894907082674e-06,41.19426299553102,3.9773228778483687,0.041496366773901894,0.004006491120749796 +147,40.0786709980159,5.301971264208152,5.355378600239167e-05,7.084582083280403e-06,41.2637742145192,5.195782234186251,0.04769879216122144,0.006006055956369926 +148,79.41772219986936,6.9175823373701455,0.00010611927974607105,9.24338843889771e-06,74.31015057919899,6.369989878792751,0.08589869674837214,0.007363379358321256 +150,29.79626840353003,1.117389090794966,3.981438838874501e-05,1.4930783492669444e-06,40.74858733978344,1.4002166160024754,0.04710333345706307,0.001618580532024783 +151,31.198902787561106,3.40981817523852,4.7220468823096906e-05,5.1608613909485015e-06,35.94654265402648,3.7828153610009774,0.04422344927838623,0.004653831242042645 +152,59.42586932936722,5.884796600690786,7.94058338218992e-05,7.863362980189587e-06,59.59519030921153,5.690517392450616,0.06888896254592501,0.006577944251566092 +153,71.80634064437203,8.767725984910182,8.400959175139853e-05,1.0257772140602232e-05,59.29542106959619,7.041563649972471,0.06413634356818948,0.007616442169823425 +154,15.367120622182405,1.7051070833856496,2.921728194208958e-05,3.2418951878870233e-06,26.37869494182532,2.7323278697743283,0.036372818969625076,0.003767527817131881 +156,46.21761942085536,4.509892854376381,6.995177311225894e-05,6.825860043487629e-06,50.32974647630617,4.691628191572958,0.06191848481984645,0.005771904873334349 +157,64.9722631744674,7.612250596095024,7.601414506071516e-05,8.905934513875365e-06,62.4955727049211,7.1432408760772015,0.06759778453698102,0.007726423436692495 +158,40.65279853590325,1.7894149039877147,4.75616146146015e-05,2.0935203753297235e-06,47.64181933715522,1.9659194023516389,0.0515313367916826,0.0021264186850412353 +159,22.050590154791095,2.138172553016319,2.9464369472133912e-05,2.85706213099064e-06,38.18386168226351,3.478423121465989,0.04413857575446069,0.004020877818238339 +160,74.73213648294407,4.094256264065211,8.743262955411226e-05,4.790062322349317e-06,63.61518687596935,3.183658580626295,0.06880878324087843,0.0034435750949594205 +161,4.181777963592859,0.4613685244090738,6.32924460234126e-06,6.982949042797594e-07,23.655010493251158,1.7739911003079891,0.029101716131018168,0.002182463010736976 +162,29.598669686114363,2.9071421940901705,3.462887687091129e-05,3.401202491631145e-06,43.19802272788136,4.027139300482611,0.04672474884663313,0.004355918639396586 +164,23.124334000066586,0.9963611392999256,3.499936329161535e-05,1.5080220465551773e-06,37.23184877582702,0.9875103027229971,0.04580470147820238,0.0012148903723589379 +165,72.61626966629937,3.045503342146517,8.495717124058257e-05,3.563076844094431e-06,63.14775456578867,2.478022510393874,0.06830318674084314,0.0026803302103024164 +166,106.83846798410707,9.816188439797811,9.300683289257176e-05,8.545354637601883e-06,84.76300170183609,7.4537480566013485,0.0790860581883189,0.006954538427025454 +167,81.67266588025196,7.869585142324063,9.555266646756928e-05,9.206995219736669e-06,68.22992451005504,6.272391805370721,0.07380026654793975,0.0067844745608835345 +168,6.220492611235887,0.6866887393002867,9.414899505984778e-06,1.0393237121969822e-06,25.19949932646016,1.8985581462049466,0.031001832624494238,0.0023357123534082473 +169,11.76569403929621,1.181450425360136,1.3765239266099264e-05,1.3822344633304625e-06,31.112255236113747,2.4804677172376017,0.03365228823358828,0.002682975372280253 +170,57.38903073649236,4.312859418128456,7.66842223090835e-05,5.762917863627284e-06,65.51295400770327,4.717243128871287,0.07572961453198795,0.005452891099386028 +171,54.2121417622394,5.649687595906064,6.34253258518131e-05,6.60983434860122e-06,50.0492534847986,5.109453280345668,0.05413531585025012,0.005526593263526322 +173,50.15094839771713,5.662562381832287,5.867394536546858e-05,6.624897164164277e-06,49.109034671196234,5.406461284375826,0.05311833679664302,0.0058478492461576815 +175,49.458325338868754,5.150002497876035,6.608707564229895e-05,6.881523025764196e-06,56.88229516463099,5.992694600596129,0.06575301559453041,0.006927247580039021 +176,49.44393716917436,3.8197401267511117,5.784678941323004e-05,4.468893768904645e-06,52.620667887053315,3.80720741360217,0.056916667382040737,0.004118031311946709 +177,49.35146795550623,5.488335474992379,5.773859572033249e-05,6.421060938933794e-06,52.11002153492478,5.659880854559052,0.05636432670495885,0.006121958199224692 +178,38.52404127555214,2.382788384603337,3.35366055929684e-05,2.0743055925615144e-06,45.513342994392204,2.7296441832232508,0.042465121197982486,0.0025468283242174794 +179,32.179282662644404,1.4454530254757902,4.87043233281895e-05,2.1877371303309638e-06,40.6533737708407,1.6035978843118648,0.05001406688766788,0.0019728363087154854 +180,61.22186460460808,3.0860327180606246,7.162631886736637e-05,3.610493815020104e-06,57.70743058509863,2.673624122616777,0.06241870835353757,0.0028919007944826543 +181,39.01076301107285,1.8839924703263076,4.5640516768318855e-05,2.2041709337730166e-06,43.134989455505476,1.595181103139618,0.04665656380187226,0.0017254129386294625 +182,56.85778191820166,2.893375248408679,5.769474141960106e-05,2.9359663911436065e-06,51.83135126519515,2.4323786567092704,0.05221144226723639,0.0024502158386156803 +183,20.208337041592895,2.170407645811726,3.0585915669445045e-05,3.2849761505107774e-06,29.768279115472293,3.0087430357048164,0.036622600897790826,0.0037015238594478935 +184,56.83153461709193,1.5794906066909817,5.766812541524669e-05,1.6027415591108402e-06,55.401592454645034,1.418463291040632,0.05580787338808618,0.001428865421456067 +185,53.317105327117645,4.447256393092118,9.07396698899299e-05,7.5687262942951486e-06,60.76504266268975,4.887616470886952,0.07927187365725134,0.006376207411159264 +186,49.86482632388414,2.4819996161793245,5.8339197739266244e-05,2.9038076951591343e-06,54.872577240902935,2.51294150960626,0.05935241973900303,0.0027181001286474362 +187,55.45571755332422,4.009134701421482,8.39338806117649e-05,6.067944807711234e-06,61.34638088131701,4.3102257339615235,0.07547175230254305,0.005302681010489095 +189,7.163502671379355,0.946808671770677,9.571992764931931e-06,1.2651416732449757e-06,27.60693331043392,2.3025156217318643,0.031912191789573295,0.0026615893657201337 +193,28.101988431570245,1.9075229598427133,4.2533190462067675e-05,2.8870924048424618e-06,35.92438727590241,2.300350299523548,0.04419618925903017,0.002830019519024787 +194,51.50350309865452,2.690912920272132,6.0256362511346944e-05,3.148225162467068e-06,52.89509457902915,2.701436647451345,0.05721349376038787,0.002921984165131206 +195,58.68195360837749,5.888954299708472,8.8816922118343e-05,8.913111497382374e-06,64.39566583290403,6.355347031768656,0.07922316992428469,0.007818705363371517 +197,56.01895940529496,2.695460070286345,7.485345878903744e-05,3.601718265220112e-06,53.67819908938798,2.4547733614802545,0.06204922400905247,0.002837591140945256 +198,61.169672127064075,6.947581509716685,8.173593208945038e-05,9.283473831354335e-06,54.612775193786604,6.038631394237074,0.06312954796072306,0.0069803460612818105 +199,71.68792089330172,4.1223003383970545,7.274320569886361e-05,4.182982819585871e-06,69.94356913730401,3.982746306285074,0.07045649191259379,0.004011953298634644 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/X_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/X_data.csv new file mode 100644 index 00000000..65a57991 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/X_data.csv @@ -0,0 +1,301 @@ +1,2,2,0,1,1,1,1,0,1,2 +2,1,1,1,1,0,0,1,0,0,0 +0,0,1,2,0,2,2,1,1,0,2 +0,1,2,1,1,0,2,2,1,1,1 +1,2,2,0,0,1,1,2,1,1,2 +1,2,0,2,1,0,0,0,2,0,0 +0,2,2,1,0,0,2,2,1,2,0 +0,2,0,1,1,0,1,2,1,0,2 +0,0,2,2,0,2,1,1,2,1,1 +0,0,2,1,1,1,1,1,1,1,2 +0,0,1,2,0,2,0,0,0,1,1 +2,2,2,1,0,2,1,2,1,1,2 +0,2,2,0,0,1,0,1,1,1,2 +1,1,2,0,1,0,0,2,1,0,0 +1,0,1,0,2,2,1,2,1,0,0 +2,2,1,2,2,1,0,0,1,2,0 +2,2,0,2,2,2,1,0,0,2,2 +2,1,2,2,2,0,2,1,1,0,0 +0,0,1,0,1,0,1,0,1,0,2 +1,0,0,0,2,1,1,0,0,2,0 +2,1,0,1,1,2,0,1,2,0,2 +2,0,1,1,1,1,1,0,2,2,0 +1,2,0,2,0,1,0,0,1,1,2 +1,0,1,2,0,1,0,0,1,1,2 +1,0,0,2,2,1,1,2,2,2,0 +2,2,0,2,2,2,1,2,1,2,2 +1,0,1,2,2,0,1,0,0,0,0 +2,0,2,2,1,2,1,0,1,1,2 +2,0,1,0,2,0,2,0,0,2,1 +2,0,1,2,0,1,0,1,1,2,2 +2,0,0,0,1,1,0,1,0,0,2 +2,2,1,2,1,2,0,0,1,0,1 +2,1,2,0,1,0,2,1,1,0,0 +1,0,1,2,0,0,0,0,0,1,2 +2,1,0,1,0,0,2,1,2,0,2 +0,2,0,0,0,0,0,1,2,0,0 +0,0,0,2,2,1,2,0,1,2,2 +2,0,0,1,0,1,0,0,0,0,0 +2,1,2,1,1,0,0,2,0,1,1 +2,0,2,1,1,1,0,0,2,2,2 +1,1,1,1,0,0,2,0,2,1,1 +1,2,2,0,1,0,2,1,1,0,2 +1,1,1,2,0,0,0,1,0,1,1 +1,0,1,2,2,0,1,0,0,1,2 +1,0,0,1,1,0,2,1,0,1,1 +2,0,2,0,1,0,0,1,2,0,1 +1,0,0,2,0,0,1,2,2,1,2 +2,2,1,0,2,2,1,0,0,1,1 +0,0,1,0,2,2,1,2,2,2,2 +0,2,1,2,2,0,2,0,1,1,2 +2,1,2,1,1,1,0,1,0,2,0 +0,0,2,2,2,1,1,2,0,0,1 +1,2,1,2,2,0,2,1,2,0,1 +0,0,1,0,1,1,2,2,1,1,0 +0,0,0,1,0,0,0,0,2,1,2 +0,1,2,0,1,1,2,0,0,2,1 +1,0,2,1,0,2,0,2,0,0,0 +2,1,0,2,2,0,1,2,2,1,2 +2,2,2,0,0,1,1,0,0,2,2 +1,0,0,0,2,2,1,2,1,1,2 +2,0,2,2,1,1,0,2,0,1,2 +2,1,2,0,1,2,1,2,1,1,1 +0,1,1,1,0,0,2,2,2,1,2 +0,0,2,2,2,1,1,2,1,1,2 +2,1,1,0,1,1,2,0,2,2,2 +0,1,2,1,0,0,2,0,1,2,2 +0,0,2,1,1,0,2,2,0,2,1 +1,0,1,2,2,0,2,1,0,2,1 +2,0,2,0,1,2,1,2,1,1,1 +2,1,1,1,1,1,1,1,0,1,0 +0,2,2,2,1,1,0,1,2,1,1 +0,0,1,2,0,1,2,0,0,2,1 +1,2,2,1,0,0,0,1,2,1,1 +0,2,0,0,1,2,1,2,0,2,0 +2,0,2,1,0,2,2,0,0,0,1 +1,1,0,0,0,2,2,1,1,2,2 +1,1,0,1,0,0,0,0,0,0,2 +0,0,2,0,2,0,1,2,2,1,1 +1,1,2,0,2,2,1,1,2,2,2 +1,0,2,1,0,2,1,1,0,1,0 +0,1,2,1,1,2,1,0,2,1,1 +1,0,2,1,1,2,2,2,0,2,1 +1,0,1,2,2,1,2,1,1,1,0 +0,2,1,2,1,0,0,0,2,2,2 +2,1,2,1,0,0,2,2,0,1,0 +2,2,2,0,1,1,1,0,0,0,1 +1,1,0,2,0,0,0,1,1,2,0 +2,1,2,1,2,2,1,1,2,1,1 +0,2,1,2,0,0,1,0,2,2,0 +2,1,2,2,0,2,2,0,2,1,0 +1,0,0,2,2,2,2,1,2,2,1 +2,0,0,2,0,0,2,1,1,2,2 +1,0,0,1,2,1,2,2,0,1,0 +0,0,0,2,2,0,0,2,1,0,1 +1,2,2,0,1,0,2,0,0,2,1 +1,0,0,2,2,0,1,2,1,1,1 +0,0,1,0,1,1,2,1,0,2,1 +0,2,1,1,1,2,2,0,0,1,1 +0,1,2,1,1,1,2,1,1,0,0 +1,2,0,1,2,1,0,0,0,2,2 +2,0,0,1,2,0,2,1,0,1,2 +0,1,2,1,0,0,0,1,0,0,1 +2,1,1,2,0,0,2,1,1,2,1 +0,2,1,1,2,0,2,2,0,2,2 +1,0,0,1,0,1,0,2,1,0,2 +2,1,0,0,2,2,1,2,2,2,2 +2,1,0,0,2,2,1,1,0,1,0 +0,0,1,2,1,0,2,1,2,1,0 +1,2,2,1,1,1,1,1,0,2,0 +2,2,2,0,2,2,0,2,0,1,0 +1,2,2,1,0,0,0,0,1,0,2 +0,0,1,2,1,2,1,2,0,1,0 +1,0,1,0,1,1,1,2,1,1,0 +2,0,0,1,1,0,0,1,0,0,0 +2,2,2,0,2,1,0,2,1,2,0 +2,1,2,2,1,1,2,0,0,0,0 +1,0,1,1,0,1,0,0,0,2,2 +0,0,1,2,1,2,2,0,0,0,1 +2,1,1,2,2,1,0,1,1,1,2 +1,2,1,0,1,0,1,0,1,1,1 +0,2,2,0,2,2,0,1,2,0,1 +0,1,0,1,2,0,1,2,2,1,2 +0,0,0,2,1,2,0,0,1,0,2 +2,1,1,2,0,0,1,2,0,1,2 +2,2,1,1,1,0,0,0,1,1,1 +2,0,2,2,0,1,0,1,0,2,2 +2,2,2,1,0,1,2,2,1,0,0 +0,2,2,2,0,2,1,0,1,1,1 +1,2,1,2,1,1,2,2,2,2,0 +1,2,2,0,0,0,0,1,0,2,2 +0,1,1,2,1,1,1,1,0,0,1 +1,1,0,1,1,2,2,2,0,1,0 +1,1,1,1,1,2,2,2,0,0,1 +2,1,1,1,0,2,0,0,1,0,0 +2,1,2,1,2,0,2,0,1,2,2 +0,2,0,0,2,0,1,0,2,0,1 +2,2,0,0,1,1,2,2,1,0,1 +0,2,2,0,0,1,1,0,2,0,1 +0,0,0,0,1,2,0,1,0,2,0 +2,1,0,1,2,1,0,0,2,0,2 +2,0,2,2,0,1,2,1,2,1,2 +2,0,2,0,0,0,2,2,2,2,1 +1,0,2,1,1,2,0,2,0,1,0 +0,1,1,1,0,0,0,2,1,2,0 +0,2,0,2,1,0,0,2,2,0,1 +1,0,0,1,2,2,0,0,1,1,2 +1,2,2,2,0,0,2,0,1,2,1 +1,0,0,1,1,0,2,0,2,1,2 +0,2,0,1,1,2,0,2,2,0,0 +0,0,0,1,2,0,1,0,0,0,2 +2,0,2,1,1,1,0,2,1,0,0 +1,0,1,2,1,0,0,2,0,2,1 +0,1,2,2,1,1,2,0,2,1,0 +2,2,0,0,2,1,2,2,0,1,2 +0,2,0,1,1,0,1,1,2,0,1 +2,1,2,1,1,1,0,0,0,2,1 +1,1,1,0,0,2,1,1,0,1,2 +1,2,2,0,1,0,1,2,2,0,0 +2,0,1,0,2,2,1,1,1,0,0 +0,1,0,1,2,1,2,0,1,2,1 +2,2,1,2,2,0,1,0,1,1,0 +2,0,2,2,2,1,1,1,0,1,2 +1,2,2,1,0,1,1,1,1,2,1 +2,2,2,1,1,2,0,1,2,0,0 +0,2,0,1,1,2,0,1,0,2,2 +1,0,0,2,2,1,0,2,1,2,1 +2,1,2,1,0,1,2,0,1,0,0 +0,2,1,1,2,2,2,1,1,0,1 +1,0,0,1,0,2,1,0,2,2,0 +2,0,2,2,0,0,0,0,2,2,1 +2,0,2,0,0,1,1,0,1,2,0 +1,1,1,1,1,1,1,0,0,0,0 +1,0,1,0,1,2,2,0,1,0,0 +1,2,2,2,1,2,1,0,2,1,2 +2,2,1,0,0,2,0,0,0,0,1 +2,0,2,0,0,2,1,2,0,1,0 +0,0,2,1,0,0,0,2,0,0,2 +1,1,1,2,0,0,2,1,0,1,0 +0,2,0,2,0,1,0,2,1,1,0 +1,2,2,0,2,1,1,0,0,1,2 +1,0,2,1,1,0,1,2,1,2,0 +2,2,2,0,1,2,0,0,1,2,2 +1,0,1,2,1,0,1,1,0,2,2 +1,2,0,2,0,1,2,1,1,1,2 +2,1,2,0,2,2,2,2,2,2,0 +0,1,0,2,1,0,0,2,1,0,1 +1,0,1,1,2,2,0,0,1,0,2 +2,0,2,0,2,2,2,2,1,2,1 +2,0,0,0,1,2,2,2,1,0,0 +2,0,0,0,1,1,1,2,2,2,0 +2,1,1,1,2,0,2,0,0,2,2 +2,1,0,2,2,0,1,1,2,0,0 +1,1,2,0,1,1,2,2,2,2,0 +0,0,0,1,0,0,2,1,0,0,0 +0,0,2,0,0,2,1,0,1,2,2 +1,2,0,2,0,0,1,2,2,1,1 +1,2,1,1,2,2,2,1,0,1,2 +2,2,2,0,1,1,2,2,2,0,1 +2,1,1,2,1,1,2,0,0,0,1 +0,2,0,2,2,1,0,2,2,2,2 +1,2,2,0,1,2,0,0,2,0,1 +2,1,2,1,2,1,0,2,0,0,0 +1,0,2,1,1,2,2,1,2,2,2 +0,0,2,0,1,0,2,0,0,1,0 +1,2,0,2,2,0,2,0,0,0,0 +1,0,0,2,0,0,0,2,1,2,1 +2,1,1,2,0,2,2,0,2,1,2 +1,1,2,1,1,2,0,2,0,0,1 +1,2,0,0,0,1,2,0,0,1,1 +2,0,1,1,2,0,0,2,2,0,1 +0,1,1,0,1,1,2,0,1,0,2 +1,1,0,1,1,1,2,2,1,0,2 +2,1,0,0,2,1,0,0,1,0,1 +2,1,0,0,0,0,1,1,0,2,1 +2,1,2,0,0,0,0,1,1,0,1 +1,0,0,2,0,1,1,0,1,1,0 +2,1,1,1,0,0,0,1,1,2,2 +1,2,1,1,2,0,0,1,1,1,1 +2,1,2,1,2,0,0,2,1,1,0 +1,1,0,1,1,2,1,2,2,0,1 +0,0,2,0,2,1,2,0,2,1,1 +2,1,1,0,2,1,2,0,1,0,0 +0,2,1,1,2,0,0,1,0,0,1 +2,1,0,1,0,1,1,1,2,0,0 +2,2,2,0,0,1,2,1,1,2,2 +0,0,1,0,0,2,0,0,0,2,0 +0,1,1,0,0,1,2,1,1,0,0 +0,2,2,0,1,0,1,0,0,0,2 +1,0,1,2,2,2,0,2,0,2,0 +2,1,0,0,2,0,0,2,1,1,1 +0,0,0,2,1,0,1,1,0,0,2 +2,1,1,2,1,0,2,2,1,0,0 +0,1,1,0,2,2,2,2,0,2,0 +2,1,1,2,0,1,0,0,0,2,2 +0,0,0,0,2,2,1,1,1,0,1 +0,0,2,1,2,2,1,0,0,0,0 +1,1,1,0,0,0,2,1,1,2,0 +1,0,2,0,1,2,2,0,1,0,2 +0,2,1,1,2,1,0,1,1,1,2 +1,2,2,0,0,1,1,0,1,2,2 +2,0,1,1,0,0,2,2,1,2,2 +1,1,1,1,0,0,0,0,1,0,0 +2,0,1,2,1,1,0,0,2,1,2 +1,1,2,2,0,2,1,0,0,0,0 +0,2,2,1,1,2,0,1,0,0,0 +0,1,2,2,2,2,0,0,2,0,2 +0,0,0,0,2,0,0,2,0,1,0 +1,0,1,0,0,1,2,1,1,2,2 +2,2,1,0,0,1,2,1,0,0,2 +2,0,2,1,0,1,0,2,1,1,0 +0,1,1,0,0,2,2,2,0,1,1 +2,2,2,0,2,1,0,0,1,1,1 +1,2,2,2,1,2,0,1,2,1,0 +0,0,1,1,2,1,0,0,0,2,1 +0,0,2,0,0,1,2,1,0,1,1 +1,0,1,2,0,1,2,2,2,1,1 +0,0,1,0,2,1,2,2,2,2,2 +0,1,0,0,1,1,1,2,1,1,0 +1,1,1,1,0,1,1,2,2,0,1 +2,1,1,2,2,2,1,0,1,0,0 +2,1,0,2,0,2,2,0,1,2,1 +2,2,2,1,1,2,0,0,2,2,2 +0,1,1,1,1,1,1,2,2,1,0 +0,2,2,2,2,0,0,2,1,0,1 +0,2,1,1,1,2,0,2,1,0,1 +2,0,0,1,2,0,0,2,2,0,0 +1,1,2,0,0,2,2,1,2,2,0 +0,0,2,0,0,1,2,2,2,2,0 +2,2,1,0,0,1,2,1,1,1,1 +0,1,0,2,1,0,0,2,1,1,1 +1,2,0,0,0,1,1,2,0,0,2 +2,2,1,2,0,1,1,0,1,1,0 +1,1,0,2,0,0,1,2,0,1,1 +1,1,0,0,2,0,1,2,0,2,1 +2,0,2,1,1,0,2,1,2,0,2 +0,0,1,2,2,1,0,0,2,0,1 +2,0,1,1,1,2,0,2,2,2,2 +2,0,1,0,2,2,2,2,1,1,2 +0,2,0,0,2,1,1,0,2,0,0 +0,2,1,0,1,0,2,1,1,0,2 +2,0,2,1,1,1,0,2,0,0,0 +2,0,0,0,2,2,0,0,2,0,1 +1,2,2,2,2,0,1,2,2,1,0 +2,1,1,0,0,1,2,2,0,2,2 +1,1,1,2,2,2,0,1,0,0,2 +2,1,0,2,1,0,1,0,0,1,2 +0,0,1,2,0,0,0,0,2,1,0 +1,2,1,1,2,0,0,1,0,1,2 +2,1,1,2,1,0,2,0,1,1,0 +2,0,2,2,2,0,0,0,1,2,2 +1,1,1,1,2,0,1,1,2,1,2 +1,2,0,0,0,1,1,0,1,0,2 +0,1,2,0,0,1,2,0,1,2,1 +2,2,1,0,0,2,0,2,1,0,2 +1,1,1,1,0,2,0,1,2,1,0 +1,0,2,2,2,2,2,1,2,1,0 +1,0,1,1,2,0,2,1,1,2,2 +0,0,0,1,2,1,0,1,0,0,0 +2,0,0,0,1,2,1,1,1,0,2 +0,2,2,2,0,1,1,0,2,2,0 +2,1,2,2,1,0,0,1,1,0,0 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/Y_data.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/Y_data.csv new file mode 100644 index 00000000..d5b7754a --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/Y_data.csv @@ -0,0 +1,302 @@ +sim_id,qoi,qoi_err,qoi_kla,qoi_kla_err,qoi_sum,qoi_sum_err,qoi_sum_kla,qoi_sum_kla_err +0,17.338820036625307,1.504621568901604,0.26528828560031775,0.023021086535762673,37.0771160590263,2.590384166424954,4.586223480296684,0.32041544623195456 +1,10.597655943331029,1.092778160806681,0.1691856625129047,0.017445593450507897,31.43211477913992,2.5229477181729596,3.9714625530689522,0.31877563620772836 +2,12.474378628948209,1.2825944016295003,0.19636548697594317,0.020189965509314577,32.726677145542894,2.502456952602995,4.106057536325839,0.3139711429874244 +3,16.059254635411634,1.0550748828288026,0.24571061475048947,0.01614290973978449,33.374223505090924,1.1262183889758282,4.1281972209501205,0.13930666050833332 +4,15.58267003435941,1.5411112254586703,0.23841882043678628,0.023579394271044194,34.46774971135103,2.6338904063168203,4.2634606687597705,0.32579696229653543 +6,7.26227820844476,0.4618471895982591,0.11756940090956995,0.00747686825460577,25.439075724789262,0.9395901989271344,3.2367714862916444,0.11954989236196535 +7,13.361344436669967,1.3272092039281531,0.21032834858896143,0.020892337699801918,35.54677903611469,2.6731295802528034,4.459889316460897,0.33538515667967417 +9,15.083251960678808,1.4720848658398604,0.23743280739611886,0.023172804069896826,36.8589548821891,2.686470685991622,4.624511755211787,0.3370582618826082 +10,8.95462942883682,0.8822838343656652,0.1389766611799275,0.013693125158066075,27.554423847511462,1.690055915108808,3.4327206486137056,0.21054658479566396 +11,13.877544851036742,1.2763104327186856,0.21232987183680066,0.01952786559236987,35.93722722696279,2.4349724623180538,4.445225475718888,0.3011918964646552 +12,11.043656345668017,0.9012139899775681,0.17878575441856107,0.014589753433780432,27.831182621184404,2.1131816858263806,3.541128403444577,0.2688727888847519 +13,11.754283150122996,1.2007654829276986,0.1772781338648371,0.018109948629279435,32.994577044134985,2.3246013235528915,4.0520246354545995,0.2854815146757893 +14,8.578941327132195,0.6643367610093042,0.13504528924516573,0.010457648167258018,27.57840786252366,1.4944790889737802,3.460127172837823,0.18750493976206256 +16,12.362094007455191,1.2104255762463467,0.1973540349177611,0.01932377890799164,32.08501529278876,2.3732270088886405,4.0539579040151645,0.29985843244614935 +17,13.82955207430303,1.4469439180958337,0.21769770753632714,0.022777048179918654,34.666167197800874,2.6230906364411055,4.349393471051291,0.32910627883997706 +18,15.10866322227264,1.4848400325347466,0.23448809334394685,0.02304487849305996,35.80583520457451,2.818979288315099,4.460681200155409,0.35118767215373115 +19,10.962684472512741,0.9739929025406403,0.17014562669334904,0.01511679308231213,33.46508720043694,1.999692809684587,4.169115233941133,0.2491238019529113 +20,13.090136136200929,1.302964452712956,0.20316033384512397,0.020222149750561625,32.42051625160412,2.5953206303417775,4.038939086788491,0.32332433744380307 +21,15.034094303258533,1.6067424427980324,0.24338668145244843,0.026011524419974813,36.27547876865312,2.6844848354005424,4.615544288231032,0.3415629254101734 +22,9.565553654415027,0.8824012725126623,0.15485674970379273,0.014285194347609144,27.56964962358593,1.961724480980642,3.5078519904786045,0.2496019796889785 +24,12.722374477577146,1.3743748310075072,0.19745240618003654,0.021330422072860872,34.513232283983086,2.7023518144989542,4.299646610913613,0.3366580598740068 +26,10.729669964395917,1.0481268633024423,0.16652536280358102,0.016267015365317928,32.12046270945523,2.543093472788997,4.0015551363036534,0.31681762620261145 +27,14.937833667089699,1.2185924891923514,0.2351437072880238,0.01918245724032468,32.37771545549025,1.8945408308079816,4.062272688126862,0.23769871855574085 +29,17.625754334546706,1.6237069284281218,0.27745542776541027,0.02555954723082045,35.89927189289482,2.795073047004133,4.504103862457908,0.35068397332467866 +30,11.5908051204751,0.9243135786937261,0.17989055371985693,0.01434544708100324,32.25332622745972,2.0943485050203656,4.018110599105033,0.2609133664817957 +31,9.092010545234386,0.8995495482744841,0.13712634670982551,0.013567069970459858,31.160194109448163,2.1502131242435825,3.8267548554790256,0.26406570140777513 +33,8.370462251598445,0.7998123966467671,0.13550941478463696,0.012948163022466822,26.086892701649063,1.8558795273884685,3.3191919280176556,0.2361346909780338 +34,10.4649945236064,1.1750930401935467,0.16011716738680173,0.017979232438900077,30.98740096516362,2.514791578933165,3.8329627469146392,0.31106521160460826 +36,13.153796669146583,0.719895495951242,0.20999405000678475,0.011492786043366168,29.792533776530426,1.0335073879373196,3.764309927276423,0.1305844662124958 +40,12.807076831234413,1.3748444019417796,0.19876699439375536,0.021337709856364472,33.198453004939594,2.5631631756510718,4.135851860403901,0.3193179871049399 +42,12.340270016659181,1.1773505171780752,0.19977663335409646,0.019060127718600498,35.98781146035268,2.7047531225731665,4.578945245505339,0.3441419733043901 +43,13.814184640747337,1.5098150308276144,0.21439739897125856,0.0234324662624199,33.90804040683345,2.762380513951192,4.224252014947403,0.34413641461150696 +47,15.474233610190858,1.4965564073596809,0.24358743976094444,0.02355802251082116,35.156486657480066,2.6288515465502797,4.4109114417138615,0.32982907189273036 +49,12.34682040369392,1.2068775395370035,0.19988267757089243,0.01953814068848483,28.94472835072957,2.054363957505438,3.6828115099477596,0.2613890562953636 +50,11.253938097592913,1.0736066699899431,0.17715391689351667,0.0169001841970682,31.739327595502786,2.265973560948269,3.9821795745364232,0.28430071820823083 +51,7.480210418104828,0.7342337941014727,0.12449392920768548,0.01221993030617419,27.606899844431233,1.955574849020566,3.5615153408561184,0.2522851122084268 +52,9.712781863366041,0.9683053786098328,0.15289429736725946,0.01524263311810661,31.667607110123118,2.209146298866711,3.9731876265027783,0.27717132871039657 +53,7.039937994044074,0.6452313144379033,0.11716442380394014,0.010738468895654113,24.602440794570647,1.7423985806623814,3.1738884499199167,0.22478171074561062 +55,16.960590761335943,1.7180542913085337,0.2632297674827453,0.026664344301899543,35.65893924551784,2.7407079449917973,4.4423772093120615,0.3414363626574345 +56,9.335425615636726,0.9001216272777203,0.14488681897005193,0.013969985368848189,31.118823832453067,2.4938867299215617,3.8767745996506493,0.3106877297490583 +57,15.141244563585165,1.3879015499357852,0.23499329657300091,0.02154034030482379,32.20646740018359,2.452028006290884,4.012268988887207,0.3054726806041373 +58,16.41347126244998,1.6204595355831364,0.25473856317070337,0.02514967901488849,35.762736835535264,2.8875171331657454,4.455309458316512,0.35972589160629825 +59,17.485704744720927,1.5613696668537191,0.2752507612682162,0.024578259538114277,34.55431982351372,2.5900395619143692,4.335358765239908,0.3249593907336177 +60,16.35927636476525,1.639236297947587,0.25751932835048796,0.025804016084990222,33.708730452645725,2.3939269740282363,4.229268592389004,0.3003542414020464 +61,18.73595398907213,1.7840180498394997,0.2949315268596961,0.028083073202000236,36.18256214346029,2.8962320997447755,4.539646236380097,0.3633758466069813 +62,10.73432992682054,0.8246234001641618,0.1713678702939686,0.013164674166351057,29.785748384542458,1.4823702963963712,3.763446498795022,0.18729834247796956 +63,15.968517911980264,1.5791304871018503,0.25136849612640483,0.02485788962495669,34.14565564930459,2.810706515060176,4.284089890583612,0.3526457213250796 +64,12.67025119951776,1.1901889419017821,0.196643448175463,0.018471840362942468,31.72395570019022,2.3317099428538457,3.952159493169173,0.29048362294590896 +65,9.602322487420588,0.9366325753117479,0.14902957647840456,0.014536686952292021,30.086027770722243,2.135961386554784,3.748115297786622,0.2660979245727567 +66,12.529059166625782,1.1032887938638818,0.19445235836911182,0.017123161849256555,31.705815367623778,2.368533843943811,3.949901845269315,0.29507130134649606 +67,12.871383243708092,1.3782233545631883,0.19976492954162353,0.021390140135211975,35.40913362223645,2.7659305898095643,4.411256518929699,0.3445785902409739 +68,11.731263675099486,1.0170319377328139,0.18466773960654867,0.016009612796227094,34.086903048750166,2.1948067282597155,4.276718486599872,0.2753717606975819 +70,17.482671883996094,1.723065845383837,0.2674894759002379,0.026363360416621424,34.61081995976255,2.765205058742157,4.2811587746606925,0.34203991453345917 +72,15.422086098504769,1.5469402582916159,0.2427664322490213,0.024351126365728542,36.23478843620044,2.9573523611555492,4.546199461586774,0.3710443552245433 +73,12.339540949930846,1.1964994324198077,0.20255544433120065,0.019640720441645092,32.73776691809578,2.2849733461438486,4.1944160923739755,0.2927545118666524 +74,17.246436552609545,1.7798470097458046,0.27148454848730386,0.028017437709136783,36.366462662858744,2.8170668252907296,4.562721179083865,0.35344351706155624 +75,5.554842907404228,0.4512950425316966,0.08992764171591107,0.00730603899506531,22.058910948068565,1.0800079159160714,2.806692143527018,0.13741610996503142 +76,16.070757818434554,1.5051883864985578,0.2458871039702589,0.02302980465932061,35.15294878229135,2.696973219770903,4.34821949783854,0.33360022261528843 +77,11.422643680906951,1.1114030649655686,0.17981018252412245,0.017495213328186446,35.920925424029555,2.571440850624473,4.50683172653295,0.32262674392972834 +79,14.687365081863936,1.4694039331200766,0.22794923864015762,0.0228052823595413,32.77815664648524,2.509627701135548,4.083491484582299,0.31264855609742603 +80,12.487741405139431,1.1144766549081662,0.19381110222555759,0.017296798667171983,36.38150704346333,2.405138593215322,4.532398241093534,0.2996315110435728 +81,16.452159178381972,1.5703307601787433,0.2481313077510264,0.023683713541795177,34.712609809040394,2.608341611210837,4.263012415200463,0.3203271875219216 +83,11.666503592609047,0.9682604979526291,0.18106519424724488,0.015027490777510609,28.796282281911193,1.3747173775612727,3.5874309453707935,0.17126181821395103 +84,10.50274471107167,1.0664989905826947,0.16069475517928702,0.01631771493121969,31.91771504671246,2.5706125551312895,3.9480372322358046,0.31796994435403614 +85,9.11396662792082,0.9854019179418105,0.13944608540680103,0.01507690839994735,28.630427281645503,2.266703274671095,3.541418698591919,0.28037811947801244 +87,13.882730056265967,1.412714583672016,0.21853505726754435,0.022238252936864895,33.17221524239084,2.5943508047271795,4.161957041556602,0.3255006191508151 +88,14.16908969909729,1.2853112249218694,0.2230427888658414,0.02023273239532168,34.81433816905362,2.6670110280513875,4.367986244845744,0.3346169451451916 +89,17.113458679370357,1.6855862679922686,0.26560243139045087,0.026160451810760113,34.22010653325241,2.522742326031171,4.263129105675904,0.314282371557592 +93,10.595790964027094,1.0002693720902764,0.16211830050099305,0.015304376161913158,30.308612176497,2.3887503828522747,3.7489994856447897,0.29547456361566804 +96,17.45904233732039,1.7087966024614132,0.2671276396288684,0.02614500808246539,37.67143403661019,2.7549764384036606,4.659736481559069,0.34077450312588026 +97,11.273607827627634,1.3723128217878182,0.17248907115425524,0.020996735701872264,31.83279617861323,2.5458908162727503,3.9375322038928693,0.3149119235527291 +98,15.547533181256313,1.4802499935417752,0.2482081012751089,0.02363140416078583,34.45958573379212,2.7920097913931725,4.353988545309432,0.35277204851005334 +99,15.171598106600793,1.0079643740648485,0.2354644539296471,0.0156436902198495,31.347522806564534,1.1373963846989612,3.9052625745668066,0.14169641285601914 +100,12.70549187935016,1.3433826096330368,0.20283707922377053,0.021446458539778217,37.32625056868356,2.7962590159804264,4.716200932006327,0.35330951210948525 +101,12.153528676646806,1.2101956757471197,0.19402525163468617,0.019320193069954424,32.11367806179119,2.4704100659465253,4.057588321829463,0.31213824260264367 +102,15.166704702794275,1.3909192436390563,0.2353886330469906,0.021587192857960166,34.02469076273311,2.510002559699467,4.23878427617634,0.3126952558484278 +103,4.7307079335603515,0.4401479898323269,0.07765504353702386,0.0072250732434118135,19.544227793620873,1.212096367197119,2.504034345978217,0.1552955156963357 +106,8.141802006701713,0.3961555172547826,0.1281642127005483,0.006236083846566798,25.7677902074265,0.5610664067794122,3.232959725948724,0.0703942822453522 +113,12.46201834106653,0.7034086332895574,0.1879521981457908,0.010608811125388229,31.344052163613124,0.8083674199464524,3.8493256443943653,0.09927463824556423 +114,17.760130760231423,1.7688305731460117,0.27957071134206063,0.02784400792168331,36.42446020734835,2.9607415840908704,4.5699966394118645,0.37146958424198 +115,18.44240080317489,1.8568466849391299,0.28217334749962825,0.02841021895547691,37.35433837130185,2.888868424688692,4.620514266985601,0.3573362119023157 +116,16.7781112724354,1.7361493054329906,0.2567095133191839,0.026563540794925813,34.700463577826156,2.774140726800582,4.292247173101167,0.34314520512640817 +118,18.609250794683888,1.8078175480480425,0.2847261941239286,0.027660060891501102,37.41467407758871,2.942476370085627,4.627977442719996,0.3639672027679074 +119,8.205471735824581,0.8692634703801634,0.1291668909344809,0.01368355939631297,29.532426789672286,2.375823632963905,3.70529646566873,0.2980835599108949 +120,13.409593747912577,1.3093614140189738,0.2110871799536227,0.02061131855455185,32.28086742021238,2.435426968237612,4.050123951186108,0.30556121578218814 +123,12.777526957535901,1.2253148922364205,0.20113726834347775,0.019288277857215687,35.46527857675457,2.5287602495731143,4.4496540448387645,0.3172711092227426 +124,14.008044222890621,1.2940610434565392,0.22363072526601774,0.020658973164418545,32.75260642084775,2.426249692325562,4.138308380570909,0.3065578753059916 +125,18.324746141287285,1.801660552522969,0.2724028235432995,0.02678222212683605,37.07884991534111,2.820659806486757,4.520776888105712,0.3439042389795965 +126,8.890851298865387,0.794841848384265,0.1419381733819942,0.012689268585745886,28.421999175873836,2.232363820625982,3.5911418093303222,0.28206091345929624 +127,12.628007867810577,1.177415976508642,0.19598869614837383,0.018273683741393005,30.475791316803544,2.1880494206799197,3.796672013904811,0.2725870483289356 +128,14.294665463609682,1.4440325327163597,0.21871239258168637,0.022094102936525428,31.722048172682186,2.5719417607424737,3.9238366382883925,0.3181345434383401 +129,7.171795272825239,0.6308024650886044,0.11289521524582426,0.009929812182957149,24.98964404520646,1.7138778734333762,3.1353346075644533,0.2150322989792806 +130,16.61386899445647,1.614337926134785,0.26152699479851477,0.025412078700763178,35.12199158229414,2.8001283061196824,4.406583514315918,0.35131832438388094 +131,6.3706142990985635,0.5472960753177641,0.10313420734832414,0.008860204724799184,22.745497360418266,1.6398454927372554,2.8940507939123874,0.2086477193683415 +132,16.158637021584536,1.4418456140596245,0.25436125694049777,0.022696819181992258,33.34611438227745,2.5926132677769598,4.183775323648502,0.32528261881251713 +133,13.727159289322595,1.2952723453881787,0.21304664435181356,0.020102733631225493,30.530232714612584,2.2855517742288933,3.803444882994832,0.284733178478196 +134,15.997144459453818,1.691733703547658,0.251818700906509,0.026630389228958263,37.073612246897724,2.926309390854865,4.651442531055015,0.367149547473271 +135,15.835263936437977,1.515218043948695,0.24576460234620645,0.023516309013451996,35.63465272190041,2.7612388891066266,4.4393516033547815,0.3439940999359724 +137,17.630630099621015,1.6412370931334446,0.2736287542526896,0.025472127694237293,38.374576388363494,2.767129186744343,4.780689570562353,0.34472786121695914 +138,8.585594309751155,0.9042170270635208,0.13515017122374468,0.014233736375391609,28.346497434353708,2.135528749667038,3.556497621226444,0.2679344400781932 +139,11.989500340054121,1.1648375826620803,0.1887327732228271,0.018336296016902745,32.52912123582845,2.329835925357236,4.081271154001681,0.29231321949282074 +140,16.194832666275346,1.3263339879372706,0.26217785387099435,0.021471997002950605,33.990016083733394,2.4880578210803646,4.324751317347851,0.3165703515069666 +141,16.847255920031024,1.603697043606883,0.25776730657799524,0.02453697322933994,34.60286522457087,2.664980270601036,4.280173673849347,0.3296425981353376 +142,6.468923803267134,0.5392516551087556,0.10039872915484015,0.008369271692490755,23.37630244132205,1.3428465820907955,2.912218171628132,0.16729173606004966 +145,14.361528193350027,1.5179253599668288,0.2292739025308762,0.024232843910812204,34.80349250682954,2.7469555287156857,4.397438874436354,0.3470792198786322 +146,8.621453145317096,0.4888112467090467,0.13191108825042208,0.00747897395202562,27.162239510324586,0.6087146847247991,3.359819836602511,0.07529466308520834 +147,15.016272474742886,1.3326300300159823,0.23637845072123387,0.02097757765181754,34.411646016412256,2.654325497222667,4.317459950444314,0.3330251631740126 +148,14.368724900278018,1.36263517106308,0.22618508930762388,0.021449903175100003,34.94569482691806,2.558524983951112,4.384464427644897,0.32100554402866055 +149,14.732513383220933,1.5624136577719663,0.22541114157495534,0.023905319957950245,37.55583808711033,3.1106818497666735,4.645438609171299,0.3847732417057708 +150,5.065841184615521,0.45986481926355904,0.07974562476290874,0.007239115081227703,20.575447254089877,1.3460999657088202,2.5815285449863383,0.16889039849142087 +151,13.497561682877466,1.4510065367110045,0.21548139618634768,0.023164547919987656,32.86958238765167,2.698828791131921,4.153090704877461,0.34099857534899564 +152,15.567763442317782,1.3802970412396351,0.24505973835246006,0.021727927266378035,36.64439802167945,2.564029082217065,4.59759236135595,0.3216961161627348 +153,19.089144723282416,1.7507788969512421,0.29626496337757213,0.027172220301460184,38.28559500513555,2.7646639185472512,4.769603889692725,0.344420709089863 +154,10.97397557220647,1.1116084646599085,0.1801389058048595,0.018247164046401636,30.703527725149943,2.594661072998824,3.933779772642846,0.33243167811840457 +157,9.6266307651204,1.0740859287230051,0.14940684482523087,0.01666998491965896,30.97857894287491,2.49361774048425,3.8593092622374003,0.3106547288717324 +159,9.825585304442486,0.9402246471924146,0.15466949501220958,0.014800550488685133,30.338104114240835,2.1779180968561134,3.8063748568828335,0.27325282598433276 +161,7.921821289428838,0.7839785790460017,0.12646752196054828,0.012515787031753172,26.597424847901028,1.7314585159003069,3.360598076848409,0.21877065888717284 +163,14.679618913601155,1.3680042340556702,0.23435231142518123,0.02183946028689744,34.390058265253,2.7357033574954905,4.345203709532757,0.3456576980906481 +166,17.106726203660156,1.672917270545349,0.25800348138075835,0.025230922312321043,35.58955367131401,2.78608944330353,4.370708799680682,0.3421561775965537 +167,19.587452996722423,1.8914173305383921,0.3039987453003099,0.02935493937977264,36.80020033084008,2.7246833505331387,4.584554023932556,0.339439946150521 +170,7.081554135249953,0.6759403859043663,0.11147467934609036,0.010640353280742412,24.74464886335163,1.8725424757077216,3.1045961996477023,0.23493920992232098 +171,16.033978799155758,1.5289717153317635,0.24884880570941356,0.02372977974399071,34.729251685394765,2.630917049664438,4.3265582336654,0.3277587414330424 +172,10.462183649907386,0.9810712730138812,0.16937283709335127,0.015882614037521482,33.336270666963244,2.387981192777947,4.24158061092532,0.3038376676182639 +173,15.572566837601746,1.523474073166094,0.24168765020265934,0.023644455838784058,33.696750608293115,2.5450016573998435,4.197929604495103,0.3170554314058558 +174,15.508046183540303,1.4891328735964862,0.24068608632351304,0.023111458343606985,35.82492027175061,2.8058372142374135,4.46305441853217,0.3495500919944507 +175,9.418242025150064,0.873619593789335,0.1482577820780041,0.013752131555891934,31.672068562646444,2.1444976958839534,3.9737473842356654,0.2690601686676262 +176,14.541971932009915,1.3897780970051077,0.22569298300139612,0.021569506934107623,35.55944875846481,2.8030272846602853,4.429986443788038,0.3492003758820121 +177,8.09059666013305,0.7444415250551933,0.12556679421683456,0.01155380001127565,25.06392663129113,1.855821281468066,3.122455361749195,0.23119757713995975 +178,11.220832232884218,1.3267429599461285,0.16923262552470614,0.02000994131701676,32.75260753730867,2.609053606283819,4.0223086490554545,0.32041476009048997 +179,12.072197360538611,1.1647643728198207,0.19272683621201186,0.018594904125723875,32.38873161498765,2.4466099007636513,4.092341553246313,0.30913107313056315 +180,19.644646452838618,1.7471822151139382,0.3048863920454799,0.027116399528541533,38.27727706653296,2.8077206944762647,4.76856764427698,0.34978470476293805 +181,14.277031735911251,1.4436015983727795,0.2215807100749641,0.02240481587136972,32.52763533055445,2.660704517596688,4.052280547953535,0.33146956583042125 +182,13.398790121477315,1.2947623547364702,0.20500484190601356,0.01981018804176492,30.177208225522833,2.246758031846821,3.7327450364091135,0.27791089317186923 +183,10.700971274567003,1.133778692033535,0.17083512366927855,0.01810015353722918,29.872777234413267,2.451302811221325,3.774440506860295,0.3097233495450061 +184,13.774490624764681,1.3446103404886056,0.21075357158974306,0.020572915498232102,33.39814284259047,2.5549401603526016,4.131160000236048,0.3160315423283181 +185,9.227995033327389,0.923297470405808,0.1493924931715235,0.014947310932085444,29.327155810514775,2.116334740979233,3.7314760460815797,0.2692744036441103 +186,11.820447528632743,1.179096970045291,0.18345441810150867,0.018299691953366448,33.72152644116479,2.4092102230077863,4.201016169235338,0.30013858119980125 +187,12.451299200850515,1.232424047341517,0.19877837191415207,0.01967499468823805,34.912407224607,2.570860179543494,4.41120280201318,0.32482966741958946 +188,11.231893957813199,1.0607072007267317,0.1843732502316896,0.017411670273658867,33.51146729469238,2.2403714347704424,4.293543846517732,0.2870400422364148 +189,8.338711779015307,0.8176039503304914,0.13126386876204962,0.012870316240644575,28.265803854263925,2.3628882142610883,3.5463733889010145,0.2964601299580333 +190,9.572114955073907,1.1505691042404689,0.14645604468469287,0.017604030136949823,30.171403114294012,2.518319029542717,3.732030678598686,0.3115017170779069 +191,5.106675895995272,0.46310959906893706,0.0803884379606222,0.007290193862296434,19.842589894773916,1.3036657401905418,2.4895795258902207,0.16356632640166116 +192,16.459082012113594,1.519141967213161,0.2590904176027051,0.023913552796770418,34.89403475853969,2.673304297924556,4.377982892987866,0.33540633993896 +193,11.744390690601936,1.0827015142320475,0.1874927410391062,0.017284734472687496,30.2124461787644,2.238358704657026,3.8173578497113123,0.282817754018804 +195,11.201728117596133,1.2118457639203433,0.1788302125732575,0.019346535935598402,31.752820615827645,2.476555843745426,4.011993701500717,0.31291476643082033 +198,15.960485087469845,1.3482858991270483,0.2512417608351952,0.021224024304366814,33.94752366234995,2.5676328471918035,4.259228801756621,0.32214826282674003 +200,12.922077416387175,1.2190890364412474,0.20055204426985182,0.018920394184854843,29.441839157682953,2.2606581193910187,3.6678563054967377,0.2816321729553698 +201,15.631836807389293,1.5530176526113484,0.24606834836493646,0.024446806441775326,33.877430587925524,2.608724770265759,4.250434568505278,0.32730386427846725 +204,7.997647544024912,0.785767133724853,0.1276786041733432,0.01254439512206709,27.845543734069974,2.021461175393468,3.518306213724679,0.2554131994013862 +205,9.231898132262398,0.9010741920051873,0.1515430141030709,0.014791270119170129,29.987436726722358,2.281655866342962,3.842039302506181,0.2923294709438009 +206,15.371912972087811,1.5169953519745263,0.24197676081566769,0.02387976188193077,37.12064938880068,2.8705746113613912,4.657345277647997,0.36015687576828126 +208,15.096610563859242,1.4931612821849478,0.2376430916679914,0.02350457819365404,32.35326100355088,2.58380746493607,4.059204508336569,0.3241776125501246 +210,16.306584163400363,1.475816615701337,0.25307966569569607,0.02290480777501861,36.652095169445076,2.7491235683064623,4.566105413758151,0.3424848688813529 +211,9.277769534384339,0.44817214280287804,0.14399246288435774,0.0069557031352394825,28.44002796184172,0.5486841761270341,3.5430567533076265,0.06835503742359993 +213,14.785106462240519,1.5536386422939334,0.23273943118551763,0.0244565688315331,37.18003995121822,2.9528850042156622,4.66479548806018,0.370483858072736 +214,16.83959122284962,1.5786493415201175,0.26135184466570033,0.024500767983414152,35.675913716942055,2.6628563714367903,4.444491882563439,0.3317376429706643 +215,17.60832536954659,1.7104926524399564,0.27328258310227005,0.026546979376283603,34.9841862677878,2.4894557888382116,4.358316108363333,0.3101354189719161 +217,11.259651235081183,1.0469384633083736,0.1772438502728388,0.016480386502323786,32.452871686836275,2.2604637866342916,4.0717044927152815,0.2836094335341177 +218,13.041342964154376,1.3853255721283038,0.20529012445506103,0.02180708381757053,34.203812151442726,2.5300719976329944,4.2913840577676305,0.3174356877991613 +219,18.050089239114378,1.661664467372782,0.2801388737169572,0.02578916958352602,36.50155405502089,2.7873699575621718,4.547349844650216,0.34724949859386933 +220,12.97599514726034,1.3532384514711522,0.2013886219842639,0.021002383544774524,33.23605220321334,2.477069746303046,4.14053595559674,0.30859249727911575 +221,11.208614749536487,1.1109389978345987,0.1714947523362134,0.016997658725148364,33.46427235638494,2.541997908242394,4.139337450043918,0.3144304775989975 +223,19.25702671228018,1.9583494062103346,0.29043424182921984,0.029535801841449206,37.55100310124042,2.8799381923212612,4.611591556072749,0.3536815944413861 +226,13.930279147142205,1.2810747207596733,0.21619944457739884,0.0198824187343875,36.13627646716362,2.548450957910621,4.501847482672358,0.31748532641455074 +228,13.934230651500659,1.319113728574046,0.2193457541177541,0.020764834657735157,35.836767255844435,2.4620172644537246,4.496265466060475,0.30889737134988443 +229,16.372612308575277,1.5433522432527966,0.25410442849947684,0.023952966842055747,33.79050453872821,2.346978109675076,4.209609436912368,0.2923857259186935 +230,13.695774275972772,1.2785143097100033,0.21559184612741944,0.020125715770175037,34.64490725366393,2.452532213000208,4.3467260904407805,0.3077071524492839 +231,16.359798913196038,1.6762798901928528,0.250309090217963,0.025647509268979723,35.93823763653004,2.915886862505025,4.445351493817671,0.3606782878764328 +232,8.69192147896108,0.8433832695783842,0.13876190528579643,0.013464165507722607,27.865506410478215,1.9639076265015567,3.520822817132496,0.24814086204897143 +235,4.946086425945566,0.4259552182073719,0.07896327540970169,0.006800289422981153,19.182362227240482,1.1292883109741212,2.423727634745622,0.1426877073052193 +236,11.342063067677234,1.1041084458919213,0.1810700067818233,0.017626504331055597,34.734242183141056,2.5783990579095932,4.388691546198616,0.32578220905209926 +238,11.148389809953773,1.148168332813141,0.1754920545844747,0.01807385848262194,30.72332762496997,2.319386833979987,3.854702881751148,0.29100191300801737 +240,12.93820952857311,1.2763760097976105,0.20655140249988765,0.020376641324186533,32.67640746937161,2.281549146337015,4.128680604526689,0.2882748881616026 +241,18.14939450887593,1.802928327967388,0.2737292226346087,0.027191770471410255,36.80765109001092,2.8153808333150954,4.520303709013698,0.345753560638757 +242,13.058322477461484,1.37200028648017,0.21140186405608638,0.02221138423775367,30.95656171474527,2.488446054690167,3.938795471813279,0.3166204355116285 +243,8.742152790147143,0.4781639927890933,0.13956427306552086,0.007633658626388924,28.673190010175286,0.9018782312860111,3.622879967564674,0.11395301939369998 +244,5.42932582163481,0.5040650771830442,0.08912474615956943,0.00827444760688822,21.577398978019822,1.3791465985121516,2.764555368538785,0.17670003399402634 +245,15.043517629753701,1.372394899327127,0.23680720494775614,0.02160352440119652,33.18903557762472,2.45862605630387,4.164063933731729,0.30847163556901186 +246,8.464513286152483,0.8063393300906387,0.13513145439089347,0.012872778708491453,26.58512970200125,2.0224288847335266,3.3590464810657807,0.2555350568012672 +247,17.027611718087755,1.5821610107581043,0.2642700787625377,0.024555282434817957,35.93285421855917,2.4147099042385385,4.476502623400493,0.30082372959651876 +248,15.78153068934852,1.5141215460412438,0.24493065791959512,0.023499291275491965,37.45952435254007,2.831384731790293,4.666693423201337,0.3527328425755218 +249,10.162763569887076,0.983423746748984,0.15772771146298736,0.015262893395718076,32.02031243912632,2.424140116415992,3.989088350499636,0.30199921118064255 +250,14.545546480350051,1.4329022321457445,0.22574808105507418,0.02223876082506936,37.19176430326155,2.731621306496109,4.633335977196301,0.3403043526589157 +251,14.234978983008398,1.6186034378345526,0.21779880409377006,0.024765044857686706,31.862491840299043,2.4314292450178514,3.9412053849589523,0.30075369125684487 +252,5.395524230590785,0.28704577059304553,0.08255478100900179,0.004391973739366255,21.476508904344836,0.4500374196938202,2.656549897659446,0.05566765373997411 +254,15.50631265026321,1.5842999290784145,0.24754975705412316,0.02529247741806424,33.08356813495647,2.6192496620035213,4.180125560478535,0.33094351905310554 +255,11.101400781794407,0.7810518616466753,0.17475255074452078,0.01229491735046169,29.078770363229182,1.315340387532184,3.648370275328622,0.16502928809809347 +256,5.912321228986767,0.5137787208217239,0.09046047275978474,0.007860984574313397,21.72787797345344,1.3495510649747218,2.687619163167274,0.16693205421764332 +257,10.312737176488703,1.0385982233313535,0.16463789891370595,0.016580722108832203,33.041942782459685,2.3191148405389974,4.174875294779228,0.29302197262631385 +258,12.91602287935187,1.2139506152768669,0.20331763191880925,0.019109409039453445,38.15561524308182,2.7190097980030434,4.787200082222285,0.34114097874292426 +259,5.6714397051795,0.4432059687006692,0.08802135989253033,0.006878604746849623,21.52364514576768,1.0611158096472457,2.681409851550565,0.13219351863286335 +262,14.119810572071513,1.3285744656318088,0.22226706126737716,0.02091376089244058,35.69993598689503,2.6920420360650996,4.479097910045663,0.33775746438090415 +263,10.04366015211698,0.8969875548915872,0.1536706407370835,0.013724145401746424,29.467556805181488,2.265362281448129,3.644966791626991,0.2802122463519227 +264,13.398366008291156,1.0645135126806733,0.2229865993995718,0.01771650722637865,34.17891796766114,2.5159692225223904,4.409321573990326,0.3245777816272627 +266,9.856204549112345,0.8392169427352892,0.15734957465308624,0.01339769566703582,33.37054965772983,2.1581380796706298,4.216395030295149,0.2726824330778193 +267,14.220919679062286,1.4277269746226082,0.22070996366856108,0.02215845218235273,30.862593828144874,2.346448322068243,3.8448513273203107,0.29231972516079624 +269,17.35568604794513,1.6363575240615567,0.261758368062112,0.024679535794854074,35.54584294042482,2.68718417025151,4.365341378652508,0.33000979242831063 +270,12.71331569035123,1.13927941862808,0.1945172973345586,0.017431294779269253,34.41198414216036,2.251195264850663,4.25656639313372,0.27846002919096785 +271,16.335482130234908,1.5978953942777212,0.25352802997067164,0.02479946830957812,34.624512996886686,2.6215322768354823,4.313508777192034,0.32658950284264915 +272,11.07837526002715,1.1086794700087081,0.17194119798737278,0.0172071871355652,34.85888652993892,2.566743135455885,4.342756198414931,0.3197675190131655 +273,16.230091475287633,1.4025113565204275,0.25548605754302633,0.02207763879102694,33.52267443585138,2.5836505503474982,4.205927457681764,0.3241581101041158 +274,8.786766035274368,0.7991869788641291,0.13831691684075562,0.012580405401941807,28.334522867222436,1.9315600697449153,3.5549952303361327,0.24234347856248292 +275,12.859182489538362,1.4077421122285334,0.1939422290289899,0.02123157077564591,34.641783080697124,2.8175480636211496,4.254316043248407,0.3460197156065594 +276,10.418134540406903,0.9295191347466735,0.17101526543790718,0.01525819818718789,31.899664910220572,2.3330482908990846,4.08703709619267,0.29891395219823746 +277,4.236579772684347,0.364051442832288,0.0685874011318555,0.005893750072442998,18.35665222191618,1.0935802594612432,2.3356510522746383,0.13914421065884308 +278,12.422643294902905,1.0149483118752258,0.19832089561082772,0.01620311019413889,29.646104278658576,2.1159011561329306,3.745802385423044,0.2673453322387333 +279,12.886995252073817,1.3862673598678545,0.19717464336224896,0.02121027958341837,30.88587656849506,2.6372321499642806,3.820406974524395,0.3262105926253927 +280,14.84556176699036,1.3986329703829845,0.23040434304823695,0.02170689905606892,32.47729028259552,2.4758627943966607,4.046008580856741,0.30844205363158367 +281,14.366984368489273,1.4349522469209361,0.2293610073675082,0.02290822377449718,30.509312687306483,2.2142016296016376,3.8548670831574943,0.27976549537204903 +283,12.451688430526149,0.9904546057269594,0.1960083091160064,0.01559124560559686,30.120100323422307,1.3139018127900892,3.7790229780392486,0.1648488912090385 +284,14.138495035738144,1.548675123231307,0.222560811505872,0.02437843570437136,35.41263027082393,2.7677366752724923,4.4430473481045905,0.34725421413988483 +285,14.469429612060246,1.5340739618652337,0.22138589403947942,0.023471715518567957,35.39432642196145,2.8201241609313117,4.378072195455103,0.34883294654376173 +288,14.38525761297252,1.3901990435432803,0.22965272967018874,0.02219376348510372,32.77017789022536,2.5994968777699037,4.140528544610681,0.32844774477843414 +289,15.294015154474385,1.5758567497837161,0.24416054424182834,0.02515768670215981,34.020645460461566,2.669933362681376,4.298525754330353,0.33734743025878017 +290,12.827396238606502,1.3289438107006115,0.20478232924383305,0.021215857367091903,30.480145871528748,2.432796784569234,3.851181841237611,0.30738510372110533 +292,15.776129669961222,1.5423366241820795,0.251857105417874,0.024622543416723115,34.52903003858605,2.5812163411979334,4.362759259298869,0.32613790425709777 +293,14.782350613706042,1.3746335510429872,0.22942330073576764,0.02133442608850049,34.597894349318814,2.53551164864693,4.310192636112119,0.315873085409016 +294,18.6021688641832,1.6350446010408253,0.284617788896821,0.02501658717827999,35.723086038909756,2.7224653468631157,4.418737459308434,0.33675309005359166 +296,15.284431400071435,1.5042132745708088,0.237215762069955,0.023345526497072652,33.849047828876074,2.451075980795931,4.216902739869473,0.30535420290993204 +297,17.374159665480423,1.8032170782605415,0.26582899076554367,0.027589672552484706,34.751731946574274,2.729615728424063,4.298586998530999,0.33763758017090856 +298,8.637342069678068,0.6215061715181462,0.1359647588180623,0.009783442178474662,26.53251686018863,1.154984215972468,3.3289062719985676,0.14491027070180335 +300,13.021446339796302,1.369007158323128,0.20497692201096218,0.021550207726650932,33.86229760026613,2.692372422331063,4.248535906984733,0.3377987237097311 +303,15.810673662472382,1.6169181586668695,0.25240871329526726,0.02581320952196779,35.12075884195593,2.821910108558504,4.437525636285353,0.35654976893784435 +304,14.310121079723265,1.5843312145168769,0.22526245913727258,0.02493971528834297,36.53293581551418,2.8931114512211544,4.583606536770784,0.3629843663917173 +305,9.038050541941905,0.8216146100540248,0.13828470930883585,0.012570934073444763,29.759398736369818,2.1505023980392477,3.6810680842405357,0.26600489521417847 +306,4.655304397641121,0.4118043259524002,0.07747872101531021,0.006853702735213392,19.992665509680542,1.270864595561292,2.57921698265933,0.16395190255871697 +307,15.365983363874435,1.1228988649247218,0.24530934854658393,0.017926453681186803,34.8081933244787,1.46531696941513,4.398031672367623,0.18514349140360026 +308,10.947362306007143,1.0751612679626896,0.1772274196767379,0.01740584187597755,33.048359531724415,2.256168958538844,4.204947890334029,0.2870663789934271 +309,5.486360328311352,0.47942780747160335,0.08636384707296063,0.007546939568175703,20.532702130339207,1.2139614569250008,2.5761427997776427,0.15231010738932166 +310,11.196717165640582,0.9737172989980227,0.17625297231583978,0.015327757735133797,28.25148315484552,1.6675120964586665,3.5445746188230363,0.20921454003996334 +312,12.084429682299861,1.1019516352582235,0.19563483413856134,0.01783949520664766,36.3814097341548,2.570388273357004,4.629025116198528,0.3270459271011027 +313,12.483683719318392,1.2764398988041388,0.193747903955692,0.019810463039528246,33.100187529926956,2.567740251773317,4.123609981314413,0.3198881976744679 +314,5.424440442458234,0.4593894971103817,0.0853891317366386,0.007231505388122545,21.272835281630687,1.3911764395415793,2.669003869717335,0.17454444842161315 +315,7.6005929724381405,0.7617137306820045,0.11964476826727424,0.011990520098093715,26.290639417716807,1.9803196585094236,3.298559081811435,0.24846110779884809 +316,9.579261626087307,0.9941181125250784,0.152927645777576,0.015870549162086536,29.924963484911814,2.3720354113893527,3.781034265995483,0.29970787349965805 +317,9.465069581681318,1.0621975829510133,0.15323050540692196,0.017195972102793857,31.107980164648126,2.4823747789096133,3.9580613809385237,0.31584794941407873 +320,14.489959287824044,1.2952975241827436,0.22809337837114427,0.02038989775042967,34.01515913327849,2.4972033662794955,4.267713565094421,0.3133117396074126 +321,14.940435900489764,1.520468529186744,0.23518493854470257,0.023934462152085965,34.31290080923513,2.82957912782895,4.305073330066112,0.35501357656271215 +322,15.832500819784068,1.4936612453802491,0.24224122462624226,0.022853390843064834,36.53893546826508,2.85309198820449,4.5196536732475145,0.35291087491591194 +323,17.28651478725102,1.6950056288584625,0.2682882778859626,0.026306641146012437,37.099986450043296,2.925386452909353,4.6219035554921994,0.3644436384389752 +324,12.481747931204156,1.1923618670768479,0.19371808285945527,0.018505585614927895,32.67399706934046,2.4124338773563396,4.070517658041371,0.3005403555554157 +325,9.794470674687908,0.9755315785748141,0.1585624265128377,0.015792854905214194,27.13690466559535,2.1044267603022466,3.4527884119044883,0.267758626903585 +326,15.63908950376336,1.5473159211719516,0.24272008801702125,0.024014483482981488,36.31610474837356,2.902943551686599,4.524247842627961,0.36164770952140857 +327,7.9777735696103,0.7773201870584474,0.12736091359515045,0.012409503518229472,25.074181610193932,1.858380205822567,3.1681373176443834,0.23480741154257712 +328,12.424418806637382,1.1865755085056175,0.19834924071170437,0.018943047141445478,31.343666264380598,2.4824070219238967,3.9602903220420393,0.31365355990491006 +329,5.01760670877284,0.5001093029321729,0.07898632571048929,0.00787263701301678,19.583903628768827,1.1689892944300384,2.4571230756541116,0.14666894940787864 +330,5.484738849860212,0.373944891188089,0.09128308589347638,0.006223604178094821,21.559696882560512,0.9924432527097015,2.7813768160909946,0.12803327752745608 +331,17.347790864177906,1.4872224902603481,0.2692391450141418,0.023081815711206093,36.81301274547801,2.6465839422307083,4.586151250900762,0.3297104298741803 +332,12.438433891307081,1.2948740161375711,0.19579966272761198,0.0203832651160107,34.12569469191238,2.8084330271884226,4.281585486021914,0.35236047782272073 +333,11.831766294513963,0.9344935930056651,0.18624958961666768,0.01471031829604441,32.8184162898677,1.6695308025752267,4.11756525395311,0.20946781716613772 +334,15.019093724709633,1.6157921245578921,0.23642286138955107,0.025434969945635936,32.56546332762467,2.5909023881975144,4.08582849008806,0.32506777767091405 +335,8.166728551087129,0.8379020457438068,0.12674836807181056,0.013004315771940493,25.193170356456914,1.7922841252257977,3.138556500591203,0.22328214006190494 +336,17.00753927433009,1.6815871330361352,0.2602198220632283,0.02572872521323125,35.25816082790404,2.8267603890775357,4.36123110582945,0.34965395381073744 +338,15.130431511272748,1.447219465033764,0.2415490213062382,0.023104063167914083,34.23187093536442,2.577318609268902,4.325214199877216,0.3256455093402852 +339,9.055048386283723,0.7483969397969218,0.1445588695839831,0.01194774572171628,27.445083182809284,1.4406072371943324,3.4677001360292246,0.18202145277200507 +340,18.0962102857969,1.5784106846205972,0.2768766264832932,0.024150085496405963,35.431593003630326,2.6003370653892186,4.382682492113309,0.3216466086892268 +342,9.157914083034607,0.9290204169297401,0.1421322871636736,0.01441854504014074,30.234277189857423,2.1801779407376456,3.7665842003610357,0.2716064198919517 +344,14.676772335256349,0.7657147608928261,0.23103402563509778,0.01205347876605841,32.12239017833603,0.6606155459387794,4.030236639916134,0.08288414913583451 +345,16.958951568386702,1.6315732535955638,0.2594761574654935,0.024963474702977967,34.13638813321513,2.6271811885164205,4.22247217962732,0.32496699522106165 +346,13.426675389122698,1.340533725787337,0.20838322022772565,0.020805205049474928,34.27256967211894,2.5451632775719353,4.269664945476978,0.31707556599132347 +347,12.913566021122326,1.3439793594751517,0.20041994649137929,0.02085870555592031,29.90172964007385,2.3694803457925264,3.725149336568651,0.2951892162890845 +348,7.814472077234357,0.7332670931868113,0.11956401066453952,0.01121922935845618,28.35739836685782,2.2086074889625293,3.5076544226477893,0.27319261542718404 +349,16.054751599149732,1.455506941065639,0.24564167408649848,0.022269616533140076,36.53743296137719,2.763158334652568,4.51946742556219,0.34178657538239504 +350,6.365034012320657,0.42213561492351315,0.10019553787190814,0.006645071324093235,22.44991402415668,0.8328838193834445,2.8166864741831676,0.10449806560947353 +351,16.72535089205537,1.6683946030613057,0.25957882530951887,0.02589362184449654,36.77899393252476,2.83581116833162,4.581913200006684,0.3532842863712631 +352,6.39460381584034,0.5896826476711883,0.10352437119776932,0.009546568804649727,24.588943220003575,1.7834629279528191,3.128630995010902,0.22692302572429435 +353,10.240615268541092,1.0008505041800941,0.15893546064678968,0.01553330847308519,28.67110001137946,2.091694761799636,3.571837832516094,0.2605827638739494 +355,11.309313444235224,1.2331555013831084,0.18055091546870117,0.019687079661186414,34.155438085688345,2.6980192022410536,4.31560400040652,0.3408998131762784 +356,12.549385092602833,1.3918495877067611,0.19200873240061392,0.021295647002291748,31.768962072111318,2.679523602026127,3.929635723766106,0.3314414756546223 +357,13.614731377088845,1.3679891747620883,0.21431599728684658,0.021534171783963368,31.218199163010258,2.321636313057604,3.9167928488523,0.2912842108904978 +358,10.63630962543909,0.967954007920088,0.16980302829564858,0.015452871116372367,30.03323936840162,2.1213780405808804,3.79471712744142,0.26803733974963523 +359,13.868996626746796,1.4501801495955313,0.21524797152702357,0.022506915528929174,35.37656409672771,2.7282623296338224,4.407199019719137,0.3398858925876026 +360,17.139651748539066,1.7282443173728135,0.2698034545006818,0.027205120260865443,34.76443740216303,2.7546288260233185,4.3617217988827655,0.34560963720785504 +361,15.378414656772788,1.4189346958514177,0.24207910699748464,0.022336141385560882,32.424988989096406,2.3879021054368224,4.068203865843941,0.29959833077697157 +362,13.322368508680425,1.3306603689165462,0.206764605476196,0.02065199337659598,34.898642525259746,2.687559291998032,4.34766338318738,0.33481540479712046 +363,14.438902809105523,1.452336999402173,0.23050940679544665,0.023185788049501607,33.99240056583376,2.723945062350827,4.294959429708824,0.3441720307129922 +364,7.457033336162799,0.713664954117596,0.11409470243745844,0.010919274047658876,25.40075178463691,1.8152026956818657,3.141928287545385,0.22453023223670765 +365,12.248335111544543,1.2182502500459929,0.1874029640083454,0.01863957065865561,31.04674707635751,2.306975402988601,3.840305739866866,0.2853597144988957 +366,12.446824558100952,1.2433392011836388,0.2015022923276077,0.020128483213513286,37.01117680889195,2.8332229672457494,4.709161726830484,0.3604885418754189 +367,14.22444324470066,1.5006199744242208,0.2239138815714673,0.023621989096985166,35.40217564821508,2.6478603437468933,4.441736830806195,0.33221401217031427 +368,8.640847427114277,0.909373094869019,0.1379465352019683,0.014517657984497702,28.198820492676568,2.175833681620771,3.562937243785595,0.27491784142330045 +369,5.204074458294161,0.21495635250381986,0.08425049486673723,0.0034799999919931874,20.80673564421587,0.3059448092577605,2.6473930765977185,0.03892759458762899 +370,16.48421297318159,1.5655709789852121,0.2522130838506669,0.023953675267321964,35.004941950140115,2.5183905268096747,4.329911895897119,0.31151056088250934 +373,7.492292714441592,0.3916116408980595,0.11628119626058407,0.006077855178485315,25.151872902311137,0.5405996293411695,3.1334134775245706,0.0673477546225497 +376,9.855073197744858,0.9824006276345656,0.15295163016972346,0.015246946873093787,27.806563497222218,2.2348427990497837,3.46413211947901,0.2784159474775842 +377,16.794658039307453,1.6158152011064975,0.2643728831107524,0.0254353332048147,36.35638961543476,2.731972567789819,4.561457363374171,0.34276715916232176 +378,12.527767007099415,1.1212298573233015,0.20564520373142398,0.01840515890089111,32.353348445907905,2.469908449756304,4.145163770736258,0.31644869896797734 +380,17.14101977491912,1.6029870347492563,0.26603004065488683,0.024878490989642028,35.45677789633753,2.653217632559296,4.417192024637357,0.33053685251469833 +381,16.579622194424342,1.6384286282032943,0.2573171039029493,0.025428547443182074,35.84732269563855,2.900525435964117,4.465845948515597,0.3613463654384092 +382,5.98714965384677,0.5544986201243315,0.09424870861427927,0.008728824548679898,22.725201856442666,1.6594795857786557,2.8512506463898135,0.20820903028769663 +383,17.98616747647286,1.7853055608998445,0.2712671583464938,0.02692595667859675,35.95176057184081,2.7171143814523258,4.415190588439261,0.3336854066083647 +385,16.821851070352317,1.5909856062963055,0.26855160472955336,0.025399210579477912,37.07892006022659,2.8072363607675723,4.684940296234991,0.35469573348560196 +389,15.443924207082597,1.577487858728118,0.24311032470052799,0.024832003861470543,33.708120252850684,2.7272728461265916,4.229192033622371,0.34217750820376136 +390,12.691688554496354,1.2794946816744148,0.19978692317417265,0.020141236886788132,32.94740330731077,2.623430723046447,4.133757713071961,0.3291496718254839 +391,14.887405650459343,1.5701873915509919,0.23105369684304186,0.024369430784133676,33.044885757816004,2.757093366104967,4.11671881675076,0.3434776026453167 +392,13.947796301545972,1.4595391111674494,0.21340519707292202,0.022331357937870316,32.20921229216704,2.4871318655908574,3.984096064492162,0.3076440425704961 +394,16.663671583196532,1.4281963799381299,0.25495841946543757,0.021851768375132332,36.36158363893741,2.673860057946624,4.497716938201354,0.3307409763123845 +395,13.60235950738492,1.4344440942845877,0.22328409079299405,0.02354654317229482,35.81758862339643,2.7740283317529486,4.589000550452914,0.35541246718856095 +397,10.844757785859171,1.097779996283735,0.17071260848390554,0.017280689011921663,32.23483241651808,2.537262908839582,4.044345856086746,0.318337896055251 +398,11.8738946258076,1.2150746563598374,0.18691357443876241,0.01912716546570507,37.35809038230828,2.6229595149252085,4.687146140868698,0.32909055153040423 +399,15.624353186844772,1.5835038539196955,0.24595054505302427,0.0249267045686749,36.13982918220449,2.9811702483914484,4.534286591104903,0.37403276631252935 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/best_bootstrap_solution_nn_qoi.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/best_bootstrap_solution_nn_qoi.csv new file mode 100644 index 00000000..c0c9df82 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/best_bootstrap_solution_nn_qoi.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +1,1,0,2,1,1,1,1,2,1,1,-25.298458075806685 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/cfd_all_spargers.txt b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/cfd_all_spargers.txt new file mode 100644 index 00000000..6126fed6 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/cfd_all_spargers.txt @@ -0,0 +1 @@ +23.063376805194807,2.180974782856517 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/convergence_data_nn_qoi.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/convergence_data_nn_qoi.npz new file mode 100644 index 0000000000000000000000000000000000000000..0fad1a822794dc8e49fc5821238d3af68dfaf903 GIT binary patch literal 407046 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 literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/hyperparams_qoi.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/hyperparams_qoi.json new file mode 100644 index 00000000..3d1b9fb9 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi/hyperparams_qoi.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi", + "best": "nn", + "best_params": { + "n_units": 23, + "n_layers": 2, + "lr": 0.0009480593464653759 + }, + "amp_physical": 15.408066680154267, + "mean_physical": 12.742125745334835, + "rbf": { + "params": { + "kernel": "multiquadric", + "epsilon": 0.3066926890793783 + }, + "test_mse": 3.5302516629097895, + "val_mse": 2.6923589766690297, + "test_nrmse_amp_pct": 12.194238472226438, + "test_nrmse_mean_pct": 14.745548996215005, + "val_nrmse_amp_pct": 10.649233092529132, + "val_nrmse_mean_pct": 12.877293542819494 + }, + "rf": { + "params": { + "n_estimators": 172, + "max_depth": 9, + "min_samples_leaf": 1, + "max_features": 0.9737361629708418 + }, + "test_mse": 5.4514917312747775, + "val_mse": 4.162827063810487, + "test_nrmse_amp_pct": 15.153380539753266, + "test_nrmse_mean_pct": 18.32381052052904, + "val_nrmse_amp_pct": 13.241769854200745, + "val_nrmse_mean_pct": 16.012247638623524 + }, + "nn": { + "params": { + "n_units": 23, + "n_layers": 2, + "lr": 0.0009480593464653759 + }, + "test_mse": 1.8887684874901578, + "val_mse": 2.5414217695066155, + "test_nrmse_amp_pct": 8.919514480696769, + "test_nrmse_mean_pct": 10.785678670883808, + "val_nrmse_amp_pct": 10.346422847895706, + "val_nrmse_mean_pct": 12.51112854539323 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv new file mode 100644 index 00000000..459e1ba1 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/best_bootstrap_solution_nn_qoi_kla.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +1,0,1,1,1,1,1,1,0,1,1,-0.3629736682995711 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/cfd_all_spargers.txt b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/cfd_all_spargers.txt new file mode 100644 index 00000000..9dec85f5 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/cfd_all_spargers.txt @@ -0,0 +1 @@ +0.34284382189288115,0.03242082615751673 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/convergence_data_nn_qoi_kla.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/convergence_data_nn_qoi_kla.npz new file mode 100644 index 0000000000000000000000000000000000000000..a8799fd31a8e58407e8af94c1ef761c059f461bd GIT binary patch literal 407046 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 literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/hyperparams_qoi_kla.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/hyperparams_qoi_kla.json new file mode 100644 index 00000000..908a5901 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_kla/hyperparams_qoi_kla.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi_kla", + "best": "nn", + "best_params": { + "n_units": 36, + "n_layers": 2, + "lr": 0.009975314935443623 + }, + "amp_physical": 0.23629899091362438, + "mean_physical": 0.19950070655847135, + "rbf": { + "params": { + "kernel": "multiquadric", + "epsilon": 0.2777187935847173 + }, + "test_mse": 0.0008575605372087271, + "val_mse": 0.0006662447859979985, + "test_nrmse_amp_pct": 12.3928309856788, + "test_nrmse_mean_pct": 14.67871220606787, + "val_nrmse_amp_pct": 10.923329760318776, + "val_nrmse_mean_pct": 12.938158687791802 + }, + "rf": { + "params": { + "n_estimators": 170, + "max_depth": 9, + "min_samples_leaf": 1, + "max_features": 0.9796570773174 + }, + "test_mse": 0.0012678287438304637, + "val_mse": 0.0009871358388269475, + "test_nrmse_amp_pct": 15.06844474217578, + "test_nrmse_mean_pct": 17.84784800333656, + "val_nrmse_amp_pct": 13.296171027943922, + "val_nrmse_mean_pct": 15.74867503538024 + }, + "nn": { + "params": { + "n_units": 36, + "n_layers": 2, + "lr": 0.009975314935443623 + }, + "test_mse": 0.000341592703558487, + "val_mse": 0.0006345451226036295, + "test_nrmse_amp_pct": 7.821542792998029, + "test_nrmse_mean_pct": 9.264241221278446, + "val_nrmse_amp_pct": 10.660299052886097, + "val_nrmse_mean_pct": 12.626611466642379 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/best_bootstrap_solution_nn_qoi_sum.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/best_bootstrap_solution_nn_qoi_sum.csv new file mode 100644 index 00000000..53acf3eb --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/best_bootstrap_solution_nn_qoi_sum.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +0,2,0,2,1,1,1,2,2,2,1,-42.391510998611544 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/cfd_all_spargers.txt b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/cfd_all_spargers.txt new file mode 100644 index 00000000..42b7b934 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/cfd_all_spargers.txt @@ -0,0 +1 @@ +39.95614453605928,2.8156788973361575 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/convergence_data_nn_qoi_sum.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/convergence_data_nn_qoi_sum.npz new file mode 100644 index 0000000000000000000000000000000000000000..482dbf0feb1702c33105c9a1910fb90ed35a8f9c GIT binary patch literal 407046 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 literal 0 HcmV?d00001 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/hyperparams_qoi_sum.json b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/hyperparams_qoi_sum.json new file mode 100644 index 00000000..1d883938 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum/hyperparams_qoi_sum.json @@ -0,0 +1,50 @@ +{ + "qoi": "qoi_sum", + "best": "nn", + "best_params": { + "n_units": 38, + "n_layers": 2, + "lr": 0.009796559328428031 + }, + "amp_physical": 20.017924166447315, + "mean_physical": 32.102839935975965, + "rbf": { + "params": { + "kernel": "multiquadric", + "epsilon": 0.3098578406499811 + }, + "test_mse": 7.443186837003173, + "val_mse": 4.0108651721232595, + "test_nrmse_amp_pct": 13.628887939304555, + "test_nrmse_mean_pct": 8.498377270861624, + "val_nrmse_amp_pct": 10.00460604365068, + "val_nrmse_mean_pct": 6.23843390480062 + }, + "rf": { + "params": { + "n_estimators": 50, + "max_depth": 10, + "min_samples_leaf": 1, + "max_features": 0.7497081419086573 + }, + "test_mse": 10.682255238180035, + "val_mse": 7.966569976196548, + "test_nrmse_amp_pct": 16.327227179611672, + "test_nrmse_mean_pct": 10.180943373908633, + "val_nrmse_amp_pct": 14.09991997907255, + "val_nrmse_mean_pct": 8.79209220919255 + }, + "nn": { + "params": { + "n_units": 38, + "n_layers": 2, + "lr": 0.009796559328428031 + }, + "test_mse": 3.072524705247253, + "val_mse": 3.1047786209819535, + "test_nrmse_amp_pct": 8.756461693293739, + "test_nrmse_mean_pct": 5.460145784370962, + "val_nrmse_amp_pct": 8.802302307279254, + "val_nrmse_mean_pct": 5.488729982414982 + } +} \ No newline at end of file diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/best_bootstrap_solution_rbf_qoi_sum_kla.csv b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/best_bootstrap_solution_rbf_qoi_sum_kla.csv new file mode 100644 index 00000000..a5762411 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/best_bootstrap_solution_rbf_qoi_sum_kla.csv @@ -0,0 +1,2 @@ +x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,best_y +0,0,0,0,1,1,1,0,1,2,2,-5.520224642193352 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/cfd_all_spargers.txt b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/cfd_all_spargers.txt new file mode 100644 index 00000000..c4819b87 --- /dev/null +++ b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/cfd_all_spargers.txt @@ -0,0 +1 @@ +4.871585084708841,0.343296869076375 diff --git a/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/convergence_data_rbf_qoi_sum_kla.npz b/papers/scaleup/SA_optimization/data/study/study_0_4vvm_lev6/qoi_sum_kla/convergence_data_rbf_qoi_sum_kla.npz new file mode 100644 index 0000000000000000000000000000000000000000..1b7ca894bc7a4fc309cb624564106aeeb083dd05 GIT binary patch literal 407046 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 tuple[np.ndarray, float, list[tuple], list[np.ndarray]]: + """Run SA on the surrogate and return optimal x, y, traces.""" + x_curr = np.random.randint(0, 3, size=dim) + y_curr = surrogate.predict(x_curr) + x_best, y_best = x_curr.copy(), y_curr + + trace = [(0, y_best)] + trace_x = [x_curr.copy()] + + for i in range(max_iters): + x_new = x_curr.copy() + idx = random.randint(0, dim - 1) + x_new[idx] = (x_new[idx] + random.choice([-1, 1])) % 3 + y_new = surrogate.predict(x_new) + + delta = y_new - y_curr + if delta < 0 or np.random.rand() < np.exp(-delta / temp): + x_curr, y_curr = x_new, y_new + if y_curr < y_best: + x_best, y_best = x_new.copy(), y_new + + trace.append((i, y_best)) + trace_x.append(x_curr.copy()) + temp *= alpha + + return x_best, y_best, trace, trace_x + + +def run_optimization( + X: np.ndarray, + y: np.ndarray, + model_type: str, + params: dict, + n_runs: int = 10, + max_iters: int = 1000, + bootstrap_size: int = 250, + out_folder: str = ".", + qoi_name: str = "qoi", + qoi_ylabel: str = "QOI", +) -> None: + """Bootstrap + SA optimization for one QoI on a fixed, pre-tuned surrogate. + + Hyperparameters are held fixed (``params``); each of ``n_runs`` bootstrap + subsets (size ``bootstrap_size``, drawn without replacement from the full + data) only refits the surrogate on its subset. + """ + os.makedirs(out_folder, exist_ok=True) + + all_x = [] + all_y = [] + all_traces = np.zeros((n_runs, max_iters + 1)) + rng = np.random.default_rng(42) + bs = min(bootstrap_size, len(X)) + bootstrap_idxs = [ + rng.choice(len(X), size=bs, replace=False) for _ in range(n_runs) + ] + + for i, idxs in enumerate(bootstrap_idxs): + X_sub, y_sub = X[idxs], y[idxs] + surrogate = Surrogate_wrapper(model_type, X_sub, y_sub, params) + x_best, y_best, trace, trace_x = simulated_annealing_surrogate( + surrogate, dim=X.shape[1], max_iters=max_iters + ) + + trace_y = [t[1] for t in trace] + all_traces[i, :] = trace_y + all_x.append(x_best) + all_y.append(y_best) + + best_index = np.argmin(all_y) + best_x = all_x[best_index] + best_y = all_y[best_index] + + df = pd.DataFrame( + [ + { + **{f"x{j}": best_x[j] for j in range(len(best_x))}, + "best_y": best_y, + } + ] + ) + df.to_csv( + os.path.join( + out_folder, + f"best_bootstrap_solution_{model_type}_{qoi_name}.csv", + ), + index=False, + ) + print(f" {qoi_name} ({model_type}): best_y = {-best_y:.6g}, x = {best_x}") + + # schematic of the optimum design on the reactor bottom face + plot_schematic( + best_x, + os.path.join(out_folder, f"Optimum_schematic_{model_type}_{qoi_name}"), + title=f"Optimum {qoi_name} ({model_type.upper()})", + ) + + # save the convergence-plot inputs so the plot can be regenerated later + # (via plot_convergence / --plot-only) without rerunning the optimization + np.savez( + _convergence_data_path(out_folder, model_type, qoi_name), + all_traces=all_traces, + qoi_lo=float((-y).min()), + qoi_hi=float((-y).max()), + best_x=np.asarray(best_x), + best_y=best_y, + all_x=np.asarray(all_x), + all_y=np.asarray(all_y), + ) + plot_convergence(out_folder, model_type, qoi_name, qoi_ylabel) + + +def _convergence_data_path( + out_folder: str, model_type: str, qoi_name: str +) -> str: + """Path of the saved convergence-plot data for one model/QoI.""" + return os.path.join( + out_folder, f"convergence_data_{model_type}_{qoi_name}.npz" + ) + + +def plot_convergence( + out_folder: str, + model_type: str, + qoi_name: str, + qoi_ylabel: str, +) -> None: + """Draw the convergence plot from data saved by run_optimization. + + Reads convergence_data_{model_type}_{qoi_name}.npz (the per-run SA traces + plus the CFD QoI range) so the plot can be regenerated without rerunning the + optimization. The grey band + dashed lines mark the CFD QoI range so + extrapolation of the optimum is easy to spot. + """ + data = np.load(_convergence_data_path(out_folder, model_type, qoi_name)) + all_traces = data["all_traces"] + qoi_lo = float(data["qoi_lo"]) + qoi_hi = float(data["qoi_hi"]) + n_runs, n_points = all_traces.shape + iterations = np.arange(n_points) + + mean_trace = np.mean(-1 * all_traces, axis=0) + std_trace = np.std(all_traces, axis=0) + lower_bound = mean_trace - 1.96 * std_trace / np.sqrt(n_runs) + upper_bound = mean_trace + 1.96 * std_trace / np.sqrt(n_runs) + + fig, ax = plt.subplots(figsize=(8, 6)) + ax.axhspan( + qoi_lo, + qoi_hi, + color="grey", + alpha=0.25, + zorder=0, + label="CFD data range", + ) + ax.axhline(qoi_lo, color="dimgray", ls="--", lw=1.2, zorder=5) + ax.axhline(qoi_hi, color="dimgray", ls="--", lw=1.2, zorder=5) + ax.plot( + iterations, + mean_trace, + label=f"Mean Convergence {model_type.upper()}", + color="blue", + ) + ax.fill_between( + iterations, + lower_bound, + upper_bound, + color="blue", + alpha=0.3, + label="95% CI", + ) + # optional red dashed line: CFD-verified QoI of an optimal design, if provided + cfd_file = os.path.join(out_folder, "cfd_all_spargers.txt") + if os.path.exists(cfd_file): + with open(cfd_file) as f: + cfd_value = float(f.read().strip().split(",")[0]) + ax.axhline( + cfd_value, + color="red", + ls="--", + lw=3, + zorder=6, + label="All spargers", + ) + pretty_labels( + "Iteration", + qoi_ylabel, + fontsize=30, + # title=f"Convergence ({model_type.upper()}, {qoi_ylabel})", + grid=False, + fontname="Times", + ) + pretty_legend(fontsize=30, fontname="Times") + fname = f"Mean_Convergence_plot_{model_type}_{qoi_name}" + plt.savefig(os.path.join(out_folder, f"{fname}.png"), dpi=300) + plt.savefig(os.path.join(out_folder, f"{fname}.pdf")) + plt.close() + + +# design choices shown in the bar plot: (code, bar color, name). Only spargers +# (code 1) are shown; mixers (0) and walls (2) are omitted as less +# physically meaningful. Order sets the bar order per QoI. +DESIGN_CHOICES = [(1, "tab:blue", "Sparger"), (0, "tab:red", "Mixers")] + + +def plot_design_composition(studies: dict, out_path: str) -> None: + """Bar plot of the mean sparger/mixer/wall count over the bootstrap optima. + + For each (level, QoI) it reads the saved ensemble (all_x) of the winning + surrogate and, per placement type, plots the mean count across the bootstrap + optima with an error bar for the std. Blue = sparger, red = mixer, + grey = wall; lev1 hatched, lev6 solid. Reads only saved data, so it needs no + optimization rerun. + """ + qoi_names = list(QOI_COLS.keys()) + # stats[level][qoi_name][choice] = (mean_count, std_count) + stats = {label: {} for label in studies.values()} + for study_path, label in studies.items(): + for qoi_name in qoi_names: + out = os.path.join(study_path, qoi_name) + json_path = os.path.join(out, f"hyperparams_{qoi_name}.json") + if not os.path.exists(json_path): + continue + with open(json_path) as f: + best_type = json.load(f)["best"] + data_path = _convergence_data_path(out, best_type, qoi_name) + if not os.path.exists(data_path): + continue + npz = np.load(data_path) + if "all_x" not in npz.files: + print( + f" {label}/{qoi_name}: npz has no all_x (rerun to save)" + ) + continue + all_x = npz["all_x"] + stats[label][qoi_name] = { + choice: ( + float((all_x == choice).sum(axis=1).mean()), + float((all_x == choice).sum(axis=1).std()), + ) + for choice, _, _ in DESIGN_CHOICES + } + + ordered_levels = sorted(studies.values()) # lev1 (hatched) before lev6 + n_bars = len(DESIGN_CHOICES) * len(ordered_levels) + bar_width = 0.8 / n_bars + x_ticks = np.arange(len(qoi_names)) + + fig, ax = plt.subplots(figsize=(11, 6)) + slot = 0 + for choice, color, _ in DESIGN_CHOICES: + for level in ordered_levels: + means = [ + stats[level].get(q, {}).get(choice, (np.nan, np.nan))[0] + for q in qoi_names + ] + stds = [ + stats[level].get(q, {}).get(choice, (np.nan, np.nan))[1] + for q in qoi_names + ] + offset = (slot - (n_bars - 1) / 2) * bar_width + ax.bar( + x_ticks + offset, + means, + bar_width, + yerr=stds, + capsize=3, + color=color, + edgecolor="black", + hatch="//" if level == "lev1" else None, + ) + slot += 1 + + pretty_labels( + "", + "Average count over bootstrap optima", + fontsize=20, + grid=True, + fontname="Times", + ) + ax.set_xticks(x_ticks) + ax.set_xticklabels([QOI_COLS[q]["label"] for q in qoi_names]) + legend_handles = [ + Patch(facecolor=color, edgecolor="black", label=name) + for _, color, name in DESIGN_CHOICES + ] + [ + Patch(facecolor="white", edgecolor="black", hatch="//", label="3.6L"), + Patch(facecolor="white", edgecolor="black", label=r"608 m$^3$"), + ] + ax.legend(handles=legend_handles, fontsize=14) + plt.savefig(f"{out_path}.png", dpi=300) + plt.savefig(f"{out_path}.pdf") + plt.close() + + +if __name__ == "__main__": + studies = { + "data/study/study_0_4vvm_lev6": "lev6", + "data/study/study_0_4vvm_lev1": "lev1", + } + + parser = argparse.ArgumentParser() + parser.add_argument( + "--plot-only", + action="store_true", + help="skip the optimization and regenerate the convergence plots from " + "the saved convergence_data_*.npz in each qoi folder", + ) + args = parser.parse_args() + + selection_rows = [] + for study_path, label in studies.items(): + print(f"\n=== {label}: {study_path} ===") + if not args.plot_only: + X, Y_full = load_full_dataset(study_path) + split = make_or_load_split( + study_path, n_samples=len(X), n_test=20, n_val=20 + ) + + for qoi_name, qoi_info in QOI_COLS.items(): + out = os.path.join(study_path, qoi_name) + json_path = os.path.join(out, f"hyperparams_{qoi_name}.json") + + if args.plot_only: + if not os.path.exists(json_path): + print(f" skip {qoi_name}: no {json_path} (run first)") + continue + with open(json_path) as f: + record = json.load(f) + best_type = record["best"] + if not os.path.exists( + _convergence_data_path(out, best_type, qoi_name) + ): + print(f" skip {qoi_name}: no saved convergence data") + continue + plot_convergence(out, best_type, qoi_name, qoi_info["ylabel"]) + print(f" {qoi_name}: replotted ({best_type})") + else: + y = Y_full[qoi_name].values.reshape(-1, 1) * -1 + best_type, best_params = select_or_load_surrogate( + X, y, split, qoi_name, out + ) + with open(json_path) as f: + record = json.load(f) + run_optimization( + X, + y, + model_type=best_type, + params=best_params, + n_runs=50, + max_iters=1000, + bootstrap_size=250, + out_folder=out, + qoi_name=qoi_name, + qoi_ylabel=qoi_info["ylabel"], + ) + + selection_rows.append( + { + "level": label, + "qoi_name": qoi_name, + "best": best_type, + "val_mse": record[best_type]["val_mse"], + "val_nrmse_amp_pct": record[best_type][ + "val_nrmse_amp_pct" + ], + "val_nrmse_mean_pct": record[best_type][ + "val_nrmse_mean_pct" + ], + "best_params": record["best_params"], + } + ) + + with open("surrogate_selection.csv", "w", newline="") as f: + writer = csv.DictWriter( + f, + fieldnames=[ + "level", + "qoi_name", + "best", + "val_mse", + "val_nrmse_amp_pct", + "val_nrmse_mean_pct", + "best_params", + ], + ) + writer.writeheader() + writer.writerows(selection_rows) + print("\nWrote surrogate_selection.csv") + + plot_design_composition(studies, "design_composition_barplot") + print("Wrote design_composition_barplot.png") diff --git a/papers/scaleup/SA_optimization/get_optimal_constrained.py b/papers/scaleup/SA_optimization/get_optimal_constrained.py new file mode 100644 index 00000000..c0fc81c1 --- /dev/null +++ b/papers/scaleup/SA_optimization/get_optimal_constrained.py @@ -0,0 +1,175 @@ +import csv +import os +import random +import warnings + +import numpy as np +from load_data import load_full_dataset +from model_selection import make_or_load_split, select_or_load_surrogate +from surrogate import Surrogate_wrapper + +warnings.filterwarnings("ignore") + +QOI_COLS = { + "qoi": {"label": "QOI"}, + "qoi_kla": {"label": "QOI Num"}, + "qoi_sum": {"label": "QOI Sum"}, + "qoi_sum_kla": {"label": "QOI Sum Num"}, +} + + +def simulated_annealing_constrained( + surrogate: Surrogate_wrapper, + dim: int = 11, + max_iters: int = 1000, + max_spargers: int = 8, + temp: float = 10.0, + alpha: float = 0.95, +) -> tuple[np.ndarray, float, list[tuple]]: + """SA constrained by max number of spargers.""" + + def is_valid(x): + return np.sum(x == 1) <= max_spargers + + while True: + x_curr = np.random.randint(0, 3, size=dim) + if is_valid(x_curr): + break + + y_curr = surrogate.predict(x_curr) + x_best, y_best = x_curr.copy(), y_curr + trace = [(0, y_best)] + + for i in range(max_iters): + x_new = x_curr.copy() + idx = random.randint(0, dim - 1) + x_new[idx] = (x_new[idx] + random.choice([-1, 1])) % 3 + + if not is_valid(x_new): + trace.append((i, y_best)) + temp *= alpha + continue + + y_new = surrogate.predict(x_new) + delta = y_new - y_curr + if delta < 0 or np.random.rand() < np.exp(-delta / temp): + x_curr, y_curr = x_new, y_new + if y_curr < y_best: + x_best, y_best = x_new.copy(), y_new + + trace.append((i, y_best)) + temp *= alpha + + return x_best, y_best, trace + + +def run_constrained_optimization( + X: np.ndarray, + y: np.ndarray, + model_type: str, + params: dict, + max_spargers: int = 8, + n_runs: int = 10, + max_iters: int = 1000, + bootstrap_size: int = 250, +) -> tuple[float, float]: + """Mean optimal QoI over the bootstrap optima and its 95% uncertainty. + + Each bootstrap subset refits the fixed, pre-tuned surrogate + (``model_type`` + ``params``) and yields one constrained optimum. Returns + the mean of those optima (positive, i.e. negated back to physical) and the + 95% confidence interval of that mean (1.96 * std / sqrt(n_runs)). + """ + rng = np.random.default_rng(42) + bs = min(bootstrap_size, len(X)) + bootstrap_idxs = [ + rng.choice(len(X), size=bs, replace=False) for _ in range(n_runs) + ] + + all_y = [] + for idxs in bootstrap_idxs: + X_sub, y_sub = X[idxs], y[idxs] + surrogate = Surrogate_wrapper(model_type, X_sub, y_sub, params) + _, y_best, _ = simulated_annealing_constrained( + surrogate, + dim=X.shape[1], + max_iters=max_iters, + max_spargers=max_spargers, + ) + all_y.append(y_best) + + optima = -np.array(all_y) # negate back to physical QoI + mean_optimum = float(np.mean(optima)) + ci95 = float(1.96 * np.std(optima) / np.sqrt(len(optima))) + return mean_optimum, ci95 + + +if __name__ == "__main__": + studies = { + "data/study/study_0_4vvm_lev1": "lev1", + "data/study/study_0_4vvm_lev6": "lev6", + } + + results = [] + + for study_path, level_label in studies.items(): + print(f"\n=== {level_label}: {study_path} ===") + X, Y_full = load_full_dataset(study_path) + + split = make_or_load_split( + study_path, n_samples=len(X), n_test=20, n_val=20 + ) + + for qoi_name, qoi_info in QOI_COLS.items(): + y = Y_full[qoi_name].values.reshape(-1, 1) * -1 + + # winning surrogate + tuned params (cached from the selection step) + out = os.path.join(study_path, qoi_name) + model_type, params = select_or_load_surrogate( + X, y, split, qoi_name, out + ) + + for nsparg in range(3, 10): + print( + f" {qoi_name} ({model_type}), max_spargers={nsparg}...", + end="", + flush=True, + ) + mean_optimum, ci95 = run_constrained_optimization( + X, + y, + model_type=model_type, + params=params, + max_spargers=nsparg, + n_runs=10, + max_iters=1000, + bootstrap_size=250, + ) + print(f" mean={mean_optimum:.6g} ci95={ci95:.6g}") + results.append( + { + "level": level_label, + "qoi_name": qoi_name, + "model_type": model_type, + "n_spargers": nsparg, + "optimal_qoi_mean": mean_optimum, + "optimal_qoi_ci95": ci95, + } + ) + + out_file = "marginal_gain_results.csv" + with open(out_file, "w", newline="") as f: + writer = csv.DictWriter( + f, + fieldnames=[ + "level", + "qoi_name", + "model_type", + "n_spargers", + "optimal_qoi_mean", + "optimal_qoi_ci95", + ], + ) + writer.writeheader() + writer.writerows(results) + print(f"\nWrote {out_file}") diff --git a/papers/scaleup/SA_optimization/load_data.py b/papers/scaleup/SA_optimization/load_data.py new file mode 100644 index 00000000..244cde68 --- /dev/null +++ b/papers/scaleup/SA_optimization/load_data.py @@ -0,0 +1,45 @@ +import os + +import numpy as np +import pandas as pd + +# the 4 QoI value columns the surrogate can target (each has a matching _err) +QOI_VALUE_COLS = ["qoi", "qoi_kla", "qoi_sum", "qoi_sum_kla"] +QOI_ERR_COLS = ["qoi_err", "qoi_kla_err", "qoi_sum_err", "qoi_sum_kla_err"] + +# QoI assigned to unreliable designs, and the SNR gate for "reliable" +FAILED_QOI_VALUE = 0.0 +SNR_THRESHOLD = 5.0 + + +def _is_reliable(value: float, err: float, threshold: float) -> bool: + """True when the signal-to-noise ratio |value| / err meets the threshold.""" + return err > 0 and abs(value) / err >= threshold + + +def load_full_dataset(study_path: str) -> tuple[np.ndarray, pd.DataFrame]: + converged_X = pd.read_csv( + os.path.join(study_path, "X_data.csv"), header=None + ).values + converged_Y = pd.read_csv(os.path.join(study_path, "Y_data.csv")) + + X = converged_X.astype(int) + Y_rows = [] + for row_index in range(len(converged_Y)): + source = converged_Y.iloc[row_index] + row = {"sim_id": int(source["sim_id"])} + for qoi, err_col in zip(QOI_VALUE_COLS, QOI_ERR_COLS): + value = float(source[qoi]) + err = float(source[err_col]) + row[qoi] = ( + value + if _is_reliable(value, err, SNR_THRESHOLD) + else FAILED_QOI_VALUE + ) + row[err_col] = err + Y_rows.append(row) + + column_order = ["sim_id"] + QOI_VALUE_COLS + QOI_ERR_COLS + Y = pd.DataFrame(Y_rows)[column_order].reset_index(drop=True) + Y["sim_id"] = Y["sim_id"].astype(int) + return X, Y diff --git a/papers/scaleup/SA_optimization/make_hyperparam_tables.py b/papers/scaleup/SA_optimization/make_hyperparam_tables.py new file mode 100644 index 00000000..8afbc06d --- /dev/null +++ b/papers/scaleup/SA_optimization/make_hyperparam_tables.py @@ -0,0 +1,158 @@ +import json +from pathlib import Path +from typing import Callable + +SCRIPT_DIR = Path(__file__).parent +STUDY_DIR = SCRIPT_DIR / "data" / "study" + +# QoI key -> LaTeX row label. Order matches QOI_COLS in get_optimal_all_qois.py. +QOI_LABELS = { + "qoi": r"$\rm{QOI}_1 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_kla": r"$\rm{QOI}_2 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_sum": r"$\rm{QOI}_3 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_sum_kla": r"$\rm{QOI}_4 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", +} + +# Surrogate label -> key inside the hyperparams JSON. +SURROGATE_COLUMNS = {"RBF": "rbf", "RF": "rf", "MLP": "nn"} + +LEVELS = ("lev1", "lev6") + + +def format_int(value: float) -> str: + return str(int(value)) + + +def format_float(value: float) -> str: + """3 significant figures; scientific notation rewritten to LaTeX math.""" + text = f"{value:.3g}" + if "e" in text: + mantissa, exponent = text.split("e") + return rf"{mantissa}\times10^{{{int(exponent)}}}" + return text + + +def format_kernel(value: str) -> str: + return rf"\texttt{{{value.replace('_', r'\_')}}}" + + +# Per-surrogate column spec: (json param key, LaTeX header, formatter, is_math). +Formatter = Callable[[object], str] +SURROGATE_PARAMS: dict[str, list[tuple[str, str, Formatter, bool]]] = { + "RBF": [ + ("epsilon", r"$\epsilon$", format_float, True), + ("kernel", "Kernel", format_kernel, False), + ], + "RF": [ + ("n_estimators", r"$n_{\rm trees}$", format_int, True), + ("max_depth", "depth", format_int, True), + ("min_samples_leaf", "min. leaf", format_int, True), + ("max_features", "max. feat.", format_float, True), + ], + "MLP": [ + ("n_units", "units", format_int, True), + ("n_layers", "layers", format_int, True), + ("lr", "lr", format_float, True), + ], +} + + +def read_params(level: str, qoi_key: str, model_key: str) -> dict: + """Optimal hyperparameters for one level/QoI/surrogate.""" + json_path = ( + STUDY_DIR + / f"study_0_4vvm_{level}" + / qoi_key + / f"hyperparams_{qoi_key}.json" + ) + with open(json_path) as json_file: + hyperparams = json.load(json_file) + return hyperparams[model_key]["params"] + + +def build_cell(lev1_text: str, lev6_text: str, is_math: bool) -> str: + inner = f"{lev1_text} / {lev6_text}" + body = f"${inner}$" if is_math else inner + return rf"\rev{{{body}}}" + + +def build_table(surrogate_label: str) -> str: + model_key = SURROGATE_COLUMNS[surrogate_label] + columns = SURROGATE_PARAMS[surrogate_label] + headers = [header for _, header, _, _ in columns] + + lines = [ + r"\begin{table}[h]", + r"\centering", + r"\begin{tabular}{ |l|" + "c|" * len(headers) + " }", + r"\hline", + r"\rev{QoI} & " + + " & ".join(rf"\rev{{{header}}}" for header in headers) + + r" \\", + r"\hline", + ] + + for qoi_key, row_label in QOI_LABELS.items(): + lev1_params = read_params("lev1", qoi_key, model_key) + lev6_params = read_params("lev6", qoi_key, model_key) + cells = [ + build_cell( + formatter(lev1_params[param_key]), + formatter(lev6_params[param_key]), + is_math, + ) + for param_key, _, formatter, is_math in columns + ] + lines.append( + rf"\rev{{{row_label}}} & " + " & ".join(cells) + r" \\ \hline" + ) + + lines += [ + r"\end{tabular}", + rf"\caption{{\rev{{Optimal {surrogate_label} hyperparameters for " + r"each QoI, at reactor scales $3.6\,$L (lev1) $/$ $608\,$m$^3$ " + r"(lev6).}}", + rf"\label{{tab:hyperparams_{model_key}}}", + r"\end{table}", + ] + return "\n".join(lines) + + +def write_wrapper(table_file_names: list[str], out_path: Path) -> None: + """Standalone document that defines \\rev (red) and inputs each table.""" + inputs = [rf"\input{{{name}}}" for name in table_file_names] + wrapper = "\n".join( + [ + r"\documentclass{article}", + r"\usepackage[margin=1in]{geometry}", + r"\usepackage{xcolor}", + r"\newcommand{\rev}[1]{\textcolor{red}{#1}}", + r"\begin{document}", + *inputs, + r"\end{document}", + ] + ) + with open(out_path, "w") as wrapper_file: + wrapper_file.write(wrapper) + print(f"Wrote {out_path}") + + +def main() -> None: + table_file_names = [] + for surrogate_label, model_key in SURROGATE_COLUMNS.items(): + table = build_table(surrogate_label) + print(table) + print() + + table_file_name = f"hyperparams_{model_key}_table.tex" + table_path = SCRIPT_DIR / table_file_name + with open(table_path, "w") as table_file: + table_file.write(table) + print(f"Wrote {table_path}") + table_file_names.append(table_file_name) + + write_wrapper(table_file_names, SCRIPT_DIR / "view_hyperparam_tables.tex") + + +if __name__ == "__main__": + main() diff --git a/papers/scaleup/SA_optimization/make_val_rmse_table.py b/papers/scaleup/SA_optimization/make_val_rmse_table.py new file mode 100644 index 00000000..f1d630ef --- /dev/null +++ b/papers/scaleup/SA_optimization/make_val_rmse_table.py @@ -0,0 +1,117 @@ +import json +from pathlib import Path + +SCRIPT_DIR = Path(__file__).parent +STUDY_DIR = SCRIPT_DIR / "data" / "study" + +# QoI key -> LaTeX row label. Order matches QOI_COLS in get_optimal_all_qois.py. +QOI_LABELS = { + "qoi": r"$\rm{QOI}_1 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_kla": r"$\rm{QOI}_2 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_sum": r"$\rm{QOI}_3 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", + "qoi_sum_kla": r"$\rm{QOI}_4 (3.6\, \rm{L}~/~608\, \rm{m}^3)$", +} + +# Surrogate column header -> key inside the hyperparams JSON. +SURROGATE_COLUMNS = {"RBF": "rbf", "RF": "rf", "MLP": "nn"} + +LEVELS = ("lev1", "lev6") +METRIC_KEY = "val_nrmse_amp_pct" + + +def read_val_nrmse(level: str, qoi_key: str) -> dict[str, float]: + """Validation nRMSE (% of amplitude) for each surrogate at one level/QoI.""" + json_path = ( + STUDY_DIR + / f"study_0_4vvm_{level}" + / qoi_key + / f"hyperparams_{qoi_key}.json" + ) + with open(json_path) as json_file: + hyperparams = json.load(json_file) + return { + column: float(hyperparams[model_key][METRIC_KEY]) + for column, model_key in SURROGATE_COLUMNS.items() + } + + +def format_number(value: float, is_lowest: bool) -> str: + text = f"{value:.1f}" + return rf"\textbf{{{text}}}" if is_lowest else text + + +def build_cell( + lev1_value: float, + lev6_value: float, + lev1_is_lowest: bool, + lev6_is_lowest: bool, +) -> str: + lev1_text = format_number(lev1_value, lev1_is_lowest) + lev6_text = format_number(lev6_value, lev6_is_lowest) + return rf"${lev1_text}\% / {lev6_text}\%$" + + +def build_table() -> str: + column_headers = list(SURROGATE_COLUMNS) + lines = [ + r"\begin{tabular}{l" + "c" * len(column_headers) + "}", + r"\hline", + "QoI & " + " & ".join(column_headers) + r" \\", + r"\hline", + ] + + for qoi_key, row_label in QOI_LABELS.items(): + lev1_values = read_val_nrmse("lev1", qoi_key) + lev6_values = read_val_nrmse("lev6", qoi_key) + lev1_lowest_column = min(lev1_values, key=lev1_values.get) + lev6_lowest_column = min(lev6_values, key=lev6_values.get) + + cells = [ + build_cell( + lev1_values[column], + lev6_values[column], + column == lev1_lowest_column, + column == lev6_lowest_column, + ) + for column in column_headers + ] + lines.append(f"{row_label} & " + " & ".join(cells) + r" \\") + + lines += [r"\hline", r"\end{tabular}"] + return "\n".join(lines) + + +def write_wrapper(table_file_name: str, out_path: Path) -> None: + wrapper = "\n".join( + [ + r"\documentclass{article}", + r"\usepackage[margin=1in]{geometry}", + r"\begin{document}", + r"\begin{table}[h]", + r"\centering", + rf"\input{{{table_file_name}}}", + r"\caption{Validation nRMSE relative to amplitude " + r"(lev1 $3.6\,$L / lev6 $608\,$m$^3$); lowest per level in bold.}", + r"\end{table}", + r"\end{document}", + ] + ) + with open(out_path, "w") as wrapper_file: + wrapper_file.write(wrapper) + print(f"Wrote {out_path}") + + +def main() -> None: + table = build_table() + print(table) + + table_path = SCRIPT_DIR / "val_rmse_table.tex" + with open(table_path, "w") as table_file: + table_file.write(table) + print(f"Wrote {table_path}") + + write_wrapper("val_rmse_table.tex", SCRIPT_DIR / "view_val_rmse_table.tex") + + +if __name__ == "__main__": + main() diff --git a/papers/scaleup/SA_optimization/marginal_gain_results.csv b/papers/scaleup/SA_optimization/marginal_gain_results.csv new file mode 100644 index 00000000..9723e371 --- /dev/null +++ b/papers/scaleup/SA_optimization/marginal_gain_results.csv @@ -0,0 +1,57 @@ +level,qoi_name,model_type,n_spargers,optimal_qoi_mean,optimal_qoi_ci95 +lev1,qoi,nn,3,20.777002658440317,4.967135709603668 +lev1,qoi,nn,4,29.33137591333509,6.052693630554447 +lev1,qoi,nn,5,28.728691798440696,7.782960094406028 +lev1,qoi,nn,6,28.00670375941676,5.250816613929773 +lev1,qoi,nn,7,26.578156696520818,6.211729307089006 +lev1,qoi,nn,8,25.752087994106507,5.750639405478412 +lev1,qoi,nn,9,33.39666583737389,6.095517715388951 +lev1,qoi_kla,nn,3,2.1630368613455053e-12,5.646098656009841e-13 +lev1,qoi_kla,nn,4,2.1810997777515023e-12,7.571885282140608e-13 +lev1,qoi_kla,nn,5,2.2262035694651713e-12,7.283823393852845e-13 +lev1,qoi_kla,nn,6,1.919642208364238e-12,7.524940381917437e-13 +lev1,qoi_kla,nn,7,2.270919638464332e-12,6.688943592320943e-13 +lev1,qoi_kla,nn,8,2.1171600394206276e-12,7.240310078697636e-13 +lev1,qoi_kla,nn,9,2.704915189390905e-12,8.320571300855766e-13 +lev1,qoi_sum,nn,3,34.330421521427105,1.5979910200579341 +lev1,qoi_sum,nn,4,36.93759964547867,2.6326362889827815 +lev1,qoi_sum,nn,5,37.37891391484199,1.9716201424039503 +lev1,qoi_sum,nn,6,37.88222566926674,2.0477026431202336 +lev1,qoi_sum,nn,7,38.30321346647001,1.5016840895363077 +lev1,qoi_sum,nn,8,38.52937161920444,1.9463582167721076 +lev1,qoi_sum,nn,9,38.44378376449916,2.5630231918745983 +lev1,qoi_sum_kla,nn,3,7.804334100887237e-06,1.3813566415684952e-07 +lev1,qoi_sum_kla,nn,4,7.8251175178686e-06,1.1370595131964046e-07 +lev1,qoi_sum_kla,nn,5,7.734468577471196e-06,2.8786262283158653e-07 +lev1,qoi_sum_kla,nn,6,7.827537738907247e-06,1.5470669237093723e-07 +lev1,qoi_sum_kla,nn,7,7.704540831548307e-06,2.2034748906434659e-07 +lev1,qoi_sum_kla,nn,8,7.739101235354367e-06,2.6253140249004177e-07 +lev1,qoi_sum_kla,nn,9,7.619820316451526e-06,3.25479214629696e-07 +lev6,qoi,nn,3,15.909415092123254,0.46775342270960824 +lev6,qoi,nn,4,17.479575262616905,0.8682770294330613 +lev6,qoi,nn,5,18.754729256260596,0.529543994336786 +lev6,qoi,nn,6,19.886590714439063,0.3755539258889765 +lev6,qoi,nn,7,21.433241721384228,0.5610737501452722 +lev6,qoi,nn,8,21.610978671926706,1.0828448639168482 +lev6,qoi,nn,9,20.93777004972596,1.9637920266145474 +lev6,qoi_kla,nn,3,0.24658579471534098,0.008536403046175908 +lev6,qoi_kla,nn,4,0.27306325796051867,0.0057937584699469255 +lev6,qoi_kla,nn,5,0.2941745217305499,0.00715797413420681 +lev6,qoi_kla,nn,6,0.30658919100619186,0.00623891361279496 +lev6,qoi_kla,nn,7,0.31463449818349964,0.005752463990180858 +lev6,qoi_kla,nn,8,0.3187942689999229,0.008043733761107999 +lev6,qoi_kla,nn,9,0.33383378816617665,0.007553545891181331 +lev6,qoi_sum,nn,3,37.37678159715111,0.7814896878666623 +lev6,qoi_sum,nn,4,38.04317682799514,0.6625226569542539 +lev6,qoi_sum,nn,5,39.5093564959566,0.9260206104420369 +lev6,qoi_sum,nn,6,39.70000734500967,0.592021708828062 +lev6,qoi_sum,nn,7,39.07709702857392,0.4739951040219765 +lev6,qoi_sum,nn,8,39.57371845662897,0.18470348275441084 +lev6,qoi_sum,nn,9,39.844698183642166,0.3826178119788762 +lev6,qoi_sum_kla,rbf,3,4.830869504994335,0.10543249459025254 +lev6,qoi_sum_kla,rbf,4,4.966668120244677,0.15220367538664611 +lev6,qoi_sum_kla,rbf,5,5.111496616028076,0.07325606131503833 +lev6,qoi_sum_kla,rbf,6,5.182008623639471,0.0704755723932477 +lev6,qoi_sum_kla,rbf,7,5.161792010502566,0.08237835929861465 +lev6,qoi_sum_kla,rbf,8,5.252289373978056,0.04793709953939311 +lev6,qoi_sum_kla,rbf,9,5.233795924095803,0.04269007121971121 diff --git a/papers/scaleup/SA_optimization/model_selection.py b/papers/scaleup/SA_optimization/model_selection.py new file mode 100644 index 00000000..a44ba125 --- /dev/null +++ b/papers/scaleup/SA_optimization/model_selection.py @@ -0,0 +1,139 @@ +import json +import os + +import numpy as np +import pandas as pd +from sklearn.metrics import mean_squared_error +from surrogate import Surrogate_wrapper, tune_nn, tune_rbf, tune_rf + + +def make_or_load_split( + study_path: str, + n_samples: int, + n_test: int = 20, + n_val: int = 20, + seed: int = 0, +) -> dict: + """Return {'train','test','val'} row-index arrays, frozen in split.csv. + + If split.csv already exists in ``study_path`` it is loaded verbatim so the + split is reproducible across runs; otherwise it is drawn deterministically + from ``seed`` and written. + """ + split_file = os.path.join(study_path, "split.csv") + if os.path.exists(split_file): + df = pd.read_csv(split_file) + return { + name: df.loc[df["set"] == name, "row_index"].to_numpy() + for name in ("train", "test", "val") + } + + rng = np.random.default_rng(seed) + perm = rng.permutation(n_samples) + test_idx = perm[:n_test] + val_idx = perm[n_test : n_test + n_val] + train_idx = perm[n_test + n_val :] + + rows = ( + [(int(i), "test") for i in test_idx] + + [(int(i), "val") for i in val_idx] + + [(int(i), "train") for i in train_idx] + ) + pd.DataFrame(rows, columns=["row_index", "set"]).to_csv( + split_file, index=False + ) + return {"train": train_idx, "test": test_idx, "val": val_idx} + + +def _predict_batch(surrogate: Surrogate_wrapper, X: np.ndarray) -> np.ndarray: + """Row-wise predictions (Surrogate_wrapper.predict is single-sample).""" + return np.array([surrogate.predict(X[i]) for i in range(len(X))]) + + +def select_or_load_surrogate( + X: np.ndarray, + y: np.ndarray, + split: dict, + qoi_name: str, + out_folder: str, + n_trials: int = 100, +) -> tuple[str, dict]: + """Tune RBF, RF, and NN on the test set, pick the winner on the validation set. + + Caches the full result to ``hyperparams_{qoi_name}.json`` and reloads it on + subsequent calls so both drivers reuse one selection. Returns + ``(best_model_type, best_params)``. + """ + os.makedirs(out_folder, exist_ok=True) + json_file = os.path.join(out_folder, f"hyperparams_{qoi_name}.json") + if os.path.exists(json_file): + with open(json_file) as f: + record = json.load(f) + return record["best"], record["best_params"] + + X_train, y_train = X[split["train"]], y[split["train"]] + X_test, y_test = X[split["test"]], y[split["test"]] + X_val, y_val = X[split["val"]], y[split["val"]] + + # physical QoI reference values (y is the negated min-space target, so + # physical QoI = -y). Amplitude = max - min = the CFD data range height. + physical = -y + amp_physical = float(np.max(physical) - np.min(physical)) + mean_physical = float(np.mean(physical)) + + def nrmse_pct(mse: float, denom: float) -> float: + """Normalized RMSE as a percent of a physical-QoI reference.""" + if denom == 0: + return float("nan") + return 100.0 * np.sqrt(mse) / abs(denom) + + # 1. HPO scored on the test set + tuners = {"rbf": tune_rbf, "rf": tune_rf, "nn": tune_nn} + tuned = { + name: tuner(X_train, y_train, X_test, y_test, n_trials=n_trials) + for name, tuner in tuners.items() + } + + # 2. compare on the validation set (each refit on the train pool). MSE is in + # physical units since Surrogate_wrapper.predict inverse-transforms. + results = {} + for model_type, params in tuned.items(): + surrogate = Surrogate_wrapper(model_type, X_train, y_train, params) + test_mse = mean_squared_error( + y_test.ravel(), _predict_batch(surrogate, X_test) + ) + val_mse = mean_squared_error( + y_val.ravel(), _predict_batch(surrogate, X_val) + ) + results[model_type] = { + "params": params, + "test_mse": float(test_mse), + "val_mse": float(val_mse), + "test_nrmse_amp_pct": float(nrmse_pct(test_mse, amp_physical)), + "test_nrmse_mean_pct": float(nrmse_pct(test_mse, mean_physical)), + "val_nrmse_amp_pct": float(nrmse_pct(val_mse, amp_physical)), + "val_nrmse_mean_pct": float(nrmse_pct(val_mse, mean_physical)), + } + + best = min(results, key=lambda m: results[m]["val_mse"]) + record = { + "qoi": qoi_name, + "best": best, + "best_params": results[best]["params"], + "amp_physical": amp_physical, + "mean_physical": mean_physical, + **results, + } + with open(json_file, "w") as f: + json.dump(record, f, indent=2) + + val_summary = ", ".join( + f"{m.upper()} val_mse={results[m]['val_mse']:.6g}" + f" (nRMSE amp={results[m]['val_nrmse_amp_pct']:.1f}%" + f" mean={results[m]['val_nrmse_mean_pct']:.1f}%)" + for m in results + ) + print(f" {qoi_name}: {val_summary} -> best={best}") + for m in results: + print(f" {m.upper()} params: {results[m]['params']}") + return best, results[best]["params"] diff --git a/papers/scaleup/SA_optimization/plot_marginal_gain.py b/papers/scaleup/SA_optimization/plot_marginal_gain.py new file mode 100644 index 00000000..cdc4926e --- /dev/null +++ b/papers/scaleup/SA_optimization/plot_marginal_gain.py @@ -0,0 +1,72 @@ +import os + +import pandas as pd +from prettyPlot.plotting import plt, pretty_labels + +QOI_LABELS = { + "qoi": { + "label": "QOI", + # "ylabel": r"Optimal QOI [kg$^2$/kWh$^2$]", + "ylabel": r"Optimal QOI$_1$ [kg$^2$/kWh$^2$]", + }, + "qoi_kla": { + "label": "QOI Num", + # "ylabel": r"Optimal QOI Num [kg$^2$/s$^2$]", + "ylabel": r"Optimal QOI$_2$ [kg$^2$/s$^2$]", + }, + "qoi_sum": { + "label": "QOI Sum", + # "ylabel": r"Optimal QOI Sum [kg/kWh]", + "ylabel": r"Optimal QOI$_3$ [kg/kWh]", + }, + "qoi_sum_kla": { + "label": "QOI Sum Num", + # "ylabel": r"Optimal QOI Sum Num [kg/s]", + "ylabel": r"Optimal QOI$_4$ [kg/s]", + }, +} + +LEVEL_TITLES = { + "lev1": "3.6 L reactor", + "lev6": r"608 m$^3$ reactor", +} + + +if __name__ == "__main__": + df = pd.read_csv("marginal_gain_results.csv") + + for level in df["level"].unique(): + df_lev = df[df["level"] == level] + for qoi_name in df_lev["qoi_name"].unique(): + df_q = df_lev[df_lev["qoi_name"] == qoi_name].sort_values( + "n_spargers" + ) + info = QOI_LABELS[qoi_name] + + n_spargers = df_q["n_spargers"].values[:-1] + mean_optimum = df_q["optimal_qoi_mean"].values[:-1] + ci95 = df_q["optimal_qoi_ci95"].values[:-1] + + fig, ax = plt.subplots() + ax.plot(n_spargers, mean_optimum, linewidth=3, color="k") + ax.fill_between( + n_spargers, + mean_optimum - ci95, + mean_optimum + ci95, + color="k", + alpha=0.25, + label="95% CI", + ) + pretty_labels( + r"N$_{\rm sparg}$", + info["ylabel"], + 20, + fontname="Times", + grid=False, + title=LEVEL_TITLES.get(level, level), + ) + fname = f"marginal_gain_{level}_{qoi_name}" + plt.savefig(f"{fname}.png", dpi=300) + plt.savefig(f"{fname}.pdf") + plt.close() + print(f"Saved {fname}.png/.pdf") diff --git a/papers/scaleup/SA_optimization/surrogate.py b/papers/scaleup/SA_optimization/surrogate.py new file mode 100644 index 00000000..565ecac8 --- /dev/null +++ b/papers/scaleup/SA_optimization/surrogate.py @@ -0,0 +1,273 @@ +import warnings + +import numpy as np +import optuna +import torch +import torch.nn as nn +from scipy.interpolate import RBFInterpolator +from sklearn.ensemble import RandomForestRegressor +from sklearn.metrics import mean_squared_error +from sklearn.preprocessing import OneHotEncoder, StandardScaler + +warnings.filterwarnings("ignore") +optuna.logging.set_verbosity(optuna.logging.WARNING) + +# epsilon-using RBF kernels (so tuning epsilon stays meaningful for each) +RBF_KERNELS = ( + "multiquadric", + "inverse_multiquadric", + "inverse_quadratic", + "gaussian", +) + +# the 11 design variables are unordered categoricals {0=mixer, 1=sparger, 2=wall} +DESIGN_CATEGORIES = (0, 1, 2) + + +def make_encoder(n_features: int = 11) -> OneHotEncoder: + """One-hot encoder shared by all surrogates. + + Categories are fixed to {0, 1, 2} for every design variable so the encoded + width is always 3 x n_features, regardless of which values happen to appear + in a given train/bootstrap subset. + """ + return OneHotEncoder( + categories=[list(DESIGN_CATEGORIES)] * n_features, + sparse_output=False, + handle_unknown="ignore", + ) + + +def check_data_shape(X: np.ndarray, y: np.ndarray) -> None: + """Validate shapes: (N, d) for X, (N, 1) for y.""" + assert X.shape[0] == y.shape[0] + assert len(X.shape) == 2 + assert len(y.shape) == 2 + assert y.shape[1] == 1 + print(f"INFO: {X.shape[0]} sim with {X.shape[1]} design variables") + + +def tune_rbf( + X_train: np.ndarray, + y_train: np.ndarray, + X_test: np.ndarray, + y_test: np.ndarray, + n_trials: int = 100, +) -> dict: + """Tune RBF epsilon + kernel type by MSE on a held-out test set.""" + check_data_shape(X=X_train, y=y_train) + check_data_shape(X=X_test, y=y_test) + encoder = make_encoder(X_train.shape[1]) + X_train_enc = encoder.fit_transform(X_train) + X_test_enc = encoder.transform(X_test) + y_scaler = StandardScaler().fit(y_train) + y_train_s = y_scaler.transform(y_train) + y_test_s = y_scaler.transform(y_test) + + def objective(trial): + kernel = trial.suggest_categorical("kernel", list(RBF_KERNELS)) + epsilon = trial.suggest_float("epsilon", 0.1, 10.0, log=False) + try: + model = RBFInterpolator( + X_train_enc, y_train_s, epsilon=epsilon, kernel=kernel + ) + return mean_squared_error(y_test_s, model(X_test_enc)) + except Exception: + return float("inf") + + study = optuna.create_study(direction="minimize") + study.optimize(objective, n_trials=n_trials) + return study.best_params + + +def tune_rf( + X_train: np.ndarray, + y_train: np.ndarray, + X_test: np.ndarray, + y_test: np.ndarray, + n_trials: int = 100, +) -> dict: + """Tune RandomForest hyperparameters by MSE on a held-out test set.""" + check_data_shape(X=X_train, y=y_train) + check_data_shape(X=X_test, y=y_test) + encoder = make_encoder(X_train.shape[1]) + X_train_enc = encoder.fit_transform(X_train) + X_test_enc = encoder.transform(X_test) + y_scaler = StandardScaler().fit(y_train) + y_train_s = y_scaler.transform(y_train) + y_test_s = y_scaler.transform(y_test) + + def objective(trial): + model = RandomForestRegressor( + n_estimators=trial.suggest_int("n_estimators", 50, 200), + max_depth=trial.suggest_int("max_depth", 3, 10), + min_samples_leaf=trial.suggest_int("min_samples_leaf", 1, 10), + max_features=trial.suggest_float("max_features", 0.1, 1.0), + random_state=42, + ) + model.fit(X_train_enc, y_train_s.ravel()) + return mean_squared_error(y_test_s, model.predict(X_test_enc)) + + study = optuna.create_study(direction="minimize") + study.optimize(objective, n_trials=n_trials) + return study.best_params + + +def tune_nn( + X_train: np.ndarray, + y_train: np.ndarray, + X_test: np.ndarray, + y_test: np.ndarray, + n_trials: int = 100, +) -> dict: + """Tune NN units, layers, and learning rate by MSE on a held-out test set.""" + check_data_shape(X=X_train, y=y_train) + check_data_shape(X=X_test, y=y_test) + encoder = make_encoder(X_train.shape[1]) + X_train_enc = encoder.fit_transform(X_train) + X_test_enc = encoder.transform(X_test) + y_scaler = StandardScaler().fit(y_train) + y_train_s = y_scaler.transform(y_train) + y_test_s = y_scaler.transform(y_test) + + def objective(trial): + units = trial.suggest_int("n_units", 16, 128) + layers = trial.suggest_int("n_layers", 1, 3) + lr = trial.suggest_float("lr", 1e-4, 1e-2, log=True) + model = _build_nn(X_train_enc.shape[1], units, layers) + _train_nn(model, X_train_enc, y_train_s, lr=lr) + with torch.no_grad(): + X_t = torch.tensor(X_test_enc, dtype=torch.float32) + preds = model(X_t).numpy().flatten() + return mean_squared_error(y_test_s, preds) + + study = optuna.create_study(direction="minimize") + study.optimize(objective, n_trials=n_trials) + return study.best_params + + +def _build_nn(input_dim: int, units: int, layers: int) -> nn.Sequential: + """Build a PyTorch Sequential model.""" + layer_list = [nn.Linear(input_dim, units), nn.ReLU()] + for _ in range(layers - 1): + layer_list.extend([nn.Linear(units, units), nn.ReLU()]) + layer_list.append(nn.Linear(units, 1)) + return nn.Sequential(*layer_list) + + +def _train_nn( + model: nn.Sequential, + X: np.ndarray, + y: np.ndarray, + epochs: int = 1000, + lr: float = 1e-3, + patience: int = 50, + val_frac: float = 0.15, + min_delta: float = 1e-5, +) -> None: + """Train in-place (full-batch Adam) with early stopping. + + A fraction ``val_frac`` of the passed data is held out to monitor validation + loss; training stops once it has not improved by ``min_delta`` for + ``patience`` consecutive epochs, and the best weights are restored. The + holdout is carved from the training data given here, so it never touches the + outer test/validation split. + """ + n_samples = X.shape[0] + n_val = int(round(n_samples * val_frac)) + perm = np.random.default_rng(0).permutation(n_samples) + val_idx, train_idx = perm[:n_val], perm[n_val:] + if n_val < 1 or train_idx.size < 1: # too small to hold out: monitor train + val_idx = train_idx = np.arange(n_samples) + + X_train = torch.tensor(X[train_idx], dtype=torch.float32) + y_train = torch.tensor(y[train_idx], dtype=torch.float32) + X_val = torch.tensor(X[val_idx], dtype=torch.float32) + y_val = torch.tensor(y[val_idx], dtype=torch.float32) + + optimizer = torch.optim.Adam(model.parameters(), lr=lr) + loss_fn = nn.MSELoss() + best_val_loss = float("inf") + best_state = None + epochs_without_improvement = 0 + for _ in range(epochs): + model.train() + optimizer.zero_grad() + loss_fn(model(X_train), y_train).backward() + optimizer.step() + model.eval() + with torch.no_grad(): + val_loss = float(loss_fn(model(X_val), y_val)) + if val_loss < best_val_loss - min_delta: + best_val_loss = val_loss + best_state = { + name: t.detach().clone() + for name, t in model.state_dict().items() + } + epochs_without_improvement = 0 + else: + epochs_without_improvement += 1 + if epochs_without_improvement >= patience: + break + if best_state is not None: + model.load_state_dict(best_state) + model.eval() + + +class Surrogate_wrapper: + """Unified predict() interface for RBF, RF, and NN surrogates. + + All three share one one-hot encoding of the raw {0, 1, 2} design variables + and one standardization of the targets, both fit here on the training data. + Targets are standardized before fitting; predict() inverse-transforms so its + return value is always in physical units. predict() takes a raw design vector + and encodes it, so the caller (simulated annealing) stays in raw design space. + """ + + def __init__( + self, + model_type: str, + X: np.ndarray, + y: np.ndarray, + params: dict, + ): + self.model_type = model_type.lower() + self.encoder = make_encoder(X.shape[1]) + X_encoded = self.encoder.fit_transform(X) + self.y_scaler = StandardScaler().fit(y) + y_scaled = self.y_scaler.transform(y) + + if self.model_type == "rbf": + self.model = RBFInterpolator( + X_encoded, + y_scaled, + kernel=params.get("kernel", "multiquadric"), + epsilon=params["epsilon"], + ) + elif self.model_type == "rf": + self.model = RandomForestRegressor(**params, random_state=42) + self.model.fit(X_encoded, y_scaled.ravel()) + elif self.model_type == "nn": + self.model = _build_nn( + X_encoded.shape[1], + params["n_units"], + params["n_layers"], + ) + _train_nn( + self.model, X_encoded, y_scaled, lr=params.get("lr", 1e-3) + ) + else: + raise NotImplementedError(f"Unknown model_type: {model_type}") + + def predict(self, X: np.ndarray) -> float: + """Return the physical-space prediction for one raw design vector.""" + X_enc = self.encoder.transform(X.reshape(1, -1)) + if self.model_type == "nn": + with torch.no_grad(): + X_t = torch.tensor(X_enc, dtype=torch.float32) + scaled = self.model(X_t).item() + elif self.model_type == "rf": + scaled = self.model.predict(X_enc)[0] + else: + scaled = float(np.squeeze(self.model(X_enc))) + return float(self.y_scaler.inverse_transform([[scaled]])[0, 0]) diff --git a/papers/scaleup/SA_optimization/surrogate_selection.csv b/papers/scaleup/SA_optimization/surrogate_selection.csv new file mode 100644 index 00000000..23773d57 --- /dev/null +++ b/papers/scaleup/SA_optimization/surrogate_selection.csv @@ -0,0 +1,9 @@ +level,qoi_name,best,val_mse,val_nrmse_amp_pct,val_nrmse_mean_pct,best_params +lev6,qoi,nn,2.5414217695066155,10.346422847895706,12.51112854539323,"{'n_units': 23, 'n_layers': 2, 'lr': 0.0009480593464653759}" +lev6,qoi_kla,nn,0.0006345451226036295,10.660299052886097,12.626611466642379,"{'n_units': 36, 'n_layers': 2, 'lr': 0.009975314935443623}" +lev6,qoi_sum,nn,3.1047786209819535,8.802302307279254,5.488729982414982,"{'n_units': 38, 'n_layers': 2, 'lr': 0.009796559328428031}" +lev6,qoi_sum_kla,rbf,0.0639246836136791,10.31320641871671,6.2904200932450625,"{'kernel': 'multiquadric', 'epsilon': 0.2921716473956134}" +lev1,qoi,nn,0.04559337741600136,0.6704719275922347,18.426961145633662,"{'n_units': 115, 'n_layers': 3, 'lr': 0.007352422228350128}" +lev1,qoi_kla,nn,1.4334769254169032e-26,4.152094975112983,29.08632682734781,"{'n_units': 58, 'n_layers': 3, 'lr': 0.004000778796522329}" +lev1,qoi_sum,nn,0.6018713490278378,3.2021518530766255,10.45378113072208,"{'n_units': 32, 'n_layers': 3, 'lr': 0.003626140666750365}" +lev1,qoi_sum_kla,nn,3.7395053463098084e-13,12.835729422646637,9.480054040832073,"{'n_units': 52, 'n_layers': 2, 'lr': 0.00027717283587404306}" diff --git a/papers/scaleup/generate_scaleup_runs/README.md b/papers/scaleup/generate_scaleup_runs/README.md new file mode 100644 index 00000000..9bca124a --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/README.md @@ -0,0 +1,3 @@ +`python randsim.py` generates study folders that contain an ensemble of Openfoam case folders, each with a different design variable sample + +The case folders use `template` as a template openfoam folder to create the new openfoam case folders. diff --git a/papers/scaleup/generate_scaleup_runs/randsim.py b/papers/scaleup/generate_scaleup_runs/randsim.py new file mode 100644 index 00000000..6b518e3d --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/randsim.py @@ -0,0 +1,163 @@ +import os + +import numpy as np + +from bird.preprocess.json_gen.design_io import * +from bird.preprocess.json_gen.generate_designs import * + + +def optimization_setup(): + # spots on the branches where we can place sparger or mixers + branchcom_spots = {} + branchcom_spots[0] = np.linspace(0.2, 0.8, 4) + branchcom_spots[1] = np.linspace(0.2, 0.8, 3) + branchcom_spots[2] = np.linspace(0.2, 0.8, 4) + # branches where the sparger and mixers are placed + branches_com = [0, 1, 2] + return branchcom_spots, branches_com + + +# Shared design pool +# once it is generated, all the other studies borrow this file +# This is useful to check if QOI values match and are correlated +DESIGN_FILE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "designs.pkl" +) + + +if __name__ == "__main__": + branchcom_spots, branches_com = optimization_setup() + + config_dict = load_or_sample_designs( + DESIGN_FILE, branches_com, branchcom_spots, n_designs=400 + ) + + # --- hyperparameters of the study + vvm = 0.4 + constantD = True + # Dynamic mixer properties + # The sign business is because orientation depends on the branch + # so that the mixer pushes the flow consistently + mixer_params = { + "Np": 6, + "Vtip": 1.5, + "sigma": 0.35, + "radius": 0.4, + "sign": {0: "+", 1: "+", 2: "-"}, + "swirl_sign": {0: "+", 1: "+", 2: "-"}, + } + + # --- Setup the scale up study + # lev1 = 3.6 L, lev6 = 608 m3 + # 400 runs for lev 1 and lev 6 + # 200 runs for intermediate scales (match first 200 design variables + # of the 400 pool) + levels = [ + ("lev1", 0.05, 400), + ("lev2", 0.1, 200), + ("lev3", 0.2, 200), + ("lev4", 0.4, 200), + ("lev5", 0.8, 200), + ("lev6", 2.7615275385627096, 400), + ] + + # Per-level system/controlDict time-stepping. + # Coarser scales (higher levels) tolerate initial dt + level_controldict = { + "lev1": { + "maxCo": "0.25", + "maxDeltaT": "0.00025", + "deltaT": "1e-5", + "endTime": "100", + }, + "lev2": { + "maxCo": "0.25", + "maxDeltaT": "0.0005", + "deltaT": "2e-5", + "endTime": "200", + }, + "lev3": { + "maxCo": "0.25", + "maxDeltaT": "0.001", + "deltaT": "4e-5", + "endTime": "400", + }, + "lev4": { + "maxCo": "0.25", + "maxDeltaT": "0.002", + "deltaT": "5e-5", + "endTime": "400", + }, + "lev5": { + "maxCo": "0.25", + "maxDeltaT": "0.004", + "deltaT": "5e-5", + "endTime": "400", + }, + "lev6": { + "maxCo": "0.25", + "maxDeltaT": "0.005", + "deltaT": "1e-4", + "endTime": "400", + }, + } + + # Per-level get_qoi.py parameters + # gas density [kg/m3] at spargers change because of varying reactor height + # c* (low, high) uniform-prior bounds on the CO2/H2 depend on scale + level_qoi = { + "lev1": { + "rhog": 0.593333, + "cstar_co2": (7.68, 8.22), + "cstar_h2": (0.516, 0.548), + }, + "lev2": { + "rhog": 0.605962, + "cstar_co2": (6.8, 7.93), + "cstar_h2": (0.502, 0.514), + }, + "lev3": { + "rhog": 0.629974, + "cstar_co2": (7.04, 8.06), + "cstar_h2": (0.537, 0.557), + }, + "lev4": { + "rhog": 0.677935, + "cstar_co2": (8.3, 9.8), + "cstar_h2": (0.564, 0.601), + }, + "lev5": { + "rhog": 0.770533, + "cstar_co2": (7.89, 10.2), + "cstar_h2": (0.622, 0.653), + }, + "lev6": { + "rhog": 1.25, + "cstar_co2": (14, 16.9), + "cstar_h2": (1.04, 1.19), + }, + } + + parent = "study" + for name, scale, n_sim in levels: + study_folder = os.path.join(parent, f"study_0_4vvm_{name}") + generate_leveled_reactor_cases( + config_dict, + branchcom_spots, + scale=scale, + n_sim=n_sim, + study_folder=study_folder, + mixer_params=mixer_params, + vvm=vvm, + template_folder="./template", + constantD=constantD, # needs to be False if we do PBE + start_time=1, + account="gas2fuels", + cores_per_sim=8, # Pack as many sims per node as possible + cores_per_node=104, + walltime="120:00:00", + controldict_params=level_controldict[name], + rhog=level_qoi[name]["rhog"], + cstar_co2=level_qoi[name]["cstar_co2"], + cstar_h2=level_qoi[name]["cstar_h2"], + ) diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.gas new file mode 100644 index 00000000..e4165b1a --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_CO2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_CO2; + //value $f_CO2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.liquid new file mode 100644 index 00000000..4b8ea6a0 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/CO2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object CO2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.gas new file mode 100644 index 00000000..9f66b2d2 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 0; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_H2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_H2; + //value $f_H2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.liquid new file mode 100644 index 00000000..65ae8d34 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/H2.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object H2.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type zeroGradient; + //type fixedValue; + //value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/N2.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/N2.gas new file mode 100644 index 00000000..c1d7225f --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/N2.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object N2.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $f_N2; + } + + outlet + { + //type inletOutlet; + //phi phi.gas; + //inletValue $f_N2; + //value $f_N2; + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/T.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/T.gas new file mode 100644 index 00000000..bf0199a0 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/T.gas @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value $internalField; + } + + outlet + { + type inletOutlet; + phi phi.gas; + inletValue $internalField; + value $internalField; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/T.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/T.liquid new file mode 100644 index 00000000..7101ea31 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/T.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object T.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + outlet + { + type inletOutlet; + phi phi.liquid; + inletValue $internalField; + value $internalField; + } + inlet + { + type fixedValue; + value $internalField; + } + defaultFaces + { + type zeroGradient; + } + +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/U.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/U.gas new file mode 100644 index 00000000..e696566f --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/U.gas @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0.0 0); + +#include "${FOAM_CASE}/constant/globalVars" + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateGas; + //rho thermo:rho.gas; + //value $internalField; + type fixedValue; + value uniform (0 $uGasPhase 0); + } + outlet + { + type pressureInletOutletVelocity; + phi phi.gas; + value $internalField; + } + defaultFaces + { + type slip; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/U.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/U.liquid new file mode 100644 index 00000000..1879e020 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/U.liquid @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volVectorField; + object U.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform (0 0 0); + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + //type flowRateInletVelocity; + //massFlowRate $mflowRateLiq; + //rho thermo:rho.liquid; + //value $internalField; + type fixedValue; + value uniform (0 0 0); + } + outlet + { + type noSlip; + } + defaultFaces + { + type noSlip; + } + +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.gas new file mode 100644 index 00000000..fba2945d --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.gas @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 0.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.liquid new file mode 100644 index 00000000..a5108564 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/Ydefault.liquid @@ -0,0 +1,42 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object Ydefault.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.gas new file mode 100644 index 00000000..1e303fbe --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object alpha.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $alphaGas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaGas; + } + outlet + { + type inletOutlet; + phi phi.gas; + inletValue uniform 1; + value uniform 1; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.liquid new file mode 100644 index 00000000..5c92070b --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/alpha.liquid @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alpha.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform 1; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $alphaLiq; + } + outlet + { + type fixedValue; + value uniform 0; + } + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.gas new file mode 100644 index 00000000..b867958f --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.gas @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type calculated; + value $internalField; + //type compressible::alphatWallFunction; + //Prt 0.85; + //value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.liquid new file mode 100644 index 00000000..2569c3ee --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/alphat.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object alphat.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type compressible::alphatWallFunction; + Prt 0.85; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/f.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/f.gas new file mode 100644 index 00000000..76ee77a9 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/f.gas @@ -0,0 +1,41 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object f.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1.0; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform 1.0; //$internalField; // + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/k.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/k.gas new file mode 100644 index 00000000..4a3d44ca --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/k.gas @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_gas; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/k.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/k.liquid new file mode 100644 index 00000000..cde8f6c1 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/k.liquid @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object k.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $k_inlet_liq; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type fixedValue; + value uniform $k_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type kqRWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.gas new file mode 100644 index 00000000..ba16dd4c --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-8; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + //type nutkWallFunction; + //value $internalField; + type calculated; + value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.liquid new file mode 100644 index 00000000..1442e07f --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/nut.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object nut.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 1e-4; + +boundaryField +{ + #includeEtc "caseDicts/setConstraintTypes" + + inlet + { + type calculated; + value $internalField; + } + + outlet + { + type calculated; + value $internalField; + } + + defaultFaces + { + type nutkWallFunction; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.gas b/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.gas new file mode 100644 index 00000000..9a1b4816 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.gas @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_gas; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $omega_inlet_gas; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + //type epsilonWallFunction; + //value $internalField; + } + + // defaultFaces + // { + // type empty; + // } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.liquid b/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.liquid new file mode 100644 index 00000000..821a806d --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/omega.liquid @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object omega.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +#include "${FOAM_CASE}/constant/globalVars" + +internalField uniform $omega_inlet_liq; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform $omega_inlet_liq; + } + + outlet + { + type zeroGradient; + } + + defaultFaces + { + type omegaWallFunction; + value $internalField; + } + +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/p b/papers/scaleup/generate_scaleup_runs/template/0.orig/p new file mode 100644 index 00000000..b3a295fb --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/p @@ -0,0 +1,39 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + defaultFaces + { + type calculated; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/0.orig/p_rgh b/papers/scaleup/generate_scaleup_runs/template/0.orig/p_rgh new file mode 100644 index 00000000..88ee7d80 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/0.orig/p_rgh @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 101325; + +boundaryField +{ + inlet + { + type fixedFluxPressure; + value $internalField; + } + outlet + { + type prghTotalPressure; + p0 $internalField; + U U.gas; + phi phi.gas; + rho thermo:rho.gas; + value $internalField; + } + defaultFaces + { + type fixedFluxPressure; + value $internalField; + } +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/Allclean b/papers/scaleup/generate_scaleup_runs/template/Allclean new file mode 100755 index 00000000..f55e0ec9 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/Allclean @@ -0,0 +1,18 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Source tutorial clean functions +. $WM_PROJECT_DIR/bin/tools/CleanFunctions + +# Remove surface, features and solution +#rm -rf constant/extendedFeatureEdgeMesh > /dev/null 2>&1 +#rm -f constant/triSurface/*.eMesh > /dev/null 2>&1 +#rm -rf constant/polyMesh > /dev/null 2>&1 +#rm -rf processor* > /dev/null 2>&1 +rm -rf 0 +cleanCase + +#rm *.obj +#rm *.stl + +#------------------------------------------------------------------------------ diff --git a/papers/scaleup/generate_scaleup_runs/template/computeQOI.sh b/papers/scaleup/generate_scaleup_runs/template/computeQOI.sh new file mode 100644 index 00000000..800e45d4 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/computeQOI.sh @@ -0,0 +1,13 @@ +if [ ! -f qoi.txt ]; then + # Reconstruct if needed + source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc + reconstructPar -newTimes + module load conda + conda activate /projects/gas2fuels/conda_env/bird_mixer/ + python read_history.py -cr .. -cn local -df data + python get_qoi.py + conda deactivate +else + echo "WARNING: QOI already computed" +fi + diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/fvModels b/papers/scaleup/generate_scaleup_runs/template/constant/fvModels new file mode 100644 index 00000000..353551df --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/fvModels @@ -0,0 +1,128 @@ +FoamFile +{ + version 9.0; + format ascii; + class dictionary; + location "constant"; + object fvModels; +} + +codedSource +{ + type coded; + selectionMode all; + field U.liquid; + name sourceTime; + + codeInclude + #{ + #include "dynamicMix_util.H" + #}; + + codeOptions + #{ + -I${FOAM_CASE}/constant + #}; + codeAddAlphaRhoSup + #{ + const Time& time = mesh().time(); + const scalarField& V = mesh().V(); + vectorField& Usource = eqn.source(); + const vectorField& C = mesh().C(); + const volScalarField& rhoL = + mesh().lookupObject("thermo:rho.liquid"); + const volScalarField& alphaL = + mesh().lookupObject("alpha.liquid"); + const volVectorField& UL = + mesh().lookupObject("U.liquid"); + double pi=3.141592654; + double source_pt_x=13.807637692813548; + double source_pt_y=1.3807637692813548; + double source_pt_z=12.426873923532193; + double disk_rad=0.9665346384969483; + double disk_area=pi*disk_rad*disk_rad; + double power=7626.034346240216; + double smear_factor=3.0; + const scalar startTime = 1; + if (time.value() > startTime) + { + // Get V1 + double source_sign_factor = 1.0; + double V1 = 0; + double V2 = 0; + double rhoV; + double dist_tol = disk_rad*5; + + double dist_n; + double upV = 0; + double uprhoV = 0; + double upVvol = 0; + double downV = 0; + double downrhoV = 0; + double downVvol = 0; + double dist2; + forAll(C,i) + { + dist2 = (C[i].x()-source_pt_x)*(C[i].x()-source_pt_x); + dist2 += (C[i].y()-source_pt_y)*(C[i].y()-source_pt_y); + dist2 += (C[i].z()-source_pt_z)*(C[i].z()-source_pt_z); + + dist_n = (C[i].x()-source_pt_x); + + if (dist2 < dist_tol*dist_tol && dist_n < -dist_tol/2) { + upVvol += V[i] * alphaL[i]; + upV += V[i] * alphaL[i] * UL[i][0]; + uprhoV += V[i] * alphaL[i] * rhoL[i]; + } + if (dist2 < dist_tol*dist_tol && dist_n > dist_tol/2) { + downVvol += V[i] * alphaL[i]; + downV += V[i] * alphaL[i] * UL[i][0]; + downrhoV += V[i] * alphaL[i] * rhoL[i]; + } + } + + reduce(uprhoV, sumOp()); + reduce(downrhoV, sumOp()); + reduce(upV, sumOp()); + reduce(downV, sumOp()); + reduce(downVvol, sumOp()); + reduce(upVvol, sumOp()); + + downV /= downVvol; + upV /= upVvol; + downrhoV /= downVvol; + uprhoV /= upVvol; + + if (upV <= 0 && downV <= 0) { + source_sign_factor = -1.0; + V1 = std::abs(upV); + rhoV = uprhoV; + } else if (upV >= 0 && downV >= 0) { + source_sign_factor = 1.0; + V1 = std::abs(downV); + rhoV = downrhoV; + } else { + V1 = 0.0; + source_sign_factor = -1.0; + rhoV = uprhoV; + Foam::Info << "[BIRD:DYNMIX WARN] " << "upV = " << upV << " downV = " << downV << " for source at " << source_pt_x << ", " << source_pt_y << ", " << source_pt_z << endl; + } + Foam::Info << "[BIRD:DYNMIX INFO] V1 = " << V1 << endl; + + // Get V2 + V2 = findV2(power, rhoV, disk_area, V1); + + forAll(C,i) + { + double Thrust=0.5*rhoL[i]*(V2*V2 - V1*V1)*disk_area; + double dist2=(C[i].x()-source_pt_x)*(C[i].x()-source_pt_x); + dist2 += (C[i].y()-source_pt_y)*(C[i].y()-source_pt_y); + dist2 += (C[i].z()-source_pt_z)*(C[i].z()-source_pt_z); + double epsilon=pow(V[i],0.33333)*smear_factor; + double sourceterm=alphaL[i]*(Thrust/pow(pi,1.5)/pow(epsilon,3.0))* + exp(-dist2/(epsilon*epsilon)); + Usource[i][0] -= source_sign_factor*sourceterm*V[i]; + } + } + #}; +}; diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/g b/papers/scaleup/generate_scaleup_runs/template/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/g @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/globalVars b/papers/scaleup/generate_scaleup_runs/template/constant/globalVars new file mode 100644 index 00000000..1a0ce724 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/globalVars @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 1.6; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA 11.8966; +liqVol 606.514; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/globalVars_temp b/papers/scaleup/generate_scaleup_runs/template/constant/globalVars_temp new file mode 100644 index 00000000..fcb076a7 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/globalVars_temp @@ -0,0 +1,83 @@ +T0 300; //initial T(K) which stays constant +VVM 0.2; +//****water Liquid properties************** +CpMixLiq 4181; +muMixLiq #calc "2.414e-5 * pow(10,247.8/($T0 - 140.0))"; //viscosity (Pa.s) of water as a function of T(K) +kThermLiq 0.62; // W/m-K +rho0MixLiq 1000; // kg/m^3 +sigmaLiq 0.07; //surface tension N/m +//Wilke-Chang params for diffusion coefficient of a given solute in water (solvent) +WC_psi 2.6; +WC_M 18; // kg/kmol +WC_V_O2 25.6e-3; // m3/kmol molar volume at normal boiling temperature (Treybal 1968) +WC_V_H2 14.3e-3; +WC_V_CO2 34e-3; +WC_V_CO 30.7e-3; +WC_V_N2 31.2e-3; +WC_V_CH4 35e-3; // V_b[cm3/mol]=0.285*V_critical^1.048 (Tyn and Calus; ESTIMATING LIQUID MOLAL VOLUME; Processing, Volume 21, Issue 4, Pages 16 - 17) +//****** diffusion coeff *********** +D_H2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_H2,0.6)"; +D_CO2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO2,0.6)"; +D_CO #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CO,0.6)"; +D_CH4 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_CH4,0.6)"; +D_N2 #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_N2,0.6)"; +//****** Henry coeff *************** +H_O2_298 0.032; +DH_O2 1700; +H_CO2_298 0.83; +DH_CO2 2400; +H_CO_298 0.023; +DH_CO 1300; +H_H2_298 0.019; +DH_H2 500; +H_CH4_298 0.032; +DH_CH4 1900; +H_N2_298 0.015; +DH_N2 1300; +He_H2 #calc "$H_H2_298 * exp($DH_H2 *(1. / $T0 - 1./298.15))"; +He_CO #calc "$H_CO_298 * exp($DH_CO *(1. / $T0 - 1./298.15))"; +He_CO2 #calc "$H_CO2_298 * exp($DH_CO2 *(1. / $T0 - 1./298.15))"; +He_CH4 #calc "$H_CH4_298 * exp($DH_CH4 *(1. / $T0 - 1./298.15))"; +He_N2 #calc "$H_N2_298 * exp($DH_N2 *(1. / $T0 - 1./298.15))"; +//*******inlet gas frac************* +f_H2 0.1; +f_CO2 0.9; +f_N2 0.0; +//*******inlet gas frac************* +inletA ; +liqVol ; +alphaGas 1; +alphaLiq 0; +uGasPhase #calc "$liqVol * $VVM / (60 * $inletA * $alphaGas)"; +//********************************* +LeLiqH2 #calc "$kThermLiq / $rho0MixLiq / $D_H2 / $CpMixLiq"; +LeLiqCO #calc "$kThermLiq / $rho0MixLiq / $D_CO / $CpMixLiq"; +LeLiqCO2 #calc "$kThermLiq / $rho0MixLiq / $D_CO2 / $CpMixLiq"; // = 74 +LeLiqCH4 #calc "$kThermLiq / $rho0MixLiq / $D_CH4 / $CpMixLiq"; +LeLiqN2 #calc "$kThermLiq / $rho0MixLiq / $D_N2 / $CpMixLiq"; +LeLiqMix #calc "$f_CO2*$LeLiqCO2+$f_H2*$LeLiqH2"; +PrMixLiq #calc "$CpMixLiq * $muMixLiq / $kThermLiq"; +//********************************* +kH2 #calc "$D_H2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrH2 #calc "$muMixLiq*$CpMixLiq / $kH2"; + +kCO #calc "$D_CO*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO #calc "$muMixLiq*$CpMixLiq / $kCO"; + +kCO2 #calc "$D_CO2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCO2 #calc "$muMixLiq*$CpMixLiq / $kCO2"; + +kCH4 #calc "$D_CH4*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrCH4 #calc "$muMixLiq*$CpMixLiq / $kCH4"; + +kN2 #calc "$D_N2*$rho0MixLiq*$CpMixLiq*$LeLiqMix"; +PrN2 #calc "$muMixLiq*$CpMixLiq / $kN2"; +//********************************* +l_scale 0.5; +intensity 0.05; +k_inlet_gas #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +k_inlet_liq #calc "1.5 * Foam::pow(($uGasPhase), 2) * Foam::pow($intensity, 2)"; +eps_inlet_gas #calc "pow(0.09,0.75) * Foam::pow($k_inlet_gas, 1.5) / ($l_scale * 0.07)"; +eps_inlet_liq #calc "pow(0.09,0.75) * Foam::pow($k_inlet_liq, 1.5) / ($l_scale * 0.07)"; +omega_inlet_gas #calc "pow(0.09,-0.25) * pow($k_inlet_gas,0.5) / ($l_scale * 0.07)"; +omega_inlet_liq #calc "pow(0.09,-0.25) * pow($k_inlet_liq,0.5) / ($l_scale * 0.07)"; diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.gas b/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.gas @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType laminar; +//simulationType RAS; +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeff on; +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.liquid b/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/momentumTransport.liquid @@ -0,0 +1,27 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object momentumTransport.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//simulationType laminar; +simulationType RAS; + +RAS +{ + model kOmegaSSTSato; + turbulence on; + printCoeffs on; +} + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties @@ -0,0 +1,295 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangePopulationBalanceMultiphaseSystem; + +phases (gas liquid); + +populationBalances (bubbles); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel velocityGroup; + + velocityGroupCoeffs + { + populationBalance bubbles; + + shapeModel spherical; + + sizeGroups + ( + f1 {dSph 1.4e-3; value 0.0;} + f2 {dSph 1.8e-3; value 0.0;} + f3 {dSph 2.2e-3; value 0.0;} + f4 {dSph 2.6e-3; value 0.0;} + f5 {dSph 3e-3; value 1.0;} + f6 {dSph 3.4e-3; value 0.0;} + f7 {dSph 3.8e-3; value 0.0;} + f8 {dSph 4.2e-3; value 0.0;} + f9 {dSph 4.6e-3; value 0.0;} + f10 {dSph 5.0e-3; value 0.0;} + ); + } + + residualAlpha 1e-6; + + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + ( + LehrMilliesMewes{ + efficiency 4.695; + uCrit 0.08; + alphaMax 0.6; + } + ); + + binaryBreakupModels + (); + + breakupModels + ( + Laakkonen { + efficiency 13.83; + daughterSizeDistributionModel Laakkonen; + } + + ); + + driftModels + ( + densityChange{} + ); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_constantd b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_constantd new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_constantd @@ -0,0 +1,261 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangeMultiphaseSystem; + +phases (gas liquid); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 3e-3; + } + residualAlpha 1e-6; + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + (); + + binaryBreakupModels + (); + + breakupModels + (); + + driftModels + (); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_pbe b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_pbe new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/phaseProperties_pbe @@ -0,0 +1,295 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 9 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object phaseProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +type interfaceCompositionPhaseChangePopulationBalanceMultiphaseSystem; + +phases (gas liquid); + +populationBalances (bubbles); + +gas +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel velocityGroup; + + velocityGroupCoeffs + { + populationBalance bubbles; + + shapeModel spherical; + + sizeGroups + ( + f1 {dSph 1.4e-3; value 0.0;} + f2 {dSph 1.8e-3; value 0.0;} + f3 {dSph 2.2e-3; value 0.0;} + f4 {dSph 2.6e-3; value 0.0;} + f5 {dSph 3e-3; value 1.0;} + f6 {dSph 3.4e-3; value 0.0;} + f7 {dSph 3.8e-3; value 0.0;} + f8 {dSph 4.2e-3; value 0.0;} + f9 {dSph 4.6e-3; value 0.0;} + f10 {dSph 5.0e-3; value 0.0;} + ); + } + + residualAlpha 1e-6; + + Sc 0.7; +} + +liquid +{ + type multiComponentPhaseModel;//pureIsothermalPhaseModel; + + diameterModel constant; + + constantCoeffs + { + d 1e-4; + } + Sc #codeStream + { + code + #{ + os << ($LeLiqMix * $CpMixLiq * $muMixLiq / $kThermLiq); + #}; + }; + + residualAlpha 1e-6; +} + +populationBalanceCoeffs +{ + bubbles + { + continuousPhase liquid; + + coalescenceModels + ( + LehrMilliesMewes{ + efficiency 4.695; + uCrit 0.08; + alphaMax 0.6; + } + ); + + binaryBreakupModels + (); + + breakupModels + ( + Laakkonen { + efficiency 13.83; + daughterSizeDistributionModel Laakkonen; + } + + ); + + driftModels + ( + densityChange{} + ); + + nucleationModels + (); + } +} + +blending +{ + default + { + type linear; + minFullyContinuousAlpha.gas 0.7; + minPartlyContinuousAlpha.gas 0.3; + minFullyContinuousAlpha.liquid 0.7; + minPartlyContinuousAlpha.liquid 0.3; + } + heatTransfer + { + type linear; + minFullyContinuousAlpha.gas 1; + minPartlyContinuousAlpha.gas 0; + minFullyContinuousAlpha.liquid 1; + minPartlyContinuousAlpha.liquid 0; + } + massTransfer + { + $heatTransfer; + } +} + +surfaceTension +( + (gas and liquid) + { + type constant; + sigma $sigmaLiq; + } +); + +interfaceCompression +(); + +aspectRatio +( + (gas in liquid) + { + type Wellek; + } +); + + +drag +( + (gas in liquid) + { + type Grace; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type IshiiZuber; + residualRe 1e-3; + swarmCorrection + { + type none; + } + } +); + +virtualMass +( + (gas in liquid) + { + type constantCoefficient; + Cvm 0.5; + } +); + +// heatTransfer +// (); + +heatTransfer.gas +( + (gas in liquid) + { + type spherical; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type RanzMarshall; + residualAlpha 1e-4; + } +); + +heatTransfer.liquid +( + (gas in liquid) + { + type RanzMarshall; + residualAlpha 1e-4; + } + + (liquid in gas) + { + type spherical; + residualAlpha 1e-4; + } +); + +interfaceComposition.gas +(); + +interfaceComposition.liquid +( + (liquid and gas) + { + type Henry; + species ( CO2 H2 ); + k ( $He_CO2 $He_H2 ); + Le $LeLiqMix; + } +); + +diffusiveMassTransfer.gas +(); + +diffusiveMassTransfer.liquid +( + (gas in liquid) + { + type Higbie; // Need to install the model available at https://github.com/NREL/BioReactorDesign + //type Frossling; + Le $LeLiqMix; + } + + (liquid in gas) + { + type spherical; + Le 1.0; //not used for spherical + } +); + +phaseTransfer +(); + +lift +( + (gas in liquid) + { + type wallDamped; + + wallDamping + { + type cosine; + Cd 3.0; + } + + lift + { + type Tomiyama; + + swarmCorrection + { + type none; + } + } + } + +); + +wallLubrication +( + (gas in liquid) + { + type Antal; + Cw1 -0.01; + Cw2 0.05; + } +); + +turbulentDispersion +( + (gas in liquid) + { + type Burns; + sigma 0.9; + } +); + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.gas b/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..11b1c4b9 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.gas @@ -0,0 +1,142 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.gas; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + + +species +( + H2 + CO2 + N2 +); + +defaultSpecie N2; + +CO2 +{ + specie + { + molWeight 44.00995; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.85746029 0.00441437026 -2.21481404e-06 5.23490188e-10 -4.72084164e-14 -48759.166 2.27163806 ); + lowCpCoeffs ( 2.35677352 0.00898459677 -7.12356269e-06 2.45919022e-09 -1.43699548e-13 -48371.9697 9.90105222 ); + } + transport + { + As 1.572e-06; + Ts 240; + } + elements + { + C 1; + O 2; + } +} + +water +{ + specie + { + molWeight 18.01534; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.03399249 0.00217691804 -1.64072518e-07 -9.7041987e-11 1.68200992e-14 -30004.2971 4.9667701 ); + lowCpCoeffs ( 4.19864056 -0.0020364341 6.52040211e-06 -5.48797062e-09 1.77197817e-12 -30293.7267 -0.849032208 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + H 2; + O 1; + } +} + +N2 +{ + specie + { + molWeight 28.0134; + } + thermodynamics + { + Tlow 250; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 2.92664 0.0014879768 -5.68476e-07 1.0097038e-10 -6.753351e-15 -922.7977 5.980528 ); + lowCpCoeffs ( 3.298677 0.0014082404 -3.963222e-06 5.641515e-09 -2.444854e-12 -1020.8999 3.950372 ); + } + transport + { + As 1.512e-06; + Ts 120; + } + elements + { + N 2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + thermodynamics + { + Tlow 200; + Thigh 3500; + Tcommon 1000; + highCpCoeffs ( 3.3372792 -4.94024731e-05 4.99456778e-07 -1.79566394e-10 2.00255376e-14 -950.158922 -3.20502331 ); + lowCpCoeffs ( 2.34433112 0.00798052075 -1.9478151e-05 2.01572094e-08 -7.37611761e-12 -917.935173 0.683010238 ); + } + transport + { + As 6.362e-07; + Ts 72; + } + elements + { + H 2; + } +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.liquid b/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..d324ec51 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/constant/thermophysicalProperties.liquid @@ -0,0 +1,108 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties.liquid; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "$FOAM_CASE/constant/globalVars" + +thermoType +{ + type heRhoThermo; + mixture multiComponentMixture; + transport const; + thermo hConst; + equationOfState rhoConst;//rPolynomial; + specie specie; + energy sensibleInternalEnergy; + //energy sensibleEnthalpy; +} + +species +( + CO2 + water + H2 +); + +inertSpecie water; + +water +{ + specie + { + molWeight 18.0153; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrMixLiq; + } +} + +CO2 +{ + specie + { + molWeight 44.00995; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07; + } + transport + { + mu $muMixLiq; + Pr $PrCO2; + } +} + +H2 +{ + specie + { + molWeight 2.01594; + } + equationOfState + { + rho $rho0MixLiq; + } + thermodynamics + { + Cp $CpMixLiq; + Hf -1.5879e+07;//-9402451; + } + transport + { + mu $muMixLiq; + Pr $PrH2; + } +} + + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/get_qoi.py b/papers/scaleup/generate_scaleup_runs/template/get_qoi.py new file mode 100644 index 00000000..6c06e054 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/get_qoi.py @@ -0,0 +1,227 @@ +import json +import os +import pickle as pkl + +import matplotlib as mpl +import numpy as np +from prettyPlot.plotting import * +from scipy.optimize import curve_fit + + +def get_sim_folds(path): + folds = os.listdir(path) + sim_folds = [] + for fold in folds: + if fold.startswith("loop"): + sim_folds.append(fold) + return sim_folds + + +def func(t, cstar, kla): + t = t + t0 = 0 + c0 = 0 + return (cstar - c0) * (1 - np.exp(-kla * (t - t0))) + c0 + + +def get_vl(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("liqVol"): + vol = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read liqVol = {vol}m3") + return vol + + +def get_vvm(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("VVM"): + vvm = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read VVM = {vvm} [-]") + return vvm + + +def get_As(verb=False): + filename = os.path.join("constant", "globalVars") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if line.startswith("inletA"): + As = float(line.split()[-1][:-1]) + break + if verb: + print(f"Read As = {As}m2") + return As + + +def get_pmix(verb=False): + with open("system/mixers.json", "r+") as f: + data = json.load(f) + mixer_list = data["mixers"] + pmix = 0 + for mix in mixer_list: + pmix += mix["power"] / 1000 + if verb: + print(f"Read Mixing power = {pmix}kW") + return pmix + + +def get_lh(verb=False): + filename = os.path.join("system", "setFieldsDict") + with open(filename, "r+") as f: + lines = f.readlines() + for line in lines: + if "box (-1.0 -1.0 -1.0)" in line: + height = float(line.split("(")[2].split()[1]) + break + if verb: + print(f"Read Height = {height}m") + return height + + +def get_pinj(vvm, Vl, As, lh): + rhog = 0.593333 # kg /m3 + Vg = Vl * vvm / (60 * As * 1) # m/s + Ptank = 101325 # Pa + # Ptank = 0 # Pa + rhoL = 1000 # kg / m3 + Pl = 101325 + rhoL * 9.8 * lh # Pa + # W + P1 = rhog * As * Vg**3 + # W + P2 = (Pl - Ptank) * As * Vg + # kg /s + MF = rhog * Vg * As + # kwh / kg + e_m = (P1 + P2) / (3600 * 1000 * MF) + + # returns kW + return (P1 + P2) * 1e-3 + + +def get_qoi(kla_co2, cs_co2, kla_h2, cs_h2, verb=False): + vvm = get_vvm(verb) + As = get_As(verb) + V_l = get_vl(verb) + liqh = get_lh(verb) + P_inj = get_pinj(vvm, V_l, As, liqh) + P_mix = get_pmix(verb) + + qoi_kla_co2 = kla_co2 * cs_co2 * V_l * 0.04401 + qoi_kla_h2 = kla_h2 * cs_h2 * V_l * 0.002016 + + qoi_co2 = qoi_kla_co2 / (P_mix / 3600 + P_inj / 3600) + qoi_h2 = qoi_kla_h2 / (P_mix / 3600 + P_inj / 3600) + return ( + qoi_co2 * qoi_h2, + qoi_kla_co2 * qoi_kla_h2, + qoi_co2 + qoi_h2, + qoi_kla_co2 + qoi_kla_h2, + ) + + +def get_qoi_uq(kla_co2, cs_co2, kla_h2, cs_h2): + qoi = [] + qoi_kla = [] + qoi_sum = [] + qoi_sum_kla = [] + for i in range(len(kla_co2)): + if i == 0: + verb = True + else: + verb = False + qoi_tmp, qoi_kla_tmp, qoi_sum_tmp, qoi_sum_kla_tmp = get_qoi( + kla_co2[i], cs_co2[i], kla_h2[i], cs_h2[i], verb + ) + qoi.append(qoi_tmp) + qoi_kla.append(qoi_kla_tmp) + qoi_sum.append(qoi_sum_tmp) + qoi_sum_kla.append(qoi_sum_kla_tmp) + qoi = np.array(qoi) + qoi_kla = np.array(qoi_kla) + qoi_sum = np.array(qoi_sum) + qoi_sum_kla = np.array(qoi_sum_kla) + return ( + np.mean(qoi), + np.std(qoi), + np.mean(qoi_kla), + np.std(qoi_kla), + np.mean(qoi_sum), + np.std(qoi_sum), + np.mean(qoi_sum_kla), + np.std(qoi_sum_kla), + ) + + +os.makedirs("Figures", exist_ok=True) + +dataFolder = "data" +fold = "local" + +nuq = 100 +mean_cstar_co2 = np.random.uniform(7.68, 8.22, nuq) +mean_cstar_h2 = np.random.uniform(0.516, 0.548, nuq) + + +tmp_cs_h2 = [] +tmp_cs_co2 = [] +tmp_kla_h2 = [] +tmp_kla_co2 = [] +cs_co2 = mean_cstar_co2 +cs_h2 = mean_cstar_h2 + +a = np.load(os.path.join(dataFolder, fold, "conv.npz")) +endindex = -1 +if ( + "c_h2" in a + and "c_co2" in a + and len(a["time"][:endindex] > 0) + and (a["time"][:endindex][-1] > 85) +): + for i in range(nuq): + fitparamsH2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_h2"][:endindex]), + bounds=[(cs_h2[i] - 1e-6, 0), (cs_h2[i] + 1e-6, 1)], + ) + fitparamsCO2, _ = curve_fit( + func, + np.array(a["time"][:endindex]), + np.array(a["c_co2"][:endindex]), + bounds=[(cs_co2[i] - 1e-6, 0), (cs_co2[i] + 1e-6, 1)], + ) + tmp_kla_co2.append(fitparamsCO2[1]) + tmp_kla_h2.append(fitparamsH2[1]) + tmp_cs_h2.append(cs_h2[i]) + tmp_cs_co2.append(cs_co2[i]) + +( + qoi_m, + qoi_s, + qoi_kla_m, + qoi_kla_s, + qoi_sum_m, + qoi_sum_s, + qoi_sum_kla_m, + qoi_sum_kla_s, +) = get_qoi_uq(tmp_kla_co2, tmp_cs_co2, tmp_kla_h2, tmp_cs_h2) + + +with open("qoi.txt", "w+") as f: + f.write(f"{qoi_m},{qoi_s}\n") +with open("qoi_kla.txt", "w+") as f: + f.write(f"{qoi_kla_m},{qoi_kla_s}\n") +with open("qoi_sum.txt", "w+") as f: + f.write(f"{qoi_sum_m},{qoi_sum_s}\n") +with open("qoi_sum_kla.txt", "w+") as f: + f.write(f"{qoi_sum_kla_m},{qoi_sum_kla_s}\n") diff --git a/papers/scaleup/generate_scaleup_runs/template/presteps.sh b/papers/scaleup/generate_scaleup_runs/template/presteps.sh new file mode 100644 index 00000000..d47dfe51 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/presteps.sh @@ -0,0 +1,75 @@ +# Clean case +module load conda +#conda activate /projects/gas2fuels/conda_env/bird_wf +conda activate /projects/gas2fuels/conda_env/bird_mixer +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +./Allclean + +BIRD_HOME=`python -c "import bird; print(bird.BIRD_DIR)"` + +echo PRESTEP 1 +# Generate blockmeshDict +python ${BIRD_HOME}/../applications/write_block_rect_mesh.py -i system/mesh.json -o system + +# Generate boundary stl +python ${BIRD_HOME}/../applications/write_stl_patch.py -i system/inlets_outlets.json + +# Generate mixers +python ${BIRD_HOME}/../applications/write_dynMix_fvModels.py -fs -i system/mixers.json -o constant + +echo PRESTEP 2 +# Mesh gen +blockMesh -dict system/blockMeshDict + +mkdir tmp + +# Inlet BC +surfaceToPatch -tol 1e-3 inlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/inlets\.stl/inlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + +# Outlet BC +surfaceToPatch -tol 1e-3 outlets.stl +export newmeshdir=$(foamListTimes -latestTime) +rm -rf constant/polyMesh/ +cp -r $newmeshdir/polyMesh ./constant +rm -rf $newmeshdir +cp constant/polyMesh/boundary tmp +sed -i -e 's/outlets\.stl/outlet/g' tmp/boundary +cat tmp/boundary > constant/polyMesh/boundary + + +rm -r tmp + +# Scale +transformPoints "scale=(2.7615275385627096 2.7615275385627096 2.7615275385627096)" + + +# setup IC +cp -r 0.orig 0 +setFields + +# Setup mass flow rate +# Get inlet area +postProcess -func 'patchIntegrate(patch="inlet", field="alpha.gas")' +postProcess -func writeCellVolumes +writeMeshObj + +echo PRESTEP 3 +python writeGlobalVars.py +cp constant/phaseProperties_constantd constant/phaseProperties + +conda deactivate + +if [ -f qoi.txt ]; then + rm qoi.txt +fi +if [ -f data/local/conv.npz ]; then + rm data/local/conv.npz +fi + diff --git a/papers/scaleup/generate_scaleup_runs/template/read_history.py b/papers/scaleup/generate_scaleup_runs/template/read_history.py new file mode 100644 index 00000000..0ca46649 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/read_history.py @@ -0,0 +1,100 @@ +import argparse +import os +import sys + +import numpy as np +from prettyPlot.plotting import plt, pretty_labels + +from bird.postprocess.post_quantities import * +from bird.utilities.ofio import * + +parser = argparse.ArgumentParser(description="Convergence of GH") +parser.add_argument( + "-cn", + "--case_name", + type=str, + metavar="", + required=True, + help="Case name", +) +parser.add_argument( + "-df", + "--data_folder", + type=str, + metavar="", + required=False, + help="data folder name", + default="data", +) + +args, unknown = parser.parse_known_args() + + +case_root = "." # "../" +case_name = args.case_name # "12_hole_sparger_snappyRefine_700rpm_opt_coeff" +case_folder = "." +dataFolder = args.data_folder + +if os.path.isfile(os.path.join(dataFolder, case_name, "conv.npz")): + sys.exit("WARNING: History already created, Skipping") + +time_float_sorted, time_str_sorted = get_case_times( + case_folder, remove_zero=True +) +cell_centers, _ = read_cell_centers(case_folder) +nCells = len(cell_centers) + + +co2_history = np.zeros(len(time_str_sorted)) +c_co2_history = np.zeros(len(time_str_sorted)) +h2_history = np.zeros(len(time_str_sorted)) +c_h2_history = np.zeros(len(time_str_sorted)) +gh_history = np.zeros(len(time_str_sorted)) +liqvol_history = np.zeros(len(time_str_sorted)) +print(f"case_folder = {case_folder}") +field_dict = {} +for itime, time in enumerate(time_float_sorted): + time_folder = time_str_sorted[itime] + print(f"\tTime : {time_folder}") + _, field_dict = read_cell_volumes(case_folder) + gh_history[itime], field_dict = compute_gas_holdup( + case_folder, + time_str_sorted[itime], + field_dict=field_dict, + ) + co2_history[itime], field_dict = compute_ave_y_liq( + case_folder, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + h2_history[itime], field_dict = compute_ave_y_liq( + case_folder, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + c_co2_history[itime], field_dict = compute_ave_conc_liq( + case_folder, + time_str_sorted[itime], + species_name="CO2", + field_dict=field_dict, + ) + c_h2_history[itime], field_dict = compute_ave_conc_liq( + case_folder, + time_str_sorted[itime], + species_name="H2", + field_dict=field_dict, + ) + +os.makedirs(dataFolder, exist_ok=True) +os.makedirs(os.path.join(dataFolder, case_name), exist_ok=True) +np.savez( + os.path.join(dataFolder, case_name, "conv.npz"), + time=np.array(time_float_sorted), + gh=gh_history, + co2=co2_history, + h2=h2_history, + c_h2=c_h2_history, + c_co2=c_co2_history, +) diff --git a/papers/scaleup/generate_scaleup_runs/template/run.sh b/papers/scaleup/generate_scaleup_runs/template/run.sh new file mode 100644 index 00000000..99da4760 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/run.sh @@ -0,0 +1,5 @@ +birdmultiphaseEulerFoam + + + + diff --git a/papers/scaleup/generate_scaleup_runs/template/script b/papers/scaleup/generate_scaleup_runs/template/script new file mode 100755 index 00000000..efe675ff --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/script @@ -0,0 +1,14 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=07:59:00 +#SBATCH --account=co2snow + +bash presteps.sh +source /projects/gas2fuels/ofoam_cray_mpich/OpenFOAM-dev/etc/bashrc +decomposePar -fileHandler collated +srun -n 16 birdmultiphaseEulerFoam -parallel -fileHandler collated +reconstructPar -newTimes diff --git a/papers/scaleup/generate_scaleup_runs/template/script_post b/papers/scaleup/generate_scaleup_runs/template/script_post new file mode 100755 index 00000000..aabbc33e --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/script_post @@ -0,0 +1,10 @@ +#!/bin/bash +#SBATCH --qos=high +#SBATCH --job-name=val2 +##SBATCH --partition=debug +#SBATCH --nodes=1 +#SBATCH --ntasks-per-node=16 +#SBATCH --time=00:59:00 +#SBATCH --account=co2snow + +bash computeQOI.sh diff --git a/papers/scaleup/generate_scaleup_runs/template/system/blockMeshDict b/papers/scaleup/generate_scaleup_runs/template/system/blockMeshDict new file mode 100644 index 00000000..1183d262 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/blockMeshDict @@ -0,0 +1,746 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1.0; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +vertices +( +( 0.0 0.0 0.0) +( 1.0 0.0 0.0) +( 2.0 0.0 0.0) +( 3.0 0.0 0.0) +( 4.0 0.0 0.0) +( 5.0 0.0 0.0) +( 6.0 0.0 0.0) +( 7.0 0.0 0.0) +( 8.0 0.0 0.0) +( 9.0 0.0 0.0) +( 10.0 0.0 0.0) +( 0.0 1.0 0.0) +( 1.0 1.0 0.0) +( 2.0 1.0 0.0) +( 3.0 1.0 0.0) +( 4.0 1.0 0.0) +( 5.0 1.0 0.0) +( 6.0 1.0 0.0) +( 7.0 1.0 0.0) +( 8.0 1.0 0.0) +( 9.0 1.0 0.0) +( 10.0 1.0 0.0) +( 0.0 2.0 0.0) +( 1.0 2.0 0.0) +( 2.0 2.0 0.0) +( 3.0 2.0 0.0) +( 4.0 2.0 0.0) +( 5.0 2.0 0.0) +( 6.0 2.0 0.0) +( 7.0 2.0 0.0) +( 8.0 2.0 0.0) +( 9.0 2.0 0.0) +( 10.0 2.0 0.0) +( 0.0 3.0 0.0) +( 1.0 3.0 0.0) +( 2.0 3.0 0.0) +( 3.0 3.0 0.0) +( 4.0 3.0 0.0) +( 5.0 3.0 0.0) +( 6.0 3.0 0.0) +( 7.0 3.0 0.0) +( 8.0 3.0 0.0) +( 9.0 3.0 0.0) +( 10.0 3.0 0.0) +( 0.0 4.0 0.0) +( 1.0 4.0 0.0) +( 2.0 4.0 0.0) +( 3.0 4.0 0.0) +( 4.0 4.0 0.0) +( 5.0 4.0 0.0) +( 6.0 4.0 0.0) +( 7.0 4.0 0.0) +( 8.0 4.0 0.0) +( 9.0 4.0 0.0) +( 10.0 4.0 0.0) +( 0.0 5.0 0.0) +( 1.0 5.0 0.0) +( 2.0 5.0 0.0) +( 3.0 5.0 0.0) +( 4.0 5.0 0.0) +( 5.0 5.0 0.0) +( 6.0 5.0 0.0) +( 7.0 5.0 0.0) +( 8.0 5.0 0.0) +( 9.0 5.0 0.0) +( 10.0 5.0 0.0) +( 0.0 6.0 0.0) +( 1.0 6.0 0.0) +( 2.0 6.0 0.0) +( 3.0 6.0 0.0) +( 4.0 6.0 0.0) +( 5.0 6.0 0.0) +( 6.0 6.0 0.0) +( 7.0 6.0 0.0) +( 8.0 6.0 0.0) +( 9.0 6.0 0.0) +( 10.0 6.0 0.0) +( 0.0 7.0 0.0) +( 1.0 7.0 0.0) +( 2.0 7.0 0.0) +( 3.0 7.0 0.0) +( 4.0 7.0 0.0) +( 5.0 7.0 0.0) +( 6.0 7.0 0.0) +( 7.0 7.0 0.0) +( 8.0 7.0 0.0) +( 9.0 7.0 0.0) +( 10.0 7.0 0.0) +( 0.0 0.0 1.0) +( 1.0 0.0 1.0) +( 2.0 0.0 1.0) +( 3.0 0.0 1.0) +( 4.0 0.0 1.0) +( 5.0 0.0 1.0) +( 6.0 0.0 1.0) +( 7.0 0.0 1.0) +( 8.0 0.0 1.0) +( 9.0 0.0 1.0) +( 10.0 0.0 1.0) +( 0.0 1.0 1.0) +( 1.0 1.0 1.0) +( 2.0 1.0 1.0) +( 3.0 1.0 1.0) +( 4.0 1.0 1.0) +( 5.0 1.0 1.0) +( 6.0 1.0 1.0) +( 7.0 1.0 1.0) +( 8.0 1.0 1.0) +( 9.0 1.0 1.0) +( 10.0 1.0 1.0) +( 0.0 2.0 1.0) +( 1.0 2.0 1.0) +( 2.0 2.0 1.0) +( 3.0 2.0 1.0) +( 4.0 2.0 1.0) +( 5.0 2.0 1.0) +( 6.0 2.0 1.0) +( 7.0 2.0 1.0) +( 8.0 2.0 1.0) +( 9.0 2.0 1.0) +( 10.0 2.0 1.0) +( 0.0 3.0 1.0) +( 1.0 3.0 1.0) +( 2.0 3.0 1.0) +( 3.0 3.0 1.0) +( 4.0 3.0 1.0) +( 5.0 3.0 1.0) +( 6.0 3.0 1.0) +( 7.0 3.0 1.0) +( 8.0 3.0 1.0) +( 9.0 3.0 1.0) +( 10.0 3.0 1.0) +( 0.0 4.0 1.0) +( 1.0 4.0 1.0) +( 2.0 4.0 1.0) +( 3.0 4.0 1.0) +( 4.0 4.0 1.0) +( 5.0 4.0 1.0) +( 6.0 4.0 1.0) +( 7.0 4.0 1.0) +( 8.0 4.0 1.0) +( 9.0 4.0 1.0) +( 10.0 4.0 1.0) +( 0.0 5.0 1.0) +( 1.0 5.0 1.0) +( 2.0 5.0 1.0) +( 3.0 5.0 1.0) +( 4.0 5.0 1.0) +( 5.0 5.0 1.0) +( 6.0 5.0 1.0) +( 7.0 5.0 1.0) +( 8.0 5.0 1.0) +( 9.0 5.0 1.0) +( 10.0 5.0 1.0) +( 0.0 6.0 1.0) +( 1.0 6.0 1.0) +( 2.0 6.0 1.0) +( 3.0 6.0 1.0) +( 4.0 6.0 1.0) +( 5.0 6.0 1.0) +( 6.0 6.0 1.0) +( 7.0 6.0 1.0) +( 8.0 6.0 1.0) +( 9.0 6.0 1.0) +( 10.0 6.0 1.0) +( 0.0 7.0 1.0) +( 1.0 7.0 1.0) +( 2.0 7.0 1.0) +( 3.0 7.0 1.0) +( 4.0 7.0 1.0) +( 5.0 7.0 1.0) +( 6.0 7.0 1.0) +( 7.0 7.0 1.0) +( 8.0 7.0 1.0) +( 9.0 7.0 1.0) +( 10.0 7.0 1.0) +( 0.0 0.0 2.0) +( 1.0 0.0 2.0) +( 2.0 0.0 2.0) +( 3.0 0.0 2.0) +( 4.0 0.0 2.0) +( 5.0 0.0 2.0) +( 6.0 0.0 2.0) +( 7.0 0.0 2.0) +( 8.0 0.0 2.0) +( 9.0 0.0 2.0) +( 10.0 0.0 2.0) +( 0.0 1.0 2.0) +( 1.0 1.0 2.0) +( 2.0 1.0 2.0) +( 3.0 1.0 2.0) +( 4.0 1.0 2.0) +( 5.0 1.0 2.0) +( 6.0 1.0 2.0) +( 7.0 1.0 2.0) +( 8.0 1.0 2.0) +( 9.0 1.0 2.0) +( 10.0 1.0 2.0) +( 0.0 2.0 2.0) +( 1.0 2.0 2.0) +( 2.0 2.0 2.0) +( 3.0 2.0 2.0) +( 4.0 2.0 2.0) +( 5.0 2.0 2.0) +( 6.0 2.0 2.0) +( 7.0 2.0 2.0) +( 8.0 2.0 2.0) +( 9.0 2.0 2.0) +( 10.0 2.0 2.0) +( 0.0 3.0 2.0) +( 1.0 3.0 2.0) +( 2.0 3.0 2.0) +( 3.0 3.0 2.0) +( 4.0 3.0 2.0) +( 5.0 3.0 2.0) +( 6.0 3.0 2.0) +( 7.0 3.0 2.0) +( 8.0 3.0 2.0) +( 9.0 3.0 2.0) +( 10.0 3.0 2.0) +( 0.0 4.0 2.0) +( 1.0 4.0 2.0) +( 2.0 4.0 2.0) +( 3.0 4.0 2.0) +( 4.0 4.0 2.0) +( 5.0 4.0 2.0) +( 6.0 4.0 2.0) +( 7.0 4.0 2.0) +( 8.0 4.0 2.0) +( 9.0 4.0 2.0) +( 10.0 4.0 2.0) +( 0.0 5.0 2.0) +( 1.0 5.0 2.0) +( 2.0 5.0 2.0) +( 3.0 5.0 2.0) +( 4.0 5.0 2.0) +( 5.0 5.0 2.0) +( 6.0 5.0 2.0) +( 7.0 5.0 2.0) +( 8.0 5.0 2.0) +( 9.0 5.0 2.0) +( 10.0 5.0 2.0) +( 0.0 6.0 2.0) +( 1.0 6.0 2.0) +( 2.0 6.0 2.0) +( 3.0 6.0 2.0) +( 4.0 6.0 2.0) +( 5.0 6.0 2.0) +( 6.0 6.0 2.0) +( 7.0 6.0 2.0) +( 8.0 6.0 2.0) +( 9.0 6.0 2.0) +( 10.0 6.0 2.0) +( 0.0 7.0 2.0) +( 1.0 7.0 2.0) +( 2.0 7.0 2.0) +( 3.0 7.0 2.0) +( 4.0 7.0 2.0) +( 5.0 7.0 2.0) +( 6.0 7.0 2.0) +( 7.0 7.0 2.0) +( 8.0 7.0 2.0) +( 9.0 7.0 2.0) +( 10.0 7.0 2.0) +( 0.0 0.0 3.0) +( 1.0 0.0 3.0) +( 2.0 0.0 3.0) +( 3.0 0.0 3.0) +( 4.0 0.0 3.0) +( 5.0 0.0 3.0) +( 6.0 0.0 3.0) +( 7.0 0.0 3.0) +( 8.0 0.0 3.0) +( 9.0 0.0 3.0) +( 10.0 0.0 3.0) +( 0.0 1.0 3.0) +( 1.0 1.0 3.0) +( 2.0 1.0 3.0) +( 3.0 1.0 3.0) +( 4.0 1.0 3.0) +( 5.0 1.0 3.0) +( 6.0 1.0 3.0) +( 7.0 1.0 3.0) +( 8.0 1.0 3.0) +( 9.0 1.0 3.0) +( 10.0 1.0 3.0) +( 0.0 2.0 3.0) +( 1.0 2.0 3.0) +( 2.0 2.0 3.0) +( 3.0 2.0 3.0) +( 4.0 2.0 3.0) +( 5.0 2.0 3.0) +( 6.0 2.0 3.0) +( 7.0 2.0 3.0) +( 8.0 2.0 3.0) +( 9.0 2.0 3.0) +( 10.0 2.0 3.0) +( 0.0 3.0 3.0) +( 1.0 3.0 3.0) +( 2.0 3.0 3.0) +( 3.0 3.0 3.0) +( 4.0 3.0 3.0) +( 5.0 3.0 3.0) +( 6.0 3.0 3.0) +( 7.0 3.0 3.0) +( 8.0 3.0 3.0) +( 9.0 3.0 3.0) +( 10.0 3.0 3.0) +( 0.0 4.0 3.0) +( 1.0 4.0 3.0) +( 2.0 4.0 3.0) +( 3.0 4.0 3.0) +( 4.0 4.0 3.0) +( 5.0 4.0 3.0) +( 6.0 4.0 3.0) +( 7.0 4.0 3.0) +( 8.0 4.0 3.0) +( 9.0 4.0 3.0) +( 10.0 4.0 3.0) +( 0.0 5.0 3.0) +( 1.0 5.0 3.0) +( 2.0 5.0 3.0) +( 3.0 5.0 3.0) +( 4.0 5.0 3.0) +( 5.0 5.0 3.0) +( 6.0 5.0 3.0) +( 7.0 5.0 3.0) +( 8.0 5.0 3.0) +( 9.0 5.0 3.0) +( 10.0 5.0 3.0) +( 0.0 6.0 3.0) +( 1.0 6.0 3.0) +( 2.0 6.0 3.0) +( 3.0 6.0 3.0) +( 4.0 6.0 3.0) +( 5.0 6.0 3.0) +( 6.0 6.0 3.0) +( 7.0 6.0 3.0) +( 8.0 6.0 3.0) +( 9.0 6.0 3.0) +( 10.0 6.0 3.0) +( 0.0 7.0 3.0) +( 1.0 7.0 3.0) +( 2.0 7.0 3.0) +( 3.0 7.0 3.0) +( 4.0 7.0 3.0) +( 5.0 7.0 3.0) +( 6.0 7.0 3.0) +( 7.0 7.0 3.0) +( 8.0 7.0 3.0) +( 9.0 7.0 3.0) +( 10.0 7.0 3.0) +( 0.0 0.0 4.0) +( 1.0 0.0 4.0) +( 2.0 0.0 4.0) +( 3.0 0.0 4.0) +( 4.0 0.0 4.0) +( 5.0 0.0 4.0) +( 6.0 0.0 4.0) +( 7.0 0.0 4.0) +( 8.0 0.0 4.0) +( 9.0 0.0 4.0) +( 10.0 0.0 4.0) +( 0.0 1.0 4.0) +( 1.0 1.0 4.0) +( 2.0 1.0 4.0) +( 3.0 1.0 4.0) +( 4.0 1.0 4.0) +( 5.0 1.0 4.0) +( 6.0 1.0 4.0) +( 7.0 1.0 4.0) +( 8.0 1.0 4.0) +( 9.0 1.0 4.0) +( 10.0 1.0 4.0) +( 0.0 2.0 4.0) +( 1.0 2.0 4.0) +( 2.0 2.0 4.0) +( 3.0 2.0 4.0) +( 4.0 2.0 4.0) +( 5.0 2.0 4.0) +( 6.0 2.0 4.0) +( 7.0 2.0 4.0) +( 8.0 2.0 4.0) +( 9.0 2.0 4.0) +( 10.0 2.0 4.0) +( 0.0 3.0 4.0) +( 1.0 3.0 4.0) +( 2.0 3.0 4.0) +( 3.0 3.0 4.0) +( 4.0 3.0 4.0) +( 5.0 3.0 4.0) +( 6.0 3.0 4.0) +( 7.0 3.0 4.0) +( 8.0 3.0 4.0) +( 9.0 3.0 4.0) +( 10.0 3.0 4.0) +( 0.0 4.0 4.0) +( 1.0 4.0 4.0) +( 2.0 4.0 4.0) +( 3.0 4.0 4.0) +( 4.0 4.0 4.0) +( 5.0 4.0 4.0) +( 6.0 4.0 4.0) +( 7.0 4.0 4.0) +( 8.0 4.0 4.0) +( 9.0 4.0 4.0) +( 10.0 4.0 4.0) +( 0.0 5.0 4.0) +( 1.0 5.0 4.0) +( 2.0 5.0 4.0) +( 3.0 5.0 4.0) +( 4.0 5.0 4.0) +( 5.0 5.0 4.0) +( 6.0 5.0 4.0) +( 7.0 5.0 4.0) +( 8.0 5.0 4.0) +( 9.0 5.0 4.0) +( 10.0 5.0 4.0) +( 0.0 6.0 4.0) +( 1.0 6.0 4.0) +( 2.0 6.0 4.0) +( 3.0 6.0 4.0) +( 4.0 6.0 4.0) +( 5.0 6.0 4.0) +( 6.0 6.0 4.0) +( 7.0 6.0 4.0) +( 8.0 6.0 4.0) +( 9.0 6.0 4.0) +( 10.0 6.0 4.0) +( 0.0 7.0 4.0) +( 1.0 7.0 4.0) +( 2.0 7.0 4.0) +( 3.0 7.0 4.0) +( 4.0 7.0 4.0) +( 5.0 7.0 4.0) +( 6.0 7.0 4.0) +( 7.0 7.0 4.0) +( 8.0 7.0 4.0) +( 9.0 7.0 4.0) +( 10.0 7.0 4.0) +( 0.0 0.0 5.0) +( 1.0 0.0 5.0) +( 2.0 0.0 5.0) +( 3.0 0.0 5.0) +( 4.0 0.0 5.0) +( 5.0 0.0 5.0) +( 6.0 0.0 5.0) +( 7.0 0.0 5.0) +( 8.0 0.0 5.0) +( 9.0 0.0 5.0) +( 10.0 0.0 5.0) +( 0.0 1.0 5.0) +( 1.0 1.0 5.0) +( 2.0 1.0 5.0) +( 3.0 1.0 5.0) +( 4.0 1.0 5.0) +( 5.0 1.0 5.0) +( 6.0 1.0 5.0) +( 7.0 1.0 5.0) +( 8.0 1.0 5.0) +( 9.0 1.0 5.0) +( 10.0 1.0 5.0) +( 0.0 2.0 5.0) +( 1.0 2.0 5.0) +( 2.0 2.0 5.0) +( 3.0 2.0 5.0) +( 4.0 2.0 5.0) +( 5.0 2.0 5.0) +( 6.0 2.0 5.0) +( 7.0 2.0 5.0) +( 8.0 2.0 5.0) +( 9.0 2.0 5.0) +( 10.0 2.0 5.0) +( 0.0 3.0 5.0) +( 1.0 3.0 5.0) +( 2.0 3.0 5.0) +( 3.0 3.0 5.0) +( 4.0 3.0 5.0) +( 5.0 3.0 5.0) +( 6.0 3.0 5.0) +( 7.0 3.0 5.0) +( 8.0 3.0 5.0) +( 9.0 3.0 5.0) +( 10.0 3.0 5.0) +( 0.0 4.0 5.0) +( 1.0 4.0 5.0) +( 2.0 4.0 5.0) +( 3.0 4.0 5.0) +( 4.0 4.0 5.0) +( 5.0 4.0 5.0) +( 6.0 4.0 5.0) +( 7.0 4.0 5.0) +( 8.0 4.0 5.0) +( 9.0 4.0 5.0) +( 10.0 4.0 5.0) +( 0.0 5.0 5.0) +( 1.0 5.0 5.0) +( 2.0 5.0 5.0) +( 3.0 5.0 5.0) +( 4.0 5.0 5.0) +( 5.0 5.0 5.0) +( 6.0 5.0 5.0) +( 7.0 5.0 5.0) +( 8.0 5.0 5.0) +( 9.0 5.0 5.0) +( 10.0 5.0 5.0) +( 0.0 6.0 5.0) +( 1.0 6.0 5.0) +( 2.0 6.0 5.0) +( 3.0 6.0 5.0) +( 4.0 6.0 5.0) +( 5.0 6.0 5.0) +( 6.0 6.0 5.0) +( 7.0 6.0 5.0) +( 8.0 6.0 5.0) +( 9.0 6.0 5.0) +( 10.0 6.0 5.0) +( 0.0 7.0 5.0) +( 1.0 7.0 5.0) +( 2.0 7.0 5.0) +( 3.0 7.0 5.0) +( 4.0 7.0 5.0) +( 5.0 7.0 5.0) +( 6.0 7.0 5.0) +( 7.0 7.0 5.0) +( 8.0 7.0 5.0) +( 9.0 7.0 5.0) +( 10.0 7.0 5.0) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +blocks +( + + //block 0 +hex (0 1 12 11 88 89 100 99 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 1 +hex (1 2 13 12 89 90 101 100 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 2 +hex (2 3 14 13 90 91 102 101 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 3 +hex (3 4 15 14 91 92 103 102 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 4 +hex (4 5 16 15 92 93 104 103 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 5 +hex (5 6 17 16 93 94 105 104 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 6 +hex (6 7 18 17 94 95 106 105 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 7 +hex (7 8 19 18 95 96 107 106 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 8 +hex (8 9 20 19 96 97 108 107 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 9 +hex (9 10 21 20 97 98 109 108 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 10 +hex (97 98 109 108 185 186 197 196 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 11 +hex (185 186 197 196 273 274 285 284 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 12 +hex (273 274 285 284 361 362 373 372 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 13 +hex (361 362 373 372 449 450 461 460 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 14 +hex (360 361 372 371 448 449 460 459 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 15 +hex (359 360 371 370 447 448 459 458 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 16 +hex (358 359 370 369 446 447 458 457 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 17 +hex (357 358 369 368 445 446 457 456 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 18 +hex (356 357 368 367 444 445 456 455 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 19 +hex (355 356 367 366 443 444 455 454 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 20 +hex (354 355 366 365 442 443 454 453 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 21 +hex (353 354 365 364 441 442 453 452 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 22 +hex (352 353 364 363 440 441 452 451 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 23 +hex (363 364 375 374 451 452 463 462 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 24 +hex (374 375 386 385 462 463 474 473 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 25 +hex (385 386 397 396 473 474 485 484 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 26 +hex (396 397 408 407 484 485 496 495 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 27 +hex (407 408 419 418 495 496 507 506 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 28 +hex (418 419 430 429 506 507 518 517 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 29 +hex (308 309 320 319 396 397 408 407 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 30 +hex (220 221 232 231 308 309 320 319 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 31 +hex (132 133 144 143 220 221 232 231 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 32 +hex (44 45 56 55 132 133 144 143 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 33 +hex (55 56 67 66 143 144 155 154 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 34 +hex (66 67 78 77 154 155 166 165 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 35 +hex (33 34 45 44 121 122 133 132 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 36 +hex (22 23 34 33 110 111 122 121 ) +( 10 10 10 ) +SimpleGrading (1 1 1) + + //block 37 +hex (11 12 23 22 99 100 111 110 ) +( 10 10 10 ) +SimpleGrading (1 1 1) +); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +defaultPatch +{ type wall;} + +patches +( +); diff --git a/papers/scaleup/generate_scaleup_runs/template/system/controlDict b/papers/scaleup/generate_scaleup_runs/template/system/controlDict new file mode 100644 index 00000000..7561264c --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/controlDict @@ -0,0 +1,67 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application birdmultiphaseEulerFoam; + +startFrom latestTime;//startTime; + +startTime 0; + +stopAt endTime; + +endTime 200; + +deltaT 0.0001; + +writeControl adjustableRunTime; + +writeInterval 2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.25; + +maxDeltaT 0.005; + + +functions +{ + + #includeFunc writeObjects(d.gas) + #includeFunc writeObjects(thermo:rho.gas) + #includeFunc writeObjects(thermo:rho.liquid) +} +//functions +//{ +// #includeFunc fieldAverage(U.air, U.water, alpha.air, p) +//} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/system/decomposeParDict b/papers/scaleup/generate_scaleup_runs/template/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/decomposeParDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 3.0.x | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 16; + +method scotch; + +hierarchicalCoeffs +{ + n (4 4 1); + delta 0.001; + order xyz; +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/system/fvConstraints b/papers/scaleup/generate_scaleup_runs/template/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/fvConstraints @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvConstraints; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +limitp +{ + type limitPressure; + + min 1e4; +} +limitUliq +{ + type limitVelocity; + active yes; + U U.liquid; + selectionMode all; + max 1e1; +} +limitUgas +{ + type limitVelocity; + active yes; + U U.gas; + selectionMode all; + max 2e1; +} +limitTgas +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase gas; +} +limitTliq +{ + type limitTemperature; + selectionMode all; + min 290; + max 310; + phase liquid; +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/system/fvSchemes b/papers/scaleup/generate_scaleup_runs/template/system/fvSchemes new file mode 100644 index 00000000..9e5fed8b --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/fvSchemes @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + limited cellLimited Gauss linear 1; +} + +divSchemes +{ + default none; + + "div\(phi,alpha.*\)" Gauss vanLeer; + + "div\(phir,alpha.*,alpha.*\)" Gauss vanLeer; + + "div\(alphaRhoPhi.*,U.*\)" Gauss limitedLinearV 1; + "div\(phi.*,U.*\)" Gauss limitedLinearV 1; + "div\(alphaRhoPhi.*,Yi\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(h|e).*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,(K|k|epsilon|omega).*\)" Gauss limitedLinear 1; + "div\(alphaPhi.*,f.*\)" Gauss limitedLinear 1; + "div\(alphaRhoPhi.*,\(p\|thermo:rho.*\)\)" Gauss limitedLinear 1; + + "div\(phim,(k|epsilon|omega)m\)" Gauss upwind; + "div\(\(\(\(alpha.*\*thermo:rho.*\)*nuEff.*\)*dev2\(T\(grad\(U.*\)\)\)\)\)" Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default uncorrected; +} + +wallDist +{ + method Poisson; + nRequired true; +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/system/fvSolution b/papers/scaleup/generate_scaleup_runs/template/system/fvSolution new file mode 100644 index 00000000..05d80e1e --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/fvSolution @@ -0,0 +1,121 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "alpha.*" + { + nAlphaCorr 2; + nAlphaSubCycles 5; + } + + bubbles + { + nCorr 1; + tolerance 1e-4; + scale true; + solveOnFinalIterOnly true; + sourceUpdateInterval 1; + } + + p_rgh + { + solver GAMG; + smoother DIC; + tolerance 1e-7; + relTol 0; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(k|omega|epsilon).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-7; + relTol 1e-4; + minIter 0; + maxIter 3; + } + + "(e|h).*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + minIter 0; + maxIter 3; + } + + "f.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + "Yi.*" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-12; + relTol 0; + residualAlpha 1e-8; + } + + "U.*" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-5; + relTol 0; + minIter 1; + } + + yPsi + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } + +} + +PIMPLE +{ + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 0; + +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/system/inlets_outlets.json b/papers/scaleup/generate_scaleup_runs/template/system/inlets_outlets.json new file mode 100644 index 00000000..2b53da73 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/inlets_outlets.json @@ -0,0 +1,28 @@ +{ + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0}, + "y" : {"nblocks": 11, "size_per_block": 1.0}, + "z" : {"nblocks": 5, "size_per_block": 1.0} + }, + "Fluids": [ + [ [0,0,0], [9,0,0] ], + [ [9,0,0], [9,0,4] ], + [ [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4] ], + [ [0,4,4], [0,10,4] ], + [ [0,4,4], [0,4,0] ], + [ [0,4,0], [0,10,0] ], + [ [0,4,0], [0,1,0] ] + ] + }, + "inlets": [ + {"branch_id": 0, "type": "circle", "frac_space": 0.2222222222222222, "normal_dir": 1, "radius": 0.4, "nelements": 50, "block_pos": "bottom"}, + {"branch_id": 0, "type": "circle", "frac_space": 0.5, "radius": 0.4, "normal_dir": 1,"nelements": 50, "block_pos": "bottom"}, + {"branch_id": 0, "type": "circle", "frac_space": 0.7777777777777778, "radius": 0.4, "normal_dir": 1,"nelements": 50, "block_pos": "bottom"} + ], + "outlets": [ + {"branch_id": 6, "type": "circle", "frac_space": 1, "normal_dir": 1, "radius": 0.4, "nelements": 50, "block_pos": "top"}, + {"branch_id": 4, "type": "circle", "frac_space": 1, "normal_dir": 1, "radius": 0.4, "nelements": 50, "block_pos": "top"} + ] +} diff --git a/papers/scaleup/generate_scaleup_runs/template/system/mesh.json b/papers/scaleup/generate_scaleup_runs/template/system/mesh.json new file mode 100644 index 00000000..29841d7e --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/mesh.json @@ -0,0 +1,26 @@ +{ + "Meshing": { + "Blockwise": { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0}, + "y" : {"nblocks": 11, "size_per_block": 1.0}, + "z" : {"nblocks": 5, "size_per_block": 1.0} + }, + "Fluids": [ + [ [0,0,0], [9,0,0] ], + [ [9,0,0], [9,0,4] ], + [ [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4] ], + [ [0,4,4], [0,10,4] ], + [ [0,4,4], [0,4,0] ], + [ [0,4,0], [0,10,0] ], + [ [0,4,0], [0,1,0] ] + ] + } +} diff --git a/papers/scaleup/generate_scaleup_runs/template/system/mixers.json b/papers/scaleup/generate_scaleup_runs/template/system/mixers.json new file mode 100644 index 00000000..b6224fb7 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/mixers.json @@ -0,0 +1,29 @@ +{ + "Meshing": { + "Blockwise": { + "x" : 10, + "y" : 10, + "z" : 10 + } + }, + "Geometry": { + "OverallDomain": { + "x" : {"nblocks": 10, "size_per_block": 1.0, "rescale": 2.7615275385627096}, + "y" : {"nblocks": 11, "size_per_block": 1.0, "rescale": 2.7615275385627096}, + "z" : {"nblocks": 5, "size_per_block": 1.0, "rescale": 2.7615275385627096} + }, + "Fluids": [ + [ [0,0,0], [9,0,0] ], + [ [9,0,0], [9,0,4] ], + [ [9,0,4], [0,0,4] ], + [ [0,1,4], [0,4,4] ], + [ [0,4,4], [0,10,4] ], + [ [0,4,4], [0,4,0] ], + [ [0,4,0], [0,10,0] ], + [ [0,4,0], [0,1,0] ] + ] + }, + "mixers": [ + {"branch_id": 2, "frac_space": 0.5, "start_time": 4, "power": 1500, "sign": "+"} + ] +} diff --git a/papers/scaleup/generate_scaleup_runs/template/system/setFieldsDict b/papers/scaleup/generate_scaleup_runs/template/system/setFieldsDict new file mode 100644 index 00000000..89a797b9 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/system/setFieldsDict @@ -0,0 +1,37 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: dev + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( + volScalarFieldValue alpha.gas 0.99 + volScalarFieldValue alpha.liquid 0.01 +); + +regions +( + boxToCell + { + box (-1.0 -1.0 -1.0) (552.3 11.046 552.3); + fieldValues + ( + volScalarFieldValue alpha.gas 0.01 + volScalarFieldValue alpha.liquid 0.99 + ); + } +); + + +// ************************************************************************* // diff --git a/papers/scaleup/generate_scaleup_runs/template/test.foam b/papers/scaleup/generate_scaleup_runs/template/test.foam new file mode 100644 index 00000000..e69de29b diff --git a/papers/scaleup/generate_scaleup_runs/template/writeGlobalVars.py b/papers/scaleup/generate_scaleup_runs/template/writeGlobalVars.py new file mode 100644 index 00000000..e64d69e3 --- /dev/null +++ b/papers/scaleup/generate_scaleup_runs/template/writeGlobalVars.py @@ -0,0 +1,42 @@ +import os + +import numpy as np + +from bird.utilities.ofio import * + + +def writeGvars(inletA, liqVol): + filename_tmp = os.path.join("constant", "globalVars_temp") + with open(filename_tmp, "r+") as f: + lines = f.readlines() + filename = os.path.join("constant", "globalVars") + with open(filename, "w+") as f: + for line in lines: + if line.startswith("inletA"): + f.write(f"inletA\t{inletA:g};\n") + elif line.startswith("liqVol"): + f.write(f"liqVol\t{liqVol:g};\n") + else: + f.write(line) + + +def readInletArea(): + filename = os.path.join( + "postProcessing", + "patchIntegrate(patch=inlet,field=alpha.gas)", + "0", + "surfaceFieldValue.dat", + ) + return read_surface_field_value(filename) + + +def getLiqVol(): + volume_field, _ = read_cell_volumes(".") + alpha_field, _ = read_field(".", "0", field_name="alpha.liquid") + return np.sum(volume_field * alpha_field) + + +if __name__ == "__main__": + A = readInletArea() + V = getLiqVol() + writeGvars(A, V) From 824a222c02b577bc511b745168dbc457c899c27e Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 14:38:48 -0600 Subject: [PATCH 39/52] Add mesh-agnostic loop velocity post-processing --- bird/postprocess/post_quantities/__init__.py | 10 + .../post_quantities/loop_velocity.py | 265 ++++++++++++++++++ tests/postprocess/test_loop_velocity.py | 205 ++++++++++++++ 3 files changed, 480 insertions(+) create mode 100644 bird/postprocess/post_quantities/loop_velocity.py create mode 100644 tests/postprocess/test_loop_velocity.py diff --git a/bird/postprocess/post_quantities/__init__.py b/bird/postprocess/post_quantities/__init__.py index 23ecfc38..82945861 100644 --- a/bird/postprocess/post_quantities/__init__.py +++ b/bird/postprocess/post_quantities/__init__.py @@ -6,16 +6,26 @@ _weighted_average, ) from .kla import compute_fitted_kla, compute_instantaneous_kla +from .loop_velocity import ( + build_loop_direction_field, + build_loop_direction_field_from_path, + compute_loop_velocity, + propose_loop_boxes_block_rect, +) from .phase import compute_ave_bubble_diam, compute_gas_holdup from .species import compute_ave_conc_liq, compute_ave_y_liq from .superficial_velocity import compute_superficial_gas_velocity __all__ = [ + "build_loop_direction_field", + "build_loop_direction_field_from_path", "compute_ave_bubble_diam", "compute_ave_conc_liq", "compute_ave_y_liq", "compute_fitted_kla", "compute_gas_holdup", "compute_instantaneous_kla", + "compute_loop_velocity", "compute_superficial_gas_velocity", + "propose_loop_boxes_block_rect", ] diff --git a/bird/postprocess/post_quantities/loop_velocity.py b/bird/postprocess/post_quantities/loop_velocity.py new file mode 100644 index 00000000..bbd0567e --- /dev/null +++ b/bird/postprocess/post_quantities/loop_velocity.py @@ -0,0 +1,265 @@ +import numpy as np + +from bird import logger +from bird.meshing.block_rect_mesh import from_block_rect_to_seg +from bird.utilities.ofio import read_cell_volumes, read_field + +from ._cell_filter import _weighted_average + + +def _normalize(vector: np.ndarray) -> np.ndarray: + """Unit vector along ``vector`` (raises on a zero vector).""" + norm = np.linalg.norm(vector) + if norm == 0: + raise ValueError("Cannot normalize a zero-length direction vector") + return vector / norm + + +def _report_coverage(covered: np.ndarray) -> None: + """Warn about the fraction of uncovered cells; list their ids in debug.""" + n_cells = len(covered) + n_uncovered = int(np.count_nonzero(~covered)) + if n_uncovered: + logger.warning( + f"{n_uncovered}/{n_cells} cells " + f"({100.0 * n_uncovered / n_cells:.2f}%) have no loop direction " + f"and are excluded from the loop velocity" + ) + logger.debug( + f"Uncovered cell ids: {np.flatnonzero(~covered).tolist()}" + ) + + +def build_loop_direction_field( + cell_centers: np.ndarray, boxes: list[dict] +) -> np.ndarray: + """Per-cell loop-direction field from labelled axis-aligned boxes. + + Each cell inherits the (unit) direction of the box that contains its centre. + Cells in no box keep ``NaN`` (excluded from the average); a cell in more than + one box is ambiguous and raises. + + :param cell_centers: cell centres, shape ``(N, 3)`` + :param boxes: list of ``{"min": [x, y, z], "max": [x, y, z], + "direction": [dx, dy, dz]}``; ``direction`` is normalized internally + :return: direction field, shape ``(N, 3)``, ``NaN`` where uncovered + """ + cell_centers = np.asarray(cell_centers, dtype=float) + n_cells = len(cell_centers) + direction_field = np.full((n_cells, 3), np.nan) + coverage_count = np.zeros(n_cells, dtype=int) + + for box in boxes: + box_min = np.asarray(box["min"], dtype=float) + box_max = np.asarray(box["max"], dtype=float) + direction = _normalize(np.asarray(box["direction"], dtype=float)) + inside = np.all( + (cell_centers >= box_min) & (cell_centers <= box_max), axis=1 + ) + coverage_count += inside + direction_field[inside] = direction + + n_overlap = int(np.count_nonzero(coverage_count > 1)) + if n_overlap: + raise ValueError( + f"{n_overlap} cells fall in more than one box; loop-direction " + f"boxes must not overlap" + ) + + covered = coverage_count > 0 + if not np.any(covered): + raise ValueError( + "No cell falls within any loop box; the boxes and the mesh are in " + "different coordinate frames. For a block-rectangular case this " + "usually means the 'rescale' parameter is missing from mesh.json " + "(assumed 1.0) - supply the rescale used to build the mesh." + ) + + _report_coverage(covered) + return direction_field + + +def build_loop_direction_field_from_path( + cell_centers: np.ndarray, path_points: np.ndarray, max_dist: float +) -> np.ndarray: + """Per-cell loop-direction field from a centerline polyline. + + Each cell within ``max_dist`` of the polyline gets the unit tangent of its + nearest segment; cells farther away keep ``NaN`` (excluded). The polyline + ordering sets the circulation sense. + + :param cell_centers: cell centres, shape ``(N, 3)`` + :param path_points: ordered centerline vertices, shape ``(M, 3)`` + :param max_dist: cells beyond this distance from the path are left uncovered + :return: direction field, shape ``(N, 3)``, ``NaN`` where uncovered + """ + cell_centers = np.asarray(cell_centers, dtype=float) + path_points = np.asarray(path_points, dtype=float) + if len(path_points) < 2: + raise ValueError("path_points must contain at least two vertices") + + n_cells = len(cell_centers) + best_distance = np.full(n_cells, np.inf) + direction_field = np.full((n_cells, 3), np.nan) + + for start, end in zip(path_points[:-1], path_points[1:]): + segment = end - start + length_sq = float(segment @ segment) + if length_sq == 0.0: + continue + tangent = segment / np.sqrt(length_sq) + # Projection parameter of each cell onto the segment, clamped to [0, 1] + param = np.clip( + ((cell_centers - start) @ segment) / length_sq, 0.0, 1.0 + ) + projection = start + param[:, None] * segment + distance = np.linalg.norm(cell_centers - projection, axis=1) + closer = distance < best_distance + best_distance[closer] = distance[closer] + direction_field[closer] = tangent + + uncovered = best_distance > max_dist + direction_field[uncovered] = np.nan + if np.all(uncovered): + raise ValueError( + "No cell lies within max_dist of the path; the path and the mesh " + "are in different coordinate frames, or max_dist is too small" + ) + _report_coverage(~uncovered) + return direction_field + + +def propose_loop_boxes_block_rect( + mesh_geometry: dict, rescale: float | None = None +) -> list[dict]: + """Candidate loop-direction boxes for a block-rectangular loop reactor. + + Builds one box per mesh segment (leg) from + :func:`bird.meshing.block_rect_mesh.from_block_rect_to_seg`. Each box spans the + leg along its axis, trimmed half a block at each end so adjacent legs do not + overlap and the ambiguous junction cells stay uncovered. The proposed direction + is each leg's own axis orientation (``end - start``). + + The mesh scale is never inferred: the box coordinates are scaled by ``rescale``, + which the caller must set to the factor used to build the mesh (e.g. the + ``transformPoints`` scale). A mismatch surfaces downstream as a zero-coverage + error in :func:`build_loop_direction_field`. + + :param mesh_geometry: the ``"Geometry"`` dict from the case ``mesh.json`` + :param rescale: uniform scale factor applied to the box coordinates; ``None`` + assumes 1.0 (base units) + :return: box list consumable by :func:`build_loop_direction_field` + """ + factor = 1.0 if rescale is None else float(rescale) + segment_data = from_block_rect_to_seg(mesh_geometry, rescale=False) + segments = segment_data["segments"] + block_size = segment_data["blocksize"] + + boxes = [] + for segment in segments.values(): + start = np.asarray(segment["start"], dtype=float) + end = np.asarray(segment["end"], dtype=float) + normal_dir = int(segment["normal_dir"]) + max_rad = float(segment["max_rad"]) + + box_min = np.empty(3) + box_max = np.empty(3) + for axis in range(3): + if axis == normal_dir: + low = min(start[axis], end[axis]) + 0.5 * block_size[axis] + high = max(start[axis], end[axis]) - 0.5 * block_size[axis] + else: + low = start[axis] - max_rad + high = start[axis] + max_rad + box_min[axis] = low + box_max[axis] = high + + boxes.append( + { + "min": (box_min * factor).tolist(), + "max": (box_max * factor).tolist(), + "direction": _normalize(end - start).tolist(), + } + ) + return boxes + + +def _read_liquid_fraction( + case_folder: str, time_folder: str, n_cells: int, field_dict: dict +) -> tuple[np.ndarray | float, dict]: + """Liquid fraction from alpha.gas (1 - alpha.gas) or alpha.liquid.""" + try: + alpha_gas, field_dict = read_field( + case_folder, time_folder, "alpha.gas", n_cells, field_dict + ) + return 1.0 - np.asarray(alpha_gas), field_dict + except FileNotFoundError: + pass + try: + alpha_liquid, field_dict = read_field( + case_folder, time_folder, "alpha.liquid", n_cells, field_dict + ) + return alpha_liquid, field_dict + except FileNotFoundError: + raise FileNotFoundError( + "Need alpha.gas or alpha.liquid to average over the liquid" + ) + + +def compute_loop_velocity( + case_folder: str, + time_folder: str, + loop_direction_field: np.ndarray, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Loop velocity: liquid velocity projected on the loop direction. + + .. math:: + \frac{\int_{V_{\rm loop}} \alpha_{\rm liq}\, (\mathbf{U}_{\rm liq} \cdot + \hat{\mathbf{e}}_{\rm loop})\, dV}{\int_{V_{\rm loop}} \alpha_{\rm liq}\, dV} + + Averaged over the liquid on the covered cells. Positive follows the prescribed + circulation, negative is reversed. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param loop_direction_field: ``(N, 3)`` field from a builder, ``NaN`` on + uncovered cells + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(loop_velocity, field_dict)`` + """ + if field_dict is None: + field_dict = {} + + loop_direction_field = np.asarray(loop_direction_field, dtype=float) + n_cells = len(loop_direction_field) + covered = ~np.isnan(loop_direction_field).any(axis=1) + if not np.any(covered): + raise ValueError("The loop-direction field covers no cell") + + u_liquid, field_dict = read_field( + case_folder, time_folder, "U.liquid", n_cells, field_dict + ) + # A uniform vector field is read as shape (3,); broadcast to one per cell + if np.ndim(u_liquid) == 1: + u_liquid = np.broadcast_to(u_liquid, (n_cells, 3)) + + cell_volume, field_dict = read_cell_volumes( + case_folder, volume_time, n_cells, field_dict + ) + alpha_liquid, field_dict = _read_liquid_fraction( + case_folder, time_folder, n_cells, field_dict + ) + + # Liquid velocity projected on the loop direction, averaged over the liquid + weights = np.asarray(cell_volume) * np.asarray(alpha_liquid) + if weights.ndim == 0: + weights = np.full(n_cells, float(weights)) + projected = np.sum( + u_liquid[covered] * loop_direction_field[covered], axis=1 + ) + loop_velocity = _weighted_average(projected, weights[covered]) + + return float(loop_velocity), field_dict diff --git a/tests/postprocess/test_loop_velocity.py b/tests/postprocess/test_loop_velocity.py new file mode 100644 index 00000000..7b891b82 --- /dev/null +++ b/tests/postprocess/test_loop_velocity.py @@ -0,0 +1,205 @@ +import json +import os +import tempfile +from pathlib import Path + +import numpy as np + +from bird.postprocess.post_quantities import ( + build_loop_direction_field, + build_loop_direction_field_from_path, + compute_loop_velocity, + propose_loop_boxes_block_rect, +) + + +def write_min_case(root, u_vectors, cell_volumes, alpha_gas=None): + """Minimal case with a vector U.liquid, scalar V and optional alpha.gas.""" + os.makedirs(os.path.join(root, "0"), exist_ok=True) + + def write_field(name, foam_class, body): + with open(os.path.join(root, "0", name), "w") as f: + f.write("FoamFile\n{\n format ascii;\n") + f.write(f" class {foam_class};\n") + f.write(f" object {name};\n}}\n\n") + f.write("dimensions [0 0 0 0 0 0 0];\n\n") + f.write(body) + + def scalar(values): + entries = "\n".join(f"{v:.10g}" for v in values) + return ( + "internalField nonuniform List \n" + f"{len(values)}\n(\n{entries}\n)\n;\n" + ) + + def vector(vectors): + entries = "\n".join( + f"({x:.10g} {y:.10g} {z:.10g})" for x, y, z in vectors + ) + return ( + "internalField nonuniform List \n" + f"{len(vectors)}\n(\n{entries}\n)\n;\n" + ) + + write_field("V", "volScalarField", scalar(cell_volumes)) + write_field("U.liquid", "volVectorField", vector(u_vectors)) + if alpha_gas is not None: + write_field("alpha.gas", "volScalarField", scalar(alpha_gas)) + + +def test_build_loop_direction_field(): + # Four cells: two in box A (+x), one in box B (+y), one in no box + cell_centers = np.array( + [[0.5, 0.0, 0.0], [1.5, 0.0, 0.0], [5.0, 5.0, 0.0], [9.0, 9.0, 9.0]] + ) + boxes = [ + {"min": [0, -1, -1], "max": [2, 1, 1], "direction": [3, 0, 0]}, + {"min": [4, 4, -1], "max": [6, 6, 1], "direction": [0, 2, 0]}, + ] + field = build_loop_direction_field(cell_centers, boxes) + + assert field.shape == (4, 3) + # direction is normalized to a unit vector + np.testing.assert_allclose(field[0], [1, 0, 0]) + np.testing.assert_allclose(field[1], [1, 0, 0]) + np.testing.assert_allclose(field[2], [0, 1, 0]) + # uncovered cell stays NaN + assert np.all(np.isnan(field[3])) + + # a cell inside two boxes is ambiguous -> error + overlap = [ + {"min": [0, -1, -1], "max": [2, 1, 1], "direction": [1, 0, 0]}, + {"min": [1, -1, -1], "max": [3, 1, 1], "direction": [0, 1, 0]}, + ] + try: + build_loop_direction_field(cell_centers, overlap) + raised = False + except ValueError: + raised = True + assert raised + + # boxes that match no cell (e.g. wrong coordinate frame / rescale) -> error + far = [ + { + "min": [100, 100, 100], + "max": [101, 101, 101], + "direction": [1, 0, 0], + } + ] + try: + build_loop_direction_field(cell_centers, far) + raised_empty = False + except ValueError: + raised_empty = True + assert raised_empty + + +def test_build_loop_direction_field_from_path(): + # Path: (0,0,0)->(1,0,0) [+x] then (1,0,0)->(1,1,0) [+y] + path = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]]) + cell_centers = np.array( + [ + [0.5, 0.05, 0.0], # near the +x segment + [1.0, 0.5, 0.0], # on the +y segment + [0.5, 5.0, 0.0], # far from the path + ] + ) + field = build_loop_direction_field_from_path( + cell_centers, path, max_dist=0.5 + ) + + np.testing.assert_allclose(field[0], [1, 0, 0], atol=1e-12) + np.testing.assert_allclose(field[1], [0, 1, 0], atol=1e-12) + assert np.all(np.isnan(field[2])) + + # every cell beyond max_dist (wrong frame) -> error + try: + build_loop_direction_field_from_path( + np.array([[50.0, 50.0, 50.0]]), path, max_dist=0.5 + ) + raised = False + except ValueError: + raised = True + assert raised + + +def test_propose_loop_boxes_block_rect(): + template = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "bird", + "meshing", + "block_rect_mesh_templates", + "loopReactor", + "input.json", + ) + geometry = json.load(open(template))["Geometry"] + # rescale=None -> base units (factor 1.0) + boxes = propose_loop_boxes_block_rect(geometry, rescale=None) + + # two Fluids branches of 4 blocks -> 3 segments each -> 6 legs + assert len(boxes) == 6 + + # first leg: [0,0,0]->[9,0,0], centres at 0.5..9.5, trimmed half a block + first = boxes[0] + np.testing.assert_allclose(first["direction"], [1, 0, 0]) + np.testing.assert_allclose(first["min"], [1.0, 0.0, 0.0]) + np.testing.assert_allclose(first["max"], [9.0, 1.0, 1.0]) + + # a float rescale scales the box coordinates but not the direction + scaled = propose_loop_boxes_block_rect(geometry, rescale=2.0) + np.testing.assert_allclose(scaled[0]["min"], [2.0, 0.0, 0.0]) + np.testing.assert_allclose(scaled[0]["max"], [18.0, 2.0, 2.0]) + np.testing.assert_allclose(scaled[0]["direction"], [1, 0, 0]) + + +def test_compute_loop_velocity(): + # Two cells pointing along +x, direction +x -> loop velocity = weighted |Ux| + u_vectors = [[2.0, 0.0, 0.0], [4.0, 0.0, 0.0]] + cell_volumes = [1.0, 3.0] + direction_field = np.array([[1.0, 0.0, 0.0], [1.0, 0.0, 0.0]]) + + # all-liquid (alpha.gas = 0) -> volume-weighted mean = (2*1 + 4*3)/(1+3) = 3.5 + with tempfile.TemporaryDirectory() as tmp: + write_min_case(tmp, u_vectors, cell_volumes, alpha_gas=[0.0, 0.0]) + v, _ = compute_loop_velocity( + tmp, "0", direction_field, volume_time="0" + ) + assert abs(v - 3.5) < 1e-10 + + # a NaN direction excludes its cell: only the first cell counts -> 2.0 + with tempfile.TemporaryDirectory() as tmp: + write_min_case(tmp, u_vectors, cell_volumes, alpha_gas=[0.0, 0.0]) + partial = np.array([[1.0, 0.0, 0.0], [np.nan, np.nan, np.nan]]) + v_partial, _ = compute_loop_velocity( + tmp, "0", partial, volume_time="0" + ) + assert abs(v_partial - 2.0) < 1e-10 + + # reversed direction flips the sign + with tempfile.TemporaryDirectory() as tmp: + write_min_case(tmp, u_vectors, cell_volumes, alpha_gas=[0.0, 0.0]) + reversed_dir = np.array([[-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]]) + v_rev, _ = compute_loop_velocity( + tmp, "0", reversed_dir, volume_time="0" + ) + assert abs(v_rev + 3.5) < 1e-10 + + # liquid weighting from alpha.gas: weights = vol*(1-alpha_gas) = [1, 1.5] + with tempfile.TemporaryDirectory() as tmp: + write_min_case(tmp, u_vectors, cell_volumes, alpha_gas=[0.0, 0.5]) + v_alpha, _ = compute_loop_velocity( + tmp, "0", direction_field, volume_time="0" + ) + assert abs(v_alpha - (2 * 1.0 + 4 * 1.5) / 2.5) < 1e-10 + + # neither alpha.gas nor alpha.liquid present -> error + with tempfile.TemporaryDirectory() as tmp: + write_min_case(tmp, u_vectors, cell_volumes) + try: + compute_loop_velocity(tmp, "0", direction_field, volume_time="0") + raised = False + except FileNotFoundError: + raised = True + assert raised From bf0a38d7b73f11ca3e473ba5a460fe81e97c93ef Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 14:46:26 -0600 Subject: [PATCH 40/52] Add compute_loop_velocity CLI wrapper --- applications/compute_loop_velocity.py | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 applications/compute_loop_velocity.py diff --git a/applications/compute_loop_velocity.py b/applications/compute_loop_velocity.py new file mode 100644 index 00000000..f30968b2 --- /dev/null +++ b/applications/compute_loop_velocity.py @@ -0,0 +1,87 @@ +import argparse +import csv +import json +import os + +from bird import logger +from bird.postprocess.post_quantities import ( + build_loop_direction_field, + build_loop_direction_field_from_path, + compute_loop_velocity, + propose_loop_boxes_block_rect, +) +from bird.utilities.ofio import get_case_times, read_cell_centers + + +def build_direction_field(args, cell_centers): + """Loop-direction field from the box, path, or block-rect proposer source.""" + if args.boxes is not None: + with open(args.boxes) as f: + boxes = json.load(f) + return build_loop_direction_field(cell_centers, boxes) + if args.path is not None: + with open(args.path) as f: + spec = json.load(f) + return build_loop_direction_field_from_path( + cell_centers, spec["points"], spec["max_dist"] + ) + with open(args.mesh) as f: + geometry = json.load(f)["Geometry"] + boxes = propose_loop_boxes_block_rect(geometry, rescale=args.rescale) + return build_loop_direction_field(cell_centers, boxes) + + +def main(): + parser = argparse.ArgumentParser(description="Loop (circulation) velocity") + parser.add_argument( + "-c", "--case", type=str, default=".", help="case folder" + ) + source = parser.add_mutually_exclusive_group(required=True) + source.add_argument( + "-b", "--boxes", type=str, help="JSON list of {min, max, direction}" + ) + source.add_argument( + "-p", + "--path", + type=str, + help='JSON {"points": [[x,y,z], ...], "max_dist": float}', + ) + source.add_argument( + "-m", "--mesh", type=str, help="mesh.json for the block-rect proposer" + ) + parser.add_argument( + "-r", + "--rescale", + type=float, + default=None, + help="rescale factor for the proposer (default 1.0)", + ) + parser.add_argument( + "-o", + "--output", + type=str, + default=None, + help="output CSV (default /Uliq_loop.csv)", + ) + args = parser.parse_args() + + cell_centers, _ = read_cell_centers(args.case) + direction_field = build_direction_field(args, cell_centers) + + time_values, time_names = get_case_times(args.case, remove_zero=True) + output = args.output or os.path.join(args.case, "Uliq_loop.csv") + with open(output, "w", newline="") as f: + writer = csv.writer(f) + writer.writerow(["time", "U_loop"]) + for time_value, time_name in zip(time_values, time_names): + # fresh cache per time (the caller must reset it) + u_loop, _ = compute_loop_velocity( + args.case, time_name, direction_field, field_dict={} + ) + writer.writerow([time_value, u_loop]) + logger.info(f"t={time_value:.4g}: U_loop={u_loop:.6g}") + logger.info(f"Wrote {output}") + + +if __name__ == "__main__": + main() From 1d1e9e57c6a180e77d5a5d85dd80bcf299ba2d30 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 14:57:15 -0600 Subject: [PATCH 41/52] Add steady_stat windowed --- bird/postprocess/stats.py | 40 +++++++++++++++++++++++++++++++++ tests/postprocess/test_stats.py | 33 ++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/bird/postprocess/stats.py b/bird/postprocess/stats.py index 8f5a941e..f52f6f56 100644 --- a/bird/postprocess/stats.py +++ b/bird/postprocess/stats.py @@ -184,3 +184,43 @@ def calc_mean( unc_val = np.sqrt(sigsq * T0 / N) return mean_val, unc_val * 1.96 + + +def steady_stat( + time_series: np.ndarray | list, + time_values: np.ndarray | list, + window: float | None = None, +) -> tuple[float, float]: + """(mean, 1-sigma uncertainty) over the tail window of a time series. + + The statistic is computed over the last ``window`` (in time units) of the + series via the T0 estimator (:func:`calc_mean`), with its 95% (1.96 sigma) + uncertainty converted to 1 sigma. ``window`` defaults to 10% of the total + simulation time. Returns (nan, nan) for an empty or all-nan series and + (value, 0.0) when a single sample falls in the window. + + :param time_series: time series of the signal + :param time_values: sampling times of the series + :param window: length of the end window in time units; 10% of the total + time span if None + :return: (mean, 1-sigma uncertainty about the mean) + """ + time_series = np.asarray(time_series, dtype=float) + time_values = np.asarray(time_values, dtype=float) + if time_series.size == 0 or np.all(np.isnan(time_series)): + return np.nan, np.nan + + if window is None: + window = 0.1 * (time_values.max() - time_values.min()) + logger.warning(f"Steady state assumed over last {window}s") + + in_window = time_values >= time_values.max() - window + windowed_series = time_series[in_window] + windowed_values = time_values[in_window] + if np.all(np.isnan(windowed_series)): + return np.nan, np.nan + if windowed_series.size < 2: + return float(windowed_series[0]), 0.0 + + mean_value, uncertainty_95 = calc_mean(windowed_series, windowed_values) + return float(mean_value), float(uncertainty_95 / 1.96) diff --git a/tests/postprocess/test_stats.py b/tests/postprocess/test_stats.py index 60f7a69f..5f1ff631 100644 --- a/tests/postprocess/test_stats.py +++ b/tests/postprocess/test_stats.py @@ -4,7 +4,7 @@ import pytest from bird import logger -from bird.postprocess.stats import calc_mean +from bird.postprocess.stats import calc_mean, steady_stat def test_mean_stats_uniform(): @@ -59,3 +59,34 @@ def test_mean_stats_nonuniform(): # Make sure non uniform signal is correctly treated assert abs(unc_non_unif - unc_unif) / unc_unif < 0.1 + + +def test_steady_stat(): + """ + Test the windowed (mean, 1-sigma) steady-state statistic + """ + t = np.linspace(0, 10, 1000) + signal = np.cos(t * 2 * np.pi) + + # explicit window: stat is calc_mean over the last 2 s, 95% -> 1-sigma + mask = t >= t.max() - 2.0 + mean_ref, unc95_ref = calc_mean(signal[mask], t[mask]) + mean_val, sigma = steady_stat(signal, t, window=2.0) + assert mean_val == pytest.approx(mean_ref) + assert sigma == pytest.approx(unc95_ref / 1.96) + + # default window = 10% of the span (last 1 s here) + default_mask = t >= t.max() - 0.1 * (t.max() - t.min()) + mean_def_ref, _ = calc_mean(signal[default_mask], t[default_mask]) + mean_def, _ = steady_stat(signal, t) + assert mean_def == pytest.approx(mean_def_ref) + + # empty and all-nan series -> (nan, nan) + mean_empty, sigma_empty = steady_stat([], []) + assert np.isnan(mean_empty) and np.isnan(sigma_empty) + mean_nan, sigma_nan = steady_stat([np.nan, np.nan], [0.0, 1.0]) + assert np.isnan(mean_nan) and np.isnan(sigma_nan) + + # a single sample in the window -> (value, 0.0) + mean_one, sigma_one = steady_stat([1.0, 3.5], [0.0, 1.0], window=0.5) + assert mean_one == 3.5 and sigma_one == 0.0 From 02b40f15ee19332cbde12df1f7d414ae6ecca7a2 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 15:42:56 -0600 Subject: [PATCH 42/52] Add interfacial area, turbulent diffusivity, and kL post quantities --- bird/postprocess/post_quantities/__init__.py | 18 +- bird/postprocess/post_quantities/kla.py | 462 ++++++++++++++---- bird/postprocess/post_quantities/phase.py | 10 + bird/postprocess/post_quantities/transport.py | 79 +++ tests/postprocess/test_post_quantities.py | 117 ++++- tests/postprocess/test_transport.py | 52 ++ 6 files changed, 619 insertions(+), 119 deletions(-) create mode 100644 bird/postprocess/post_quantities/transport.py create mode 100644 tests/postprocess/test_transport.py diff --git a/bird/postprocess/post_quantities/__init__.py b/bird/postprocess/post_quantities/__init__.py index 82945861..459dc520 100644 --- a/bird/postprocess/post_quantities/__init__.py +++ b/bird/postprocess/post_quantities/__init__.py @@ -5,16 +5,26 @@ _get_ind_slice, _weighted_average, ) -from .kla import compute_fitted_kla, compute_instantaneous_kla +from .kla import ( + compute_fitted_kl, + compute_fitted_kla, + compute_instantaneous_kl, + compute_instantaneous_kla, +) from .loop_velocity import ( build_loop_direction_field, build_loop_direction_field_from_path, compute_loop_velocity, propose_loop_boxes_block_rect, ) -from .phase import compute_ave_bubble_diam, compute_gas_holdup +from .phase import ( + compute_ave_bubble_diam, + compute_gas_holdup, + interfacial_area, +) from .species import compute_ave_conc_liq, compute_ave_y_liq from .superficial_velocity import compute_superficial_gas_velocity +from .transport import compute_turbulent_diffusivity __all__ = [ "build_loop_direction_field", @@ -22,10 +32,14 @@ "compute_ave_bubble_diam", "compute_ave_conc_liq", "compute_ave_y_liq", + "compute_fitted_kl", "compute_fitted_kla", "compute_gas_holdup", + "compute_instantaneous_kl", "compute_instantaneous_kla", "compute_loop_velocity", "compute_superficial_gas_velocity", + "compute_turbulent_diffusivity", + "interfacial_area", "propose_loop_boxes_block_rect", ] diff --git a/bird/postprocess/post_quantities/kla.py b/bird/postprocess/post_quantities/kla.py index c60a666b..67e2ca50 100644 --- a/bird/postprocess/post_quantities/kla.py +++ b/bird/postprocess/post_quantities/kla.py @@ -16,9 +16,201 @@ from ..kla_utils import compute_kla from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average +from .phase import ( + compute_ave_bubble_diam, + compute_gas_holdup, + interfacial_area, +) from .species import compute_ave_conc_liq +def _instantaneous_kl_field( + case_folder: str, + time_folder: str, + species_names: str | list[str], + n_cells: int | None = None, + field_dict: dict | None = None, +) -> tuple[dict, dict]: + """Per-cell mass-transfer coefficient kL over the liquid, per species.""" + if field_dict is None: + field_dict = {} + if isinstance(species_names, str): + species_names = [species_names] + + kwargs = { + "case_folder": case_folder, + "time_folder": time_folder, + "n_cells": n_cells, + } + globalVars = read_global_vars(case_folder=case_folder, cross_ref=True) + ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) + + try: + rho_liq, field_dict = read_field( + field_name="thermo:rho.liquid", field_dict=field_dict, **kwargs + ) + except FileNotFoundError: + logger.warning( + f"thermo:rho.liquid not found in " + f"{os.path.join(case_folder, time_folder)}, assuming 1000kg/m3" + ) + rho_liq = 1000.0 + field_dict["rho_liq"] = rho_liq + U_gas, field_dict = read_field( + field_name="U.gas", field_dict=field_dict, **kwargs + ) + U_liq, field_dict = read_field( + field_name="U.liquid", field_dict=field_dict, **kwargs + ) + d_gas, field_dict = read_bubble_diameter(field_dict=field_dict, **kwargs) + mu_liq, field_dict = read_mu_liquid(field_dict=field_dict, **kwargs) + + rho_liq = _field_filter(rho_liq, ind=ind_liq, field_type="scalar") + U_gas = _field_filter(U_gas, ind=ind_liq, field_type="vector") + U_liq = _field_filter(U_liq, ind=ind_liq, field_type="vector") + d_gas = _field_filter(d_gas, ind=ind_liq, field_type="scalar") + mu_liq = _field_filter(mu_liq, ind=ind_liq, field_type="scalar") + + # Magnitude of the slip velocity. Using the last axis keeps this valid + # whether the velocities are uniform, shape (3,), or per cell, shape (N,3) + mag_U_diff = np.linalg.norm(U_gas - U_liq, axis=-1) + Re = rho_liq * mag_U_diff * d_gas / mu_liq + + kl_spec_field = {} + for species_name in species_names: + if not f"D_{species_name}" in globalVars: + err_msg = f"D_{species_name} was not found in globalVars." + err_msg += f'\nIf you add it, it should be looking like #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_{species_name},0.6)";' + raise KeyError(err_msg) + kl_spec_field[species_name] = ( + (2 / np.pi**0.5) + * 3600 + * (Re**0.5) + * (((mu_liq / rho_liq) / globalVars[f"D_{species_name}"]) ** 0.5) + * (globalVars[f"D_{species_name}"] / d_gas) + ) + return kl_spec_field, field_dict + + +def _instantaneous_a_field( + case_folder: str, + time_folder: str, + n_cells: int | None = None, + field_dict: dict | None = None, +) -> tuple[np.ndarray | float, dict]: + """Per-cell interfacial area a = 6 alpha_gas / d over the liquid.""" + if field_dict is None: + field_dict = {} + kwargs = { + "case_folder": case_folder, + "time_folder": time_folder, + "n_cells": n_cells, + } + ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) + alpha_gas, field_dict = read_field( + field_name="alpha.gas", field_dict=field_dict, **kwargs + ) + d_gas, field_dict = read_bubble_diameter(field_dict=field_dict, **kwargs) + alpha_gas = _field_filter(alpha_gas, ind=ind_liq, field_type="scalar") + d_gas = _field_filter(d_gas, ind=ind_liq, field_type="scalar") + return (6.0 / d_gas) * alpha_gas, field_dict + + +def _instantaneous_kla_field( + case_folder: str, + time_folder: str, + species_names: str | list[str], + n_cells: int | None = None, + field_dict: dict | None = None, +) -> tuple[dict, dict]: + """Per-cell kLa = kL * a over the liquid, per species.""" + if field_dict is None: + field_dict = {} + if isinstance(species_names, str): + species_names = [species_names] + kl_spec_field, field_dict = _instantaneous_kl_field( + case_folder, time_folder, species_names, n_cells, field_dict + ) + a_field, field_dict = _instantaneous_a_field( + case_folder, time_folder, n_cells, field_dict + ) + kla_spec_field = { + species_name: kl_spec_field[species_name] * a_field + for species_name in species_names + } + return kla_spec_field, field_dict + + +def _instantaneous_cstar( + case_folder: str, + time_folder: str, + species_names: str | list[str], + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[dict, dict]: + """Volume-averaged saturation concentration C* over the liquid, per species.""" + if field_dict is None: + field_dict = {} + if isinstance(species_names, str): + species_names = [species_names] + kwargs = { + "case_folder": case_folder, + "time_folder": time_folder, + "n_cells": n_cells, + } + kwargs_vol = { + "case_folder": case_folder, + "time_folder": volume_time, + "n_cells": n_cells, + } + globalVars = read_global_vars(case_folder=case_folder, cross_ref=True) + mw_species = {} + for species_name in species_names: + if not f"He_{species_name}" in globalVars: + err_msg = f"He_{species_name} was not found in globalVars." + err_msg += f'\nIf you add it, it should be looking like #calc "$H_{species_name}_298 * exp($DH_{species_name} *(1. / $T0 - 1./298.15))";' + raise KeyError(err_msg) + mw_species[species_name] = species_name_to_mw( + case_folder=case_folder, species_name=species_name + ) + ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) + alpha_gas, field_dict = read_field( + field_name="alpha.gas", field_dict=field_dict, **kwargs + ) + rho_gas, field_dict = read_field( + field_name="thermo:rho.gas", field_dict=field_dict, **kwargs + ) + species_gas = {} + for species_name in species_names: + species_gas[species_name], field_dict = read_field( + field_name=f"{species_name}.gas", field_dict=field_dict, **kwargs + ) + alpha_gas = _field_filter(alpha_gas, ind=ind_liq, field_type="scalar") + alpha_liq = 1 - alpha_gas + rho_gas = _field_filter(rho_gas, ind=ind_liq, field_type="scalar") + for species_name in species_names: + species_gas[species_name] = _field_filter( + species_gas[species_name], ind=ind_liq, field_type="scalar" + ) + cell_volume, field_dict = read_cell_volumes( + field_dict=field_dict, **kwargs_vol + ) + cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") + + cstar_spec = {} + for species_name in species_names: + cstar_field = ( + rho_gas + * species_gas[species_name] + * globalVars[f"He_{species_name}"] + ) / mw_species[species_name] + cstar_spec[species_name] = _weighted_average( + cstar_field, cell_volume * alpha_liq + ) + return cstar_spec, field_dict + + def compute_instantaneous_kla( case_folder: str, time_folder: str, @@ -110,11 +302,9 @@ def compute_instantaneous_kla( """ if field_dict is None: field_dict = {} - if isinstance(species_names, str): species_names = [species_names] - # Read relevant fields kwargs = { "case_folder": case_folder, "time_folder": time_folder, @@ -126,118 +316,137 @@ def compute_instantaneous_kla( "n_cells": n_cells, } - # Read globarVars into a python dict - # Replace all the #calc entries with their numeral values - globalVars = read_global_vars(case_folder=case_folder, cross_ref=True) - - # Check that global vars has the values we want and provide a useful error message otherwise - mw_species = {} - for species_name in species_names: - if not f"He_{species_name}" in globalVars: - err_msg = f"He_{species_name} was not found in globalVars." - err_msg += f'\nIf you add it, it should be looking like #calc "$H_{species_name}_298 * exp($DH_{species_name} *(1. / $T0 - 1./298.15))";' - raise KeyError(err_msg) - if not f"D_{species_name}" in globalVars: - err_msg = f"D_{species_name} was not found in globalVars." - err_msg += f'\nIf you add it, it should be looking like #calc "1.173e-16 * pow($WC_psi * $WC_M,0.5) * $T0 / $muMixLiq / pow($WC_V_{species_name},0.6)";' - raise KeyError(err_msg) - mw_species[species_name] = species_name_to_mw( - case_folder=case_folder, species_name=species_name - ) + kla_spec_field, field_dict = _instantaneous_kla_field( + case_folder, time_folder, species_names, n_cells, field_dict + ) - # Get liquid domain + # Volume average over the liquid ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) - - # Read all the fields - alpha_gas, field_dict = read_field( - field_name="alpha.gas", field_dict=field_dict, **kwargs + cell_volume, field_dict = read_cell_volumes( + field_dict=field_dict, **kwargs_vol ) - try: - rho_liq, field_dict = read_field( - field_name="thermo:rho.liquid", field_dict=field_dict, **kwargs - ) - except FileNotFoundError: - abs_time_path = os.path.join(case_folder, time_folder) - logger.warning( - f"thermo:rho.liquid not found in {abs_time_path}, assuming it is 1000kg/m3" + cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") + kla_spec = { + species_name: _weighted_average( + kla_spec_field[species_name], cell_volume ) - rho_liq = 1000.0 - field_dict["rho_liq"] = rho_liq - - rho_gas, field_dict = read_field( - field_name="thermo:rho.gas", field_dict=field_dict, **kwargs - ) - U_gas, field_dict = read_field( - field_name="U.gas", field_dict=field_dict, **kwargs - ) - U_liq, field_dict = read_field( - field_name="U.liquid", field_dict=field_dict, **kwargs + for species_name in species_names + } + cstar_spec, field_dict = _instantaneous_cstar( + case_folder, + time_folder, + species_names, + n_cells, + volume_time, + field_dict, ) - d_gas, field_dict = read_bubble_diameter(field_dict=field_dict, **kwargs) + return kla_spec, cstar_spec, field_dict - mu_liq, field_dict = read_mu_liquid(field_dict=field_dict, **kwargs) - species_gas = {} - for species_name in species_names: - species_gas[species_name], field_dict = read_field( - field_name=f"{species_name}.gas", field_dict=field_dict, **kwargs - ) - # Only compute over the liquid - alpha_gas = _field_filter(alpha_gas, ind=ind_liq, field_type="scalar") - alpha_liq = 1 - alpha_gas - rho_liq = _field_filter(rho_liq, ind=ind_liq, field_type="scalar") - rho_gas = _field_filter(rho_gas, ind=ind_liq, field_type="scalar") - U_gas = _field_filter(U_gas, ind=ind_liq, field_type="vector") - U_liq = _field_filter(U_liq, ind=ind_liq, field_type="vector") - d_gas = _field_filter(d_gas, ind=ind_liq, field_type="scalar") - mu_liq = _field_filter(mu_liq, ind=ind_liq, field_type="scalar") - for species_name in species_names: - species_gas[species_name] = _field_filter( - species_gas[species_name], ind=ind_liq, field_type="scalar" - ) +def compute_instantaneous_kl( + case_folder: str, + time_folder: str, + species_names: str | list[str], + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[dict, dict]: + r""" + Calculate the mass-transfer coefficient (:math:`kL_{\rm spec}`) and saturation concentration (:math:`C^*_{\rm spec}`) for a list of species from instantaneous data (rather than doing a fit over time). - # Magnitude of the slip velocity. Using the last axis keeps this valid - # whether the velocities are uniform, shape (3,), or per cell, shape (N,3) - mag_U_diff = np.linalg.norm(U_gas - U_liq, axis=-1) + :math:`kL_{\rm spec}` is the penetration-theory coefficient that + :func:`compute_instantaneous_kla` multiplies by the interfacial area + :math:`a = 6 \alpha_{\rm gas} / d_{\rm gas}` to form :math:`kLa_{\rm spec}` + (i.e. :math:`kLa_{\rm spec} = kL_{\rm spec}\, a`), volume averaged over the liquid. - # Compute kLa - Re = rho_liq * mag_U_diff * d_gas / mu_liq - kla_spec_field = {} - for species_name in species_names: - kla_spec_field[species_name] = ( - (2 / np.pi**0.5) - * 3600 - * (Re**0.5) - * (((mu_liq / rho_liq) / globalVars[f"D_{species_name}"]) ** 0.5) - * (globalVars[f"D_{species_name}"] / d_gas) - * (6.0 / d_gas) - * alpha_gas - ) - cstar_spec_field = {} - for species_name in species_names: - cstar_spec_field[species_name] = ( - rho_gas - * species_gas[species_name] - * globalVars[f"He_{species_name}"] - ) / mw_species[species_name] + .. math:: + + \frac{1}{V_{\rm liq, tot}} \int_{V_{\rm liq}} kL_{\rm spec} dV + + .. math:: - # Do volume average + kL_{\rm spec} = 3600 \sqrt{\frac{4 D_{\rm spec} |u_{\rm slip}|}{\pi d_{\rm gas}}} + + where: + - :math:`kL_{\rm spec}` is the mass transfer coefficient in :math:`m.h^{-1}` + - :math:`d_{\rm gas}` is the bubble diameter in :math:`m`. Either read from the time folder, or looked up from phaseProperties + - :math:`D_{\rm spec}` is the species molecular diffusivity in :math:`m^2.s^{-1}`. Read from globalVars + - :math:`|u_{\rm slip}|` is the magnitude of the slip velocity in :math:`m.s^{-1}`. Read from the time folder. + - :math:`V_{\rm liq}` is the volume of liquid in :math:`m^3`. Read from the time folder. + + :math:`C^*_{\rm spec}` is computed as in :func:`compute_instantaneous_kla`. + + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of time folder to analyze + species_names: str | list[str] + List of species name for which to compute kL + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + kl_spec: dict + Instantaneous volume averaged kL for each species + Keys are species names + Values are the kL values + cstar_spec: dict + Instantaneous volume averaged cstar for each species + Keys are species names + Values are the cstar values + field_dict : dict + Dictionary of fields read + """ + if field_dict is None: + field_dict = {} + if isinstance(species_names, str): + species_names = [species_names] + + kwargs = { + "case_folder": case_folder, + "time_folder": time_folder, + "n_cells": n_cells, + } + kwargs_vol = { + "case_folder": case_folder, + "time_folder": volume_time, + "n_cells": n_cells, + } + + kl_spec_field, field_dict = _instantaneous_kl_field( + case_folder, time_folder, species_names, n_cells, field_dict + ) + + # Volume average over the liquid + ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) cell_volume, field_dict = read_cell_volumes( field_dict=field_dict, **kwargs_vol ) cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") - - kla_spec = {} - cstar_spec = {} - for species_name in species_names: - kla_spec[species_name] = _weighted_average( - kla_spec_field[species_name], cell_volume + kl_spec = { + species_name: _weighted_average( + kl_spec_field[species_name], cell_volume ) - cstar_spec[species_name] = _weighted_average( - cstar_spec_field[species_name], cell_volume * alpha_liq - ) - - return kla_spec, cstar_spec, field_dict + for species_name in species_names + } + cstar_spec, field_dict = _instantaneous_cstar( + case_folder, + time_folder, + species_names, + n_cells, + volume_time, + field_dict, + ) + return kl_spec, cstar_spec, field_dict def compute_fitted_kla( @@ -386,3 +595,58 @@ def compute_fitted_kla( } return kla_spec, cstar_spec, field_dict + + +def compute_fitted_kl( + case_folder: str, + species_names: str | list[str], + n_cells: int | None = None, + volume_time: str | None = None, + num_warmup: int = 4000, + num_samples: int = 1000, + field_dict: dict | None = None, +) -> tuple[dict, dict, dict]: + r"""Fitted mass-transfer coefficient :math:`kL = kLa / a`. + + Same as :func:`compute_fitted_kla` but the fitted mean and std of each + species are divided by the interfacial area :math:`a = 6\,\epsilon / d`, + evaluated at the last time folder. + + :param case_folder: path to the case folder + :param species_names: species name(s) for which to compute kL + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param num_warmup: number of MCMC warmup samples + :param num_samples: number of posterior MCMC samples + :param field_dict: cache of already-read fields + :return: ``(kl_spec, cstar_spec, field_dict)`` with kL mean/std in :math:`m/h` + """ + if field_dict is None: + field_dict = {} + + kla_spec, cstar_spec, field_dict = compute_fitted_kla( + case_folder, + species_names, + n_cells=n_cells, + volume_time=volume_time, + num_warmup=num_warmup, + num_samples=num_samples, + field_dict=field_dict, + ) + # interfacial area at the last time folder + _, time_str_sorted = get_case_times(case_folder) + last_time = time_str_sorted[-1] + area_cache: dict = {} + gas_holdup, area_cache = compute_gas_holdup( + case_folder, last_time, n_cells, volume_time, area_cache + ) + bubble_diam, area_cache = compute_ave_bubble_diam( + case_folder, last_time, n_cells, volume_time, area_cache + ) + area = interfacial_area(gas_holdup, bubble_diam) + + kl_spec = { + species: {"mean": kla["mean"] / area, "std": kla["std"] / area} + for species, kla in kla_spec.items() + } + return kl_spec, cstar_spec, field_dict diff --git a/bird/postprocess/post_quantities/phase.py b/bird/postprocess/post_quantities/phase.py index 23e30b8c..73c5f693 100644 --- a/bird/postprocess/post_quantities/phase.py +++ b/bird/postprocess/post_quantities/phase.py @@ -157,3 +157,13 @@ def compute_ave_bubble_diam( diam = _weighted_average(d_gas, alpha_liq * cell_volume) return diam, field_dict + + +def interfacial_area(gas_holdup: float, bubble_diam: float) -> float: + r"""Gas-liquid interfacial area per unit volume :math:`a = 6\,\epsilon / d`. + + :param gas_holdup: gas holdup :math:`\epsilon` [-] + :param bubble_diam: bubble diameter :math:`d` [m] + :return: interfacial area :math:`a` [1/m] + """ + return 6.0 * gas_holdup / bubble_diam diff --git a/bird/postprocess/post_quantities/transport.py b/bird/postprocess/post_quantities/transport.py new file mode 100644 index 00000000..b2bd94a0 --- /dev/null +++ b/bird/postprocess/post_quantities/transport.py @@ -0,0 +1,79 @@ +import numpy as np + +from bird.utilities.ofio import ( + read_cell_volumes, + read_field, + read_global_vars, +) + +from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average + +# Turbulent Prandtl (= turbulent Schmidt) for the nut/Prt fallback +TURBULENT_PRANDTL = 0.85 + + +def compute_turbulent_diffusivity( + case_folder: str, + time_folder: str, + n_cells: int | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Liquid-averaged turbulent mass diffusivity. + + .. math:: + D_{\rm turb} = \frac{\alpha_t^{\rm liq}}{\rho^{\rm liq}} + + averaged over the liquid [m^2/s]. ``alphat.liquid`` already carries the + solver's turbulent Prandtl number; if it was not written, the field falls + back to :math:`\nu_t^{\rm liq} / Pr_t` with :math:`Pr_t = 0.85`. The density + is read from ``thermo:rho.liquid`` (then ``rho.liquid``), falling back to + ``rho0MixLiq`` from ``globalVars`` and then 1000. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param n_cells: number of cells (deduced from the field read if None) + :param field_dict: cache of already-read fields + :return: ``(turbulent_diffusivity, field_dict)`` + """ + if field_dict is None: + field_dict = {} + + ind_liq, field_dict = _get_ind_liq( + case_folder, time_folder, n_cells=n_cells, field_dict=field_dict + ) + cell_volume, field_dict = read_cell_volumes( + case_folder, time_folder, n_cells, field_dict + ) + + # Liquid density: field, else globalVars, else 1000 + rho_liquid = None + for rho_name in ("thermo:rho.liquid", "rho.liquid"): + try: + rho_liquid, field_dict = read_field( + case_folder, time_folder, rho_name, n_cells, field_dict + ) + break + except FileNotFoundError: + continue + if rho_liquid is None: + rho_liquid = float( + read_global_vars(case_folder).get("rho0MixLiq", 1000.0) + ) + + # Turbulent diffusivity field: alphat.liquid / rho, else nut.liquid / Prt + try: + alphat_liquid, field_dict = read_field( + case_folder, time_folder, "alphat.liquid", n_cells, field_dict + ) + diffusivity = np.asarray(alphat_liquid) / np.asarray(rho_liquid) + except FileNotFoundError: + nut_liquid, field_dict = read_field( + case_folder, time_folder, "nut.liquid", n_cells, field_dict + ) + diffusivity = np.asarray(nut_liquid) / TURBULENT_PRANDTL + if diffusivity.ndim == 0: + diffusivity = float(diffusivity) + + diffusivity = _field_filter(diffusivity, ind=ind_liq, field_type="scalar") + cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") + return _weighted_average(diffusivity, cell_volume), field_dict diff --git a/tests/postprocess/test_post_quantities.py b/tests/postprocess/test_post_quantities.py index 5dbafca8..e86e99ca 100644 --- a/tests/postprocess/test_post_quantities.py +++ b/tests/postprocess/test_post_quantities.py @@ -13,10 +13,13 @@ compute_ave_bubble_diam, compute_ave_conc_liq, compute_ave_y_liq, + compute_fitted_kl, compute_fitted_kla, compute_gas_holdup, + compute_instantaneous_kl, compute_instantaneous_kla, compute_superficial_gas_velocity, + interfacial_area, ) @@ -55,8 +58,8 @@ def test_compute_gh(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -106,8 +109,8 @@ def test_compute_diam(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -143,8 +146,8 @@ def test_compute_superficial_gas_velocity(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean/", @@ -201,8 +204,8 @@ def test__superficial_velocity_pv(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean/", @@ -232,8 +235,8 @@ def test_ave_y_liq(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -300,8 +303,8 @@ def test_ave_conc_liq(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -354,8 +357,8 @@ def test_instantaneous_kla(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -422,8 +425,8 @@ def test_fitted_kla(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -475,8 +478,8 @@ def test_get_ind_gas(): """ case_folder = os.path.join( Path(__file__).parent, - "..", - "..", + " .. ".strip(), + " .. ".strip(), "bird", "postprocess", "data_conditional_mean", @@ -518,3 +521,81 @@ def test_get_ind_gas(): # A uniform liquid field needs no filtering at all, rather than selecting # a single cell assert ind_liq_unif is None + + +def test_interfacial_area(): + """ + Test the interfacial area a = 6 * holdup / diameter + """ + assert interfacial_area(0.2, 0.005) == pytest.approx(240.0) + + +def test_instantaneous_kl(): + """ + Test for instantaneous kl calculation (volume-averaged Higbie coefficient) + """ + case_folder = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "bird", + "postprocess", + "data_conditional_mean", + ) + kl_list, cstar_list, _ = compute_instantaneous_kl( + species_names=["CO2"], + case_folder=case_folder, + time_folder="79", + volume_time="1", + ) + kl_str, _, _ = compute_instantaneous_kl( + species_names="CO2", + case_folder=case_folder, + time_folder="79", + volume_time="1", + ) + # positive, finite, and the single/list species forms agree + assert kl_list["CO2"] > 0 and np.isfinite(kl_list["CO2"]) + assert kl_str["CO2"] == pytest.approx(kl_list["CO2"]) + + kla_spec, cstar_kla, _ = compute_instantaneous_kla( + species_names=["CO2"], + case_folder=case_folder, + time_folder="79", + volume_time="1", + ) + # cstar is shared with compute_instantaneous_kla + assert cstar_list["CO2"] == pytest.approx(cstar_kla["CO2"]) + # kL (= ) and kLa (= ) are distinct quantities + assert kl_list["CO2"] != pytest.approx(kla_spec["CO2"]) + + +def test_fitted_kl(): + """ + Test for fitted kl calculation (fitted kLa / interfacial area) + """ + case_folder = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "bird", + "postprocess", + "data_conditional_mean", + ) + # dummy time folders so the fit has enough snapshots + for time_folder in [str(entry) for entry in range(81, 89)]: + shutil.copytree( + os.path.join(case_folder, "80"), + os.path.join(case_folder, time_folder), + ) + kl_spec, _, _ = compute_fitted_kl( + species_names=["CO2"], + case_folder=case_folder, + num_warmup=100, + num_samples=100, + ) + for time_folder in [str(entry) for entry in range(81, 89)]: + shutil.rmtree(os.path.join(case_folder, time_folder)) + + assert "mean" in kl_spec["CO2"] and "std" in kl_spec["CO2"] + assert np.isfinite(kl_spec["CO2"]["mean"]) diff --git a/tests/postprocess/test_transport.py b/tests/postprocess/test_transport.py new file mode 100644 index 00000000..44f2fa01 --- /dev/null +++ b/tests/postprocess/test_transport.py @@ -0,0 +1,52 @@ +import os +import tempfile + +from bird.postprocess.post_quantities import compute_turbulent_diffusivity + + +def write_scalar_case(root, fields): + """Write each {name: values} as a nonuniform scalar field in the 0 folder.""" + os.makedirs(os.path.join(root, "0"), exist_ok=True) + for name, values in fields.items(): + entries = "\n".join(f"{v:.10g}" for v in values) + with open(os.path.join(root, "0", name), "w") as f: + f.write("FoamFile\n{\n format ascii;\n") + f.write(" class volScalarField;\n") + f.write(f" object {name};\n}}\n\n") + f.write("dimensions [0 0 0 0 0 0 0];\n\n") + f.write( + "internalField nonuniform List \n" + f"{len(values)}\n(\n{entries}\n)\n;\n" + ) + + +def test_compute_turbulent_diffusivity(): + # alpha.liquid selects cells 0,1 (cell 2 is gas). D = alphat/rho = [1,2,3]; + # volume-weighted over the liquid = (1*1 + 2*1)/(1+1) = 1.5 + with tempfile.TemporaryDirectory() as tmp: + write_scalar_case( + tmp, + { + "alpha.liquid": [1.0, 1.0, 0.0], + "alphat.liquid": [2.0, 4.0, 6.0], + "rho.liquid": [2.0, 2.0, 2.0], + "V": [1.0, 1.0, 1.0], + }, + ) + d_turb, _ = compute_turbulent_diffusivity(tmp, "0") + assert abs(d_turb - 1.5) < 1e-10 + + # no alphat.liquid -> nut.liquid / Prt (0.85). nut = [0.85, 1.70] -> [1, 2] + with tempfile.TemporaryDirectory() as tmp: + write_scalar_case( + tmp, + { + "alpha.liquid": [1.0, 1.0], + "nut.liquid": [0.85, 1.70], + "rho.liquid": [1.0, 1.0], + "V": [1.0, 3.0], + }, + ) + d_fallback, _ = compute_turbulent_diffusivity(tmp, "0") + # volume-weighted (1*1 + 2*3)/(1+3) = 1.75 + assert abs(d_fallback - 1.75) < 1e-10 From 6fd4167fa6215a8e2f6178e7cadb27e6dc620765 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 17:31:57 -0600 Subject: [PATCH 43/52] Froude, Weber, Sherwood dimensionless-number helpers --- bird/postprocess/post_quantities/__init__.py | 4 ++ .../post_quantities/dimensionless.py | 43 +++++++++++++++++++ bird/postprocess/stats.py | 4 +- bird/utilities/ofio/__init__.py | 2 + bird/utilities/ofio/foam_dict_io.py | 11 +++++ tests/postprocess/test_dimensionless.py | 42 ++++++++++++++++++ 6 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 bird/postprocess/post_quantities/dimensionless.py create mode 100644 tests/postprocess/test_dimensionless.py diff --git a/bird/postprocess/post_quantities/__init__.py b/bird/postprocess/post_quantities/__init__.py index 459dc520..7569c6d3 100644 --- a/bird/postprocess/post_quantities/__init__.py +++ b/bird/postprocess/post_quantities/__init__.py @@ -5,6 +5,7 @@ _get_ind_slice, _weighted_average, ) +from .dimensionless import froude, sherwood, weber from .kla import ( compute_fitted_kl, compute_fitted_kla, @@ -40,6 +41,9 @@ "compute_loop_velocity", "compute_superficial_gas_velocity", "compute_turbulent_diffusivity", + "froude", "interfacial_area", "propose_loop_boxes_block_rect", + "sherwood", + "weber", ] diff --git a/bird/postprocess/post_quantities/dimensionless.py b/bird/postprocess/post_quantities/dimensionless.py new file mode 100644 index 00000000..8d7b9d32 --- /dev/null +++ b/bird/postprocess/post_quantities/dimensionless.py @@ -0,0 +1,43 @@ +import numpy as np + +from bird.utilities.ofio import read_gravity + + +def froude( + velocity: float, length: float, case_folder: str | None = None +) -> float: + r"""Froude number :math:`Fr = U / \sqrt{g\,L}`. + + :param velocity: characteristic velocity :math:`U` [m/s] + :param length: characteristic length :math:`L` [m] + :param case_folder: case whose ``constant/g`` sets :math:`g`; 9.81 if None + or the file is absent + :return: Froude number [-] + """ + gravity = read_gravity(case_folder) if case_folder is not None else 9.81 + return velocity / np.sqrt(gravity * length) + + +def weber( + density: float, velocity: float, length: float, surface_tension: float +) -> float: + r"""Weber number :math:`We = \rho\,U^2\,L / \sigma`. + + :param density: fluid density :math:`\rho` [kg/m3] + :param velocity: characteristic velocity :math:`U` [m/s] + :param length: characteristic length :math:`L` [m] + :param surface_tension: surface tension :math:`\sigma` [N/m] + :return: Weber number [-] + """ + return density * velocity**2 * length / surface_tension + + +def sherwood(kl: float, length: float, diffusivity: float) -> float: + r"""Sherwood number :math:`Sh = k_L\,L / D`. + + :param kl: mass-transfer coefficient :math:`k_L` [m/s] + :param length: characteristic length :math:`L` [m] + :param diffusivity: mass diffusivity :math:`D` [m2/s] + :return: Sherwood number [-] + """ + return kl * length / diffusivity diff --git a/bird/postprocess/stats.py b/bird/postprocess/stats.py index f52f6f56..c0926848 100644 --- a/bird/postprocess/stats.py +++ b/bird/postprocess/stats.py @@ -212,8 +212,8 @@ def steady_stat( if window is None: window = 0.1 * (time_values.max() - time_values.min()) - logger.warning(f"Steady state assumed over last {window}s") - + logger.warning(f"Steady state assumed over last {window}s") + in_window = time_values >= time_values.max() - window windowed_series = time_series[in_window] windowed_values = time_values[in_window] diff --git a/bird/utilities/ofio/__init__.py b/bird/utilities/ofio/__init__.py index ec90e6d5..fcdfefbc 100644 --- a/bird/utilities/ofio/__init__.py +++ b/bird/utilities/ofio/__init__.py @@ -4,6 +4,7 @@ get_case_times, ) from .foam_dict_io import ( + read_gravity, read_openfoam_dict, write_openfoam_dict, ) @@ -39,6 +40,7 @@ "read_cell_volumes", "read_field", "read_global_vars", + "read_gravity", "read_mu_liquid", "read_openfoam_dict", "read_size_groups", diff --git a/bird/utilities/ofio/foam_dict_io.py b/bird/utilities/ofio/foam_dict_io.py index fe1ebc8a..a2c94b96 100644 --- a/bird/utilities/ofio/foam_dict_io.py +++ b/bird/utilities/ofio/foam_dict_io.py @@ -1,3 +1,4 @@ +import os import re @@ -193,6 +194,16 @@ def read_openfoam_dict(filename: str) -> dict: return foam_dict +def read_gravity(case_folder: str) -> float: + """Gravity magnitude [m/s2] from constant/g; 9.81 if the file is absent.""" + try: + g_dict = read_openfoam_dict(os.path.join(case_folder, "constant", "g")) + except FileNotFoundError: + return 9.81 + gravity_vector = [float(component) for component in g_dict["value"]] + return sum(component**2 for component in gravity_vector) ** 0.5 + + def write_openfoam_dict(data: dict, filename: str, indent: int = 0) -> None: """ Save a Python dictionary back to an OpenFOAM-style file. diff --git a/tests/postprocess/test_dimensionless.py b/tests/postprocess/test_dimensionless.py new file mode 100644 index 00000000..e2428e70 --- /dev/null +++ b/tests/postprocess/test_dimensionless.py @@ -0,0 +1,42 @@ +import os +import tempfile + +import numpy as np +import pytest + +from bird.postprocess.post_quantities import froude, sherwood, weber + + +def write_gravity_case(root, gy): + """Write a minimal constant/g with vertical gravity gy.""" + os.makedirs(os.path.join(root, "constant"), exist_ok=True) + with open(os.path.join(root, "constant", "g"), "w") as f: + f.write("FoamFile\n{\n class uniformDimensionedVectorField;\n}\n") + f.write("dimensions [0 1 -2 0 0 0 0];\n") + f.write(f"value (0 {gy} 0);\n") + + +def test_froude(): + # no case -> default gravity 9.81 + assert froude(1.0, 1.0) == pytest.approx(1.0 / np.sqrt(9.81)) + + # gravity read from constant/g: Fr = 2 / sqrt(16*0.25) = 1 + with tempfile.TemporaryDirectory() as tmp: + write_gravity_case(tmp, -16.0) + assert froude(2.0, 0.25, case_folder=tmp) == pytest.approx(1.0) + + # missing constant/g -> 9.81 fallback + with tempfile.TemporaryDirectory() as tmp: + assert froude(1.0, 1.0, case_folder=tmp) == pytest.approx( + 1.0 / np.sqrt(9.81) + ) + + +def test_weber(): + # We = rho*U^2*L/sigma; 1000 * 4 * 0.5 / 100 = 20 + assert weber(1000.0, 2.0, 0.5, 100.0) == pytest.approx(20.0) + + +def test_sherwood(): + # Sh = kL*L/D; 1e-4 * 0.5 / 1e-5 = 5 + assert sherwood(1e-4, 0.5, 1e-5) == pytest.approx(5.0) From 8000938b57240113fd2f11612bb7da4d30483192 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 21:38:32 -0600 Subject: [PATCH 44/52] Add dimensionless numbers calc --- bird/postprocess/post_quantities/__init__.py | 16 ++- .../post_quantities/dimensionless.py | 126 +++++++++++++++++- bird/postprocess/post_quantities/kla.py | 21 +-- bird/postprocess/post_quantities/phase.py | 103 ++++++++++++++ bird/postprocess/post_quantities/species.py | 17 +-- bird/postprocess/post_quantities/transport.py | 24 +--- bird/utilities/ofio/__init__.py | 2 + bird/utilities/ofio/global_vars.py | 23 ++++ tests/io/test_read_foam_dict.py | 29 +++- tests/io/test_read_global_vars.py | 18 ++- tests/postprocess/test_dimensionless.py | 111 +++++++++++++-- tests/postprocess/test_post_quantities.py | 52 ++++++++ 12 files changed, 471 insertions(+), 71 deletions(-) diff --git a/bird/postprocess/post_quantities/__init__.py b/bird/postprocess/post_quantities/__init__.py index 7569c6d3..7e8be921 100644 --- a/bird/postprocess/post_quantities/__init__.py +++ b/bird/postprocess/post_quantities/__init__.py @@ -5,7 +5,14 @@ _get_ind_slice, _weighted_average, ) -from .dimensionless import froude, sherwood, weber +from .dimensionless import ( + compute_froude_number, + compute_sherwood_number, + compute_weber_number, + froude, + sherwood, + weber, +) from .kla import ( compute_fitted_kl, compute_fitted_kla, @@ -20,6 +27,8 @@ ) from .phase import ( compute_ave_bubble_diam, + compute_ave_liquid_density, + compute_ave_liquid_velocity, compute_gas_holdup, interfacial_area, ) @@ -32,15 +41,20 @@ "build_loop_direction_field_from_path", "compute_ave_bubble_diam", "compute_ave_conc_liq", + "compute_ave_liquid_density", + "compute_ave_liquid_velocity", "compute_ave_y_liq", "compute_fitted_kl", "compute_fitted_kla", + "compute_froude_number", "compute_gas_holdup", "compute_instantaneous_kl", "compute_instantaneous_kla", "compute_loop_velocity", + "compute_sherwood_number", "compute_superficial_gas_velocity", "compute_turbulent_diffusivity", + "compute_weber_number", "froude", "interfacial_area", "propose_loop_boxes_block_rect", diff --git a/bird/postprocess/post_quantities/dimensionless.py b/bird/postprocess/post_quantities/dimensionless.py index 8d7b9d32..2d5876f9 100644 --- a/bird/postprocess/post_quantities/dimensionless.py +++ b/bird/postprocess/post_quantities/dimensionless.py @@ -1,20 +1,23 @@ import numpy as np -from bird.utilities.ofio import read_gravity +from bird.utilities.ofio import ( + read_global_vars, + read_gravity, + read_surface_tension, +) +from .kla import compute_instantaneous_kl +from .phase import compute_ave_liquid_density, compute_ave_liquid_velocity -def froude( - velocity: float, length: float, case_folder: str | None = None -) -> float: + +def froude(velocity: float, length: float, gravity: float = 9.81) -> float: r"""Froude number :math:`Fr = U / \sqrt{g\,L}`. :param velocity: characteristic velocity :math:`U` [m/s] :param length: characteristic length :math:`L` [m] - :param case_folder: case whose ``constant/g`` sets :math:`g`; 9.81 if None - or the file is absent + :param gravity: gravitational acceleration :math:`g` [m/s2] :return: Froude number [-] """ - gravity = read_gravity(case_folder) if case_folder is not None else 9.81 return velocity / np.sqrt(gravity * length) @@ -41,3 +44,112 @@ def sherwood(kl: float, length: float, diffusivity: float) -> float: :return: Sherwood number [-] """ return kl * length / diffusivity + + +def compute_froude_number( + case_folder: str, + time_folder: str, + length: float, + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Froude number from the liquid-averaged velocity and a given length. + + :math:`Fr = U / \sqrt{g L}` with :math:`U` the liquid-volume-averaged + :math:`|U_{\rm liq}|` at ``time_folder``, :math:`g` from ``constant/g``, and + :math:`L` the passed length. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param length: characteristic length :math:`L` [m] + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(froude_number, field_dict)`` + """ + if field_dict is None: + field_dict = {} + velocity, field_dict = compute_ave_liquid_velocity( + case_folder, time_folder, n_cells, volume_time, field_dict + ) + gravity = read_gravity(case_folder) + return froude(velocity, length, gravity=gravity), field_dict + + +def compute_weber_number( + case_folder: str, + time_folder: str, + length: float, + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Weber number from the liquid-averaged velocity/density and a given length. + + :math:`We = \rho U^2 L / \sigma` with :math:`U` and :math:`\rho` the + liquid-volume-averaged velocity magnitude and density at ``time_folder``, + :math:`\sigma` from ``constant/phaseProperties``, and :math:`L` the passed + length. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param length: characteristic length :math:`L` [m] + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(weber_number, field_dict)`` + """ + if field_dict is None: + field_dict = {} + velocity, field_dict = compute_ave_liquid_velocity( + case_folder, time_folder, n_cells, volume_time, field_dict + ) + density, field_dict = compute_ave_liquid_density( + case_folder, time_folder, n_cells, volume_time, field_dict + ) + surface_tension = read_surface_tension(case_folder) + return weber(density, velocity, length, surface_tension), field_dict + + +def compute_sherwood_number( + case_folder: str, + time_folder: str, + length: float, + species_name: str, + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Sherwood number for one species from the instantaneous kL. + + :math:`Sh = k_L L / D` with :math:`k_L` from + :func:`compute_instantaneous_kl` at ``time_folder`` and the molecular + diffusivity :math:`D` read as ``D_`` from globalVars (the standard + Sherwood definition; the turbulent contribution is deliberately excluded). + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param length: characteristic length :math:`L` [m] + :param species_name: species for which to compute kL and use D_ + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(sherwood_number, field_dict)`` + """ + if field_dict is None: + field_dict = {} + kl_spec, _, field_dict = compute_instantaneous_kl( + case_folder, + time_folder, + species_name, + n_cells=n_cells, + volume_time=volume_time, + field_dict=field_dict, + ) + diffusivity = float( + read_global_vars(case_folder=case_folder, cross_ref=True)[ + f"D_{species_name}" + ] + ) + return sherwood(kl_spec[species_name], length, diffusivity), field_dict diff --git a/bird/postprocess/post_quantities/kla.py b/bird/postprocess/post_quantities/kla.py index 67e2ca50..3b3e9caa 100644 --- a/bird/postprocess/post_quantities/kla.py +++ b/bird/postprocess/post_quantities/kla.py @@ -1,5 +1,3 @@ -import os - import numpy as np from bird import logger @@ -17,6 +15,7 @@ from ..kla_utils import compute_kla from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average from .phase import ( + _read_liquid_density_field, compute_ave_bubble_diam, compute_gas_holdup, interfacial_area, @@ -45,17 +44,9 @@ def _instantaneous_kl_field( globalVars = read_global_vars(case_folder=case_folder, cross_ref=True) ind_liq, field_dict = _get_ind_liq(field_dict=field_dict, **kwargs) - try: - rho_liq, field_dict = read_field( - field_name="thermo:rho.liquid", field_dict=field_dict, **kwargs - ) - except FileNotFoundError: - logger.warning( - f"thermo:rho.liquid not found in " - f"{os.path.join(case_folder, time_folder)}, assuming 1000kg/m3" - ) - rho_liq = 1000.0 - field_dict["rho_liq"] = rho_liq + rho_liq, field_dict = _read_liquid_density_field( + case_folder, time_folder, n_cells, field_dict + ) U_gas, field_dict = read_field( field_name="U.gas", field_dict=field_dict, **kwargs ) @@ -526,10 +517,6 @@ def compute_fitted_kla( # Get all the time folders time_float_sorted, time_str_sorted = get_case_times(case_folder) - # Read globarVars into a python dict - # Replace all the #calc entries with their numeral values - globalVars = read_global_vars(case_folder=case_folder, cross_ref=True) - # Get Mw of the species mw_species = {} for species_name in species_names: diff --git a/bird/postprocess/post_quantities/phase.py b/bird/postprocess/post_quantities/phase.py index 73c5f693..44617513 100644 --- a/bird/postprocess/post_quantities/phase.py +++ b/bird/postprocess/post_quantities/phase.py @@ -1,12 +1,42 @@ +import os + +import numpy as np + +from bird import logger from bird.utilities.ofio import ( read_bubble_diameter, read_cell_volumes, read_field, + read_global_vars, ) from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average +def _read_liquid_density_field( + case_folder: str, + time_folder: str, + n_cells: int | None, + field_dict: dict, +) -> tuple[np.ndarray | float, dict]: + """Liquid density field: thermo:rho.liquid, then rho.liquid; if neither is + written, globalVars rho0MixLiq (then 1000).""" + for rho_name in ("thermo:rho.liquid", "rho.liquid"): + try: + rho_liquid, field_dict = read_field( + case_folder, time_folder, rho_name, n_cells, field_dict + ) + return rho_liquid, field_dict + except FileNotFoundError: + continue + rho0 = float(read_global_vars(case_folder).get("rho0MixLiq", 1000.0)) + logger.warning( + f"No liquid density field in " + f"{os.path.join(case_folder, time_folder)}, assuming {rho0} kg/m3" + ) + return rho0, field_dict + + def compute_gas_holdup( case_folder: str, time_folder: str, @@ -167,3 +197,76 @@ def interfacial_area(gas_holdup: float, bubble_diam: float) -> float: :return: interfacial area :math:`a` [1/m] """ return 6.0 * gas_holdup / bubble_diam + + +def compute_ave_liquid_density( + case_folder: str, + time_folder: str, + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Volume-averaged liquid density over the liquid. + + Reads ``thermo:rho.liquid`` (then ``rho.liquid``); returns 1000 kg/m3 if + neither field is written. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(density, field_dict)`` + """ + if field_dict is None: + field_dict = {} + + ind_liq, field_dict = _get_ind_liq( + case_folder, time_folder, n_cells=n_cells, field_dict=field_dict + ) + rho_liquid, field_dict = _read_liquid_density_field( + case_folder, time_folder, n_cells, field_dict + ) + cell_volume, field_dict = read_cell_volumes( + case_folder, volume_time, n_cells, field_dict + ) + rho_liquid = _field_filter(rho_liquid, ind=ind_liq, field_type="scalar") + cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") + return _weighted_average(rho_liquid, cell_volume), field_dict + + +def compute_ave_liquid_velocity( + case_folder: str, + time_folder: str, + n_cells: int | None = None, + volume_time: str | None = None, + field_dict: dict | None = None, +) -> tuple[float, dict]: + r"""Volume-averaged liquid velocity magnitude :math:`|U_{\rm liq}|` over the liquid. + + :param case_folder: path to the case folder + :param time_folder: name of the time folder to analyze + :param n_cells: number of cells (deduced from the field read if None) + :param volume_time: time folder for the cell volumes (auto if None) + :param field_dict: cache of already-read fields + :return: ``(velocity_magnitude, field_dict)`` + """ + if field_dict is None: + field_dict = {} + + ind_liq, field_dict = _get_ind_liq( + case_folder, time_folder, n_cells=n_cells, field_dict=field_dict + ) + u_liquid, field_dict = read_field( + case_folder, time_folder, "U.liquid", n_cells, field_dict + ) + cell_volume, field_dict = read_cell_volumes( + case_folder, volume_time, n_cells, field_dict + ) + if np.ndim(u_liquid) == 1: # uniform field, shape (3,) + u_magnitude = float(np.linalg.norm(u_liquid)) + else: + u_magnitude = np.linalg.norm(u_liquid, axis=1) + u_magnitude = _field_filter(u_magnitude, ind=ind_liq, field_type="scalar") + cell_volume = _field_filter(cell_volume, ind=ind_liq, field_type="scalar") + return _weighted_average(u_magnitude, cell_volume), field_dict diff --git a/bird/postprocess/post_quantities/species.py b/bird/postprocess/post_quantities/species.py index a3f8da37..476cfb0c 100644 --- a/bird/postprocess/post_quantities/species.py +++ b/bird/postprocess/post_quantities/species.py @@ -1,5 +1,3 @@ -import os - from bird import logger from bird.utilities.ofio import ( read_cell_volumes, @@ -8,6 +6,7 @@ ) from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average +from .phase import _read_liquid_density_field def compute_ave_y_liq( @@ -168,17 +167,9 @@ def compute_ave_conc_liq( cell_volume, field_dict = read_cell_volumes( field_dict=field_dict, **kwargs_vol ) - try: - rho_liq, field_dict = read_field( - field_name="thermo:rho.liquid", field_dict=field_dict, **kwargs - ) - except FileNotFoundError: - abs_time_path = os.path.join(case_folder, time_folder) - logger.warning( - f"thermo:rho.liquid not found in {abs_time_path}, assuming it is 1000kg/m3" - ) - rho_liq = 1000.0 - field_dict["rho_liq"] = rho_liq + rho_liq, field_dict = _read_liquid_density_field( + case_folder, time_folder, n_cells, field_dict + ) # Only compute over the liquid alpha_liq = _field_filter(alpha_liq, ind=ind_liq, field_type="scalar") diff --git a/bird/postprocess/post_quantities/transport.py b/bird/postprocess/post_quantities/transport.py index b2bd94a0..57fc077d 100644 --- a/bird/postprocess/post_quantities/transport.py +++ b/bird/postprocess/post_quantities/transport.py @@ -1,12 +1,9 @@ import numpy as np -from bird.utilities.ofio import ( - read_cell_volumes, - read_field, - read_global_vars, -) +from bird.utilities.ofio import read_cell_volumes, read_field from ._cell_filter import _field_filter, _get_ind_liq, _weighted_average +from .phase import _read_liquid_density_field # Turbulent Prandtl (= turbulent Schmidt) for the nut/Prt fallback TURBULENT_PRANDTL = 0.85 @@ -45,20 +42,9 @@ def compute_turbulent_diffusivity( case_folder, time_folder, n_cells, field_dict ) - # Liquid density: field, else globalVars, else 1000 - rho_liquid = None - for rho_name in ("thermo:rho.liquid", "rho.liquid"): - try: - rho_liquid, field_dict = read_field( - case_folder, time_folder, rho_name, n_cells, field_dict - ) - break - except FileNotFoundError: - continue - if rho_liquid is None: - rho_liquid = float( - read_global_vars(case_folder).get("rho0MixLiq", 1000.0) - ) + rho_liquid, field_dict = _read_liquid_density_field( + case_folder, time_folder, n_cells, field_dict + ) # Turbulent diffusivity field: alphat.liquid / rho, else nut.liquid / Prt try: diff --git a/bird/utilities/ofio/__init__.py b/bird/utilities/ofio/__init__.py index fcdfefbc..66618409 100644 --- a/bird/utilities/ofio/__init__.py +++ b/bird/utilities/ofio/__init__.py @@ -25,6 +25,7 @@ ) from .global_vars import ( read_global_vars, + read_surface_tension, ) from .thermo import ( get_species_name, @@ -45,6 +46,7 @@ "read_openfoam_dict", "read_size_groups", "read_surface_field_value", + "read_surface_tension", "species_name_to_mw", "write_openfoam_dict", ] diff --git a/bird/utilities/ofio/global_vars.py b/bird/utilities/ofio/global_vars.py index ec2f9bd0..eb3fdfc4 100644 --- a/bird/utilities/ofio/global_vars.py +++ b/bird/utilities/ofio/global_vars.py @@ -6,6 +6,8 @@ from bird import logger +from .foam_dict_io import read_openfoam_dict + def _cross_reference_math(expr): """ @@ -207,3 +209,24 @@ def read_global_vars( globalVars_dict = _cross_reference_global_vars(globalVars_dict) return globalVars_dict + + +def read_surface_tension(case_folder: str) -> float: + """Surface tension [N/m] from constant/phaseProperties. + + Resolves a ``$var`` reference (e.g. ``sigma $sigmaLiq;``) against globalVars. + """ + phase_properties = read_openfoam_dict( + os.path.join(case_folder, "constant", "phaseProperties") + ) + sigma = None + for entry in phase_properties["surfaceTension"].values(): + if isinstance(entry, dict) and "sigma" in entry: + sigma = entry["sigma"] + break + if sigma is None: + raise KeyError("No sigma found in surfaceTension of phaseProperties") + + if isinstance(sigma, str) and sigma.startswith("$"): + return float(read_global_vars(case_folder, cross_ref=True)[sigma[1:]]) + return float(sigma) diff --git a/tests/io/test_read_foam_dict.py b/tests/io/test_read_foam_dict.py index e8692b92..16451d52 100644 --- a/tests/io/test_read_foam_dict.py +++ b/tests/io/test_read_foam_dict.py @@ -1,9 +1,36 @@ import os +import tempfile from pathlib import Path import numpy as np -from bird.utilities.ofio import read_openfoam_dict +from bird.utilities.ofio import read_gravity, read_openfoam_dict + + +def test_read_gravity(): + """ + Test reading gravity magnitude from `constant/g`, with a 9.81 fallback + """ + case_folder = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "tutorial_cases", + "OF9", + "loop_reactor_mixing_swirl", + ) + assert read_gravity(case_folder) == 9.81 + + # custom vertical gravity + with tempfile.TemporaryDirectory() as tmp: + os.makedirs(os.path.join(tmp, "constant")) + with open(os.path.join(tmp, "constant", "g"), "w") as f: + f.write("dimensions [0 1 -2 0 0 0 0];\nvalue (0 -3.0 0);\n") + assert read_gravity(tmp) == 3.0 + + # missing constant/g -> 9.81 fallback + with tempfile.TemporaryDirectory() as tmp: + assert read_gravity(tmp) == 9.81 def test_read_phaseProperties(): diff --git a/tests/io/test_read_global_vars.py b/tests/io/test_read_global_vars.py index 8fb689d2..85adba8e 100644 --- a/tests/io/test_read_global_vars.py +++ b/tests/io/test_read_global_vars.py @@ -3,7 +3,23 @@ import numpy as np -from bird.utilities.ofio import read_global_vars +from bird.utilities.ofio import read_global_vars, read_surface_tension + + +def test_read_surface_tension(): + """ + Test backing surface tension out of `constant/phaseProperties` + """ + case_folder = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "tutorial_cases", + "OF9", + "loop_reactor_mixing_swirl", + ) + # sigma is `$sigmaLiq` in phaseProperties, resolved via globalVars + assert read_surface_tension(case_folder) == 0.07 def test_read_global_vars(): diff --git a/tests/postprocess/test_dimensionless.py b/tests/postprocess/test_dimensionless.py index e2428e70..4400975e 100644 --- a/tests/postprocess/test_dimensionless.py +++ b/tests/postprocess/test_dimensionless.py @@ -1,10 +1,20 @@ import os import tempfile +from pathlib import Path import numpy as np import pytest -from bird.postprocess.post_quantities import froude, sherwood, weber +from bird.postprocess.post_quantities import ( + compute_froude_number, + compute_instantaneous_kl, + compute_sherwood_number, + compute_weber_number, + froude, + sherwood, + weber, +) +from bird.utilities.ofio import read_global_vars def write_gravity_case(root, gy): @@ -16,20 +26,52 @@ def write_gravity_case(root, gy): f.write(f"value (0 {gy} 0);\n") -def test_froude(): - # no case -> default gravity 9.81 - assert froude(1.0, 1.0) == pytest.approx(1.0 / np.sqrt(9.81)) +def write_dimensionless_case(root, u_x, rho, sigma, cell_volumes): + """Case with uniform U.liquid=(u_x,0,0), rho, all-liquid, and sigma.""" + os.makedirs(os.path.join(root, "0"), exist_ok=True) + os.makedirs(os.path.join(root, "constant"), exist_ok=True) - # gravity read from constant/g: Fr = 2 / sqrt(16*0.25) = 1 - with tempfile.TemporaryDirectory() as tmp: - write_gravity_case(tmp, -16.0) - assert froude(2.0, 0.25, case_folder=tmp) == pytest.approx(1.0) + def write_field(name, foam_class, body): + with open(os.path.join(root, "0", name), "w") as f: + f.write("FoamFile\n{\n format ascii;\n") + f.write(f" class {foam_class};\n") + f.write(f" object {name};\n}}\n\n") + f.write("dimensions [0 0 0 0 0 0 0];\n\n") + f.write(body) - # missing constant/g -> 9.81 fallback - with tempfile.TemporaryDirectory() as tmp: - assert froude(1.0, 1.0, case_folder=tmp) == pytest.approx( - 1.0 / np.sqrt(9.81) + entries = "\n".join(f"{v:.10g}" for v in cell_volumes) + write_field( + "V", + "volScalarField", + "internalField nonuniform List \n" + f"{len(cell_volumes)}\n(\n{entries}\n)\n;\n", + ) + write_field( + "alpha.liquid", "volScalarField", "internalField uniform 1;\n" + ) + write_field( + "U.liquid", + "volVectorField", + f"internalField uniform ({u_x} 0 0);\n", + ) + write_field( + "thermo:rho.liquid", + "volScalarField", + f"internalField uniform {rho};\n", + ) + with open(os.path.join(root, "constant", "phaseProperties"), "w") as f: + f.write("surfaceTension\n(\n (gas and liquid)\n {\n") + f.write( + f" type constant;\n sigma {sigma};\n" ) + f.write(" }\n);\n") + + +def test_froude(): + # default gravity 9.81 + assert froude(1.0, 1.0) == pytest.approx(1.0 / np.sqrt(9.81)) + # Fr = U / sqrt(g*L); 2 / sqrt(16*0.25) = 1 + assert froude(2.0, 0.25, gravity=16.0) == pytest.approx(1.0) def test_weber(): @@ -40,3 +82,48 @@ def test_weber(): def test_sherwood(): # Sh = kL*L/D; 1e-4 * 0.5 / 1e-5 = 5 assert sherwood(1e-4, 0.5, 1e-5) == pytest.approx(5.0) + + +def test_compute_froude_number(): + # velocity = |U.liquid| = 3, g = 9 -> Fr = 3 / sqrt(9*0.25) = 2 + with tempfile.TemporaryDirectory() as tmp: + write_dimensionless_case( + tmp, u_x=3.0, rho=1000.0, sigma=0.05, cell_volumes=[1.0, 2.0, 3.0] + ) + write_gravity_case(tmp, -9.0) + fr, _ = compute_froude_number(tmp, "0", length=0.25, volume_time="0") + assert fr == pytest.approx(2.0) + + +def test_compute_weber_number(): + # We = rho*U^2*L/sigma = 1000 * 9 * 0.2 / 0.05 = 36000 + with tempfile.TemporaryDirectory() as tmp: + write_dimensionless_case( + tmp, u_x=3.0, rho=1000.0, sigma=0.05, cell_volumes=[1.0, 2.0, 3.0] + ) + we, _ = compute_weber_number(tmp, "0", length=0.2, volume_time="0") + assert we == pytest.approx(1000.0 * 9.0 * 0.2 / 0.05) + + +def test_compute_sherwood_number(): + case_folder = os.path.join( + Path(__file__).parent, + " .. ".strip(), + " .. ".strip(), + "bird", + "postprocess", + "data_conditional_mean", + ) + # Sh = kL * L / D_molecular, with kL from compute_instantaneous_kl and + # D_CO2 read from globalVars + kl_spec, _, _ = compute_instantaneous_kl( + species_names="CO2", + case_folder=case_folder, + time_folder="80", + volume_time="1", + ) + diffusivity = float(read_global_vars(case_folder)["D_CO2"]) + sh, _ = compute_sherwood_number( + case_folder, "80", length=0.1, species_name="CO2", volume_time="1" + ) + assert sh == pytest.approx(kl_spec["CO2"] * 0.1 / diffusivity) diff --git a/tests/postprocess/test_post_quantities.py b/tests/postprocess/test_post_quantities.py index e86e99ca..65ab255f 100644 --- a/tests/postprocess/test_post_quantities.py +++ b/tests/postprocess/test_post_quantities.py @@ -12,6 +12,8 @@ _get_ind_liq, compute_ave_bubble_diam, compute_ave_conc_liq, + compute_ave_liquid_density, + compute_ave_liquid_velocity, compute_ave_y_liq, compute_fitted_kl, compute_fitted_kla, @@ -523,6 +525,56 @@ def test_get_ind_gas(): assert ind_liq_unif is None +def _write_liquid_fields(root, u_vector, rho, cell_volumes): + """Minimal case: all-liquid, uniform U.liquid and rho, nonuniform V.""" + os.makedirs(os.path.join(root, "0"), exist_ok=True) + + def write_field(name, foam_class, body): + with open(os.path.join(root, "0", name), "w") as f: + f.write("FoamFile\n{\n format ascii;\n") + f.write(f" class {foam_class};\n") + f.write(f" object {name};\n}}\n\n") + f.write("dimensions [0 0 0 0 0 0 0];\n\n") + f.write(body) + + entries = "\n".join(f"{v:.10g}" for v in cell_volumes) + write_field( + "V", + "volScalarField", + "internalField nonuniform List \n" + f"{len(cell_volumes)}\n(\n{entries}\n)\n;\n", + ) + write_field( + "alpha.liquid", "volScalarField", "internalField uniform 1;\n" + ) + write_field( + "U.liquid", + "volVectorField", + f"internalField uniform ({u_vector[0]} {u_vector[1]} " + f"{u_vector[2]});\n", + ) + write_field( + "thermo:rho.liquid", + "volScalarField", + f"internalField uniform {rho};\n", + ) + + +def test_compute_ave_liquid_density(): + with tempfile.TemporaryDirectory() as tmp: + _write_liquid_fields(tmp, (1.0, 0.0, 0.0), 1050.0, [1.0, 2.0, 3.0]) + rho, _ = compute_ave_liquid_density(tmp, "0", volume_time="0") + assert rho == pytest.approx(1050.0) + + +def test_compute_ave_liquid_velocity(): + # |U.liquid| = |(3,4,0)| = 5 + with tempfile.TemporaryDirectory() as tmp: + _write_liquid_fields(tmp, (3.0, 4.0, 0.0), 1000.0, [1.0, 2.0, 3.0]) + velocity, _ = compute_ave_liquid_velocity(tmp, "0", volume_time="0") + assert velocity == pytest.approx(5.0) + + def test_interfacial_area(): """ Test the interfacial area a = 6 * holdup / diameter From 6c55e3b646508a91f9fe776c21c03b31d9a07b44 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 21:41:30 -0600 Subject: [PATCH 45/52] needed for reproducing the loop res --- .../SA_optimization/plot_design_schematic.py | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 papers/scaleup/SA_optimization/plot_design_schematic.py diff --git a/papers/scaleup/SA_optimization/plot_design_schematic.py b/papers/scaleup/SA_optimization/plot_design_schematic.py new file mode 100644 index 00000000..60677ac6 --- /dev/null +++ b/papers/scaleup/SA_optimization/plot_design_schematic.py @@ -0,0 +1,121 @@ +import argparse + +import numpy as np +import pandas as pd +from matplotlib.lines import Line2D +from matplotlib.patches import Circle +from prettyPlot.plotting import plt + +# fraction-along-branch of each spot (matches randsim.optimization_setup) +BRANCH_SPOTS = { + 0: np.linspace(0.2, 0.8, 4), + 1: np.linspace(0.2, 0.8, 3), + 2: np.linspace(0.2, 0.8, 4), +} + +# bottom-face leg endpoints in (x, z) block coords (matches mesh.json Fluids) +BRANCH_ENDS = { + 0: ((0.0, 0.0), (9.0, 0.0)), + 1: ((9.0, 0.0), (9.0, 4.0)), + 2: ((9.0, 4.0), (0.0, 4.0)), +} + +CHOICE_COLOR = {1: "tab:blue", 0: "red", 2: "black"} +CHOICE_NAME = {1: "Sparger", 0: "Mixer", 2: "Wall"} + + +def spot_positions() -> list[tuple[float, float]]: + """(x, z) of the 11 spots, ordered as the design vector [b0, b1, b2].""" + positions = [] + for branch_id in (0, 1, 2): + (start_x, start_z), (end_x, end_z) = BRANCH_ENDS[branch_id] + for frac in BRANCH_SPOTS[branch_id]: + positions.append( + ( + start_x + frac * (end_x - start_x), + start_z + frac * (end_z - start_z), + ) + ) + return positions + + +def plot_schematic( + design_x: np.ndarray, out_path: str, title: str | None = None +) -> None: + """Draw the bottom-face schematic for one design vector (length 11).""" + design_x = np.asarray(design_x, dtype=int) + if len(design_x) != 11: + raise ValueError(f"expected 11 design values, got {len(design_x)}") + positions = spot_positions() + + fig, ax = plt.subplots(figsize=(7, 4)) + # legs as thick rounded grey lines (the tube centerlines) + for branch_id in (0, 1, 2): + (start_x, start_z), (end_x, end_z) = BRANCH_ENDS[branch_id] + ax.plot( + [start_x, end_x], + [start_z, end_z], + color="lightgray", + linewidth=16, + solid_capstyle="round", + zorder=1, + ) + # placement spots + for (spot_x, spot_z), choice in zip(positions, design_x): + ax.add_patch( + Circle( + (spot_x, spot_z), + 0.32, + facecolor=CHOICE_COLOR[int(choice)], + edgecolor="k", + linewidth=1.2, + zorder=3, + ) + ) + + ax.set_aspect("equal") + ax.axis("off") + ax.set_xlim(-1.0, 10.0) + ax.set_ylim(-1.5, 5.5) + legend_handles = [ + Line2D( + [0], + [0], + marker="o", + color="w", + markerfacecolor=CHOICE_COLOR[choice], + markeredgecolor="k", + markersize=12, + label=CHOICE_NAME[choice], + ) + for choice in (1, 0, 2) + ] + # place the legend in the open interior of the U so it clears the legs + ax.legend(handles=legend_handles, loc="center", frameon=False) + if title is not None: + ax.set_title(title, fontsize=13) + + fig.savefig(f"{out_path}.png", dpi=200, bbox_inches="tight") + fig.savefig(f"{out_path}.pdf", bbox_inches="tight") + plt.close(fig) + + +def design_from_csv(csv_path: str) -> np.ndarray: + """Read x0..x10 from a best_bootstrap_solution CSV.""" + row = pd.read_csv(csv_path).iloc[0] + return np.array([int(row[f"x{i}"]) for i in range(11)]) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Plot a design schematic") + parser.add_argument( + "-i", "--input", required=True, help="best_bootstrap_solution CSV" + ) + parser.add_argument( + "-o", "--out", default="optimum_schematic", help="output path (no ext)" + ) + parser.add_argument("-t", "--title", default=None) + args = parser.parse_args() + + plot_schematic(design_from_csv(args.input), args.out, title=args.title) + print(f"Wrote {args.out}.png / .pdf") From 8d56542ffa3921da21831e12b2c46d8753ba5624 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 10 Sep 2026 22:31:13 -0600 Subject: [PATCH 46/52] format --- bird/version.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bird/version.py b/bird/version.py index 8c4425e3..30aea71c 100644 --- a/bird/version.py +++ b/bird/version.py @@ -1,4 +1,3 @@ """Bio reactor design version""" __version__ = "0.0.58" - From 09fd47e2f48569f5853159e431812b3e32fb68c3 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:22:01 -0600 Subject: [PATCH 47/52] fix units for dimensionless sherwood --- bird/postprocess/post_quantities/dimensionless.py | 5 ++++- bird/postprocess/post_quantities/kla.py | 14 +++++++------- tests/postprocess/test_dimensionless.py | 5 +++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/bird/postprocess/post_quantities/dimensionless.py b/bird/postprocess/post_quantities/dimensionless.py index 2d5876f9..f42d3f9e 100644 --- a/bird/postprocess/post_quantities/dimensionless.py +++ b/bird/postprocess/post_quantities/dimensionless.py @@ -152,4 +152,7 @@ def compute_sherwood_number( f"D_{species_name}" ] ) - return sherwood(kl_spec[species_name], length, diffusivity), field_dict + # kL from compute_instantaneous_kl is in m/h, but D is in m2/s, so kL must + # be converted back to m/s for Sh to come out dimensionless. + kl_m_per_s = kl_spec[species_name] / 3600 + return sherwood(kl_m_per_s, length, diffusivity), field_dict diff --git a/bird/postprocess/post_quantities/kla.py b/bird/postprocess/post_quantities/kla.py index 3b3e9caa..29b5d66a 100644 --- a/bird/postprocess/post_quantities/kla.py +++ b/bird/postprocess/post_quantities/kla.py @@ -281,11 +281,11 @@ def compute_instantaneous_kla( Returns ---------- kla_spec: dict - Instantaneous volume averaged kLa for each species + Instantaneous volume averaged kLa for each species, in h^-1 Keys are species names Values are the kLa values cstar_spec: dict - Instantaneous volume averaged cstar for each species + Instantaneous volume averaged cstar for each species, in mol.m^-3 Keys are species names Values are the cstar values field_dict : dict @@ -387,11 +387,11 @@ def compute_instantaneous_kl( Returns ---------- kl_spec: dict - Instantaneous volume averaged kL for each species + Instantaneous volume averaged kL for each species, in m.h^-1 Keys are species names Values are the kL values cstar_spec: dict - Instantaneous volume averaged cstar for each species + Instantaneous volume averaged cstar for each species, in mol.m^-3 Keys are species names Values are the cstar values field_dict : dict @@ -491,11 +491,11 @@ def compute_fitted_kla( Returns ---------- kla_spec: dict - Instantaneous volume averaged kLa for each species + Instantaneous volume averaged kLa for each species, in h^-1 Keys are species names Values are dictionaries with key 'mean' (mean kLa value) and 'std' (1 standard deviation for the kLa value) cstar_spec: dict - Instantaneous volume averaged cstar for each species + Instantaneous volume averaged cstar for each species, in mol.m^-3 Keys are species names Values are dictionaries with key 'mean' (mean cstar value) and 'std' (1 standard deviation for the cstar value) field_dict : dict @@ -606,7 +606,7 @@ def compute_fitted_kl( :param num_warmup: number of MCMC warmup samples :param num_samples: number of posterior MCMC samples :param field_dict: cache of already-read fields - :return: ``(kl_spec, cstar_spec, field_dict)`` with kL mean/std in :math:`m/h` + :return: ``(kl_spec, cstar_spec, field_dict)`` with kL mean/std in :math:`m.h^{-1}` and cstar mean/std in :math:`mol.m^{-3}` """ if field_dict is None: field_dict = {} diff --git a/tests/postprocess/test_dimensionless.py b/tests/postprocess/test_dimensionless.py index 4400975e..68a35784 100644 --- a/tests/postprocess/test_dimensionless.py +++ b/tests/postprocess/test_dimensionless.py @@ -115,7 +115,8 @@ def test_compute_sherwood_number(): "data_conditional_mean", ) # Sh = kL * L / D_molecular, with kL from compute_instantaneous_kl and - # D_CO2 read from globalVars + # D_CO2 read from globalVars. kL is in m/h and D in m2/s, so kL is + # converted to m/s (/3600) for Sh to be dimensionless. kl_spec, _, _ = compute_instantaneous_kl( species_names="CO2", case_folder=case_folder, @@ -126,4 +127,4 @@ def test_compute_sherwood_number(): sh, _ = compute_sherwood_number( case_folder, "80", length=0.1, species_name="CO2", volume_time="1" ) - assert sh == pytest.approx(kl_spec["CO2"] * 0.1 / diffusivity) + assert sh == pytest.approx((kl_spec["CO2"] / 3600) * 0.1 / diffusivity) From a9cd43e21e25e06f4bd55a5864900ac8068f749c Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:24:39 -0600 Subject: [PATCH 48/52] safe globalvar read --- bird/postprocess/post_quantities/phase.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bird/postprocess/post_quantities/phase.py b/bird/postprocess/post_quantities/phase.py index 44617513..108abcf7 100644 --- a/bird/postprocess/post_quantities/phase.py +++ b/bird/postprocess/post_quantities/phase.py @@ -29,7 +29,10 @@ def _read_liquid_density_field( return rho_liquid, field_dict except FileNotFoundError: continue - rho0 = float(read_global_vars(case_folder).get("rho0MixLiq", 1000.0)) + try: + rho0 = float(read_global_vars(case_folder).get("rho0MixLiq", 1000.0)) + except FileNotFoundError: + rho0 = 1000.0 logger.warning( f"No liquid density field in " f"{os.path.join(case_folder, time_folder)}, assuming {rho0} kg/m3" From 3fa0857307860293477fbd12da91a92fb062505e Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:27:13 -0600 Subject: [PATCH 49/52] Robust stats --- bird/postprocess/stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bird/postprocess/stats.py b/bird/postprocess/stats.py index c0926848..16c3f508 100644 --- a/bird/postprocess/stats.py +++ b/bird/postprocess/stats.py @@ -219,7 +219,7 @@ def steady_stat( windowed_values = time_values[in_window] if np.all(np.isnan(windowed_series)): return np.nan, np.nan - if windowed_series.size < 2: + if windowed_series.size < 2 or np.all(windowed_series == windowed_series[0]): return float(windowed_series[0]), 0.0 mean_value, uncertainty_95 = calc_mean(windowed_series, windowed_values) From b93239ad1781e00df099ced7052849f512f277b0 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:42:28 -0600 Subject: [PATCH 50/52] fix docstrings --- .../post_quantities/dimensionless.py | 147 +++++++++++++----- bird/postprocess/post_quantities/kla.py | 53 +++++-- .../post_quantities/loop_velocity.py | 76 ++++++--- bird/postprocess/post_quantities/phase.py | 68 ++++++-- bird/postprocess/post_quantities/transport.py | 23 ++- bird/postprocess/stats.py | 21 ++- bird/preprocess/dynamic_mixer/io_fvModels.py | 21 ++- bird/preprocess/dynamic_mixer/mixer.py | 24 +-- bird/preprocess/json_gen/design_io.py | 7 +- bird/preprocess/json_gen/generate_designs.py | 35 +++-- 10 files changed, 354 insertions(+), 121 deletions(-) diff --git a/bird/postprocess/post_quantities/dimensionless.py b/bird/postprocess/post_quantities/dimensionless.py index f42d3f9e..9b3730c5 100644 --- a/bird/postprocess/post_quantities/dimensionless.py +++ b/bird/postprocess/post_quantities/dimensionless.py @@ -13,10 +13,19 @@ def froude(velocity: float, length: float, gravity: float = 9.81) -> float: r"""Froude number :math:`Fr = U / \sqrt{g\,L}`. - :param velocity: characteristic velocity :math:`U` [m/s] - :param length: characteristic length :math:`L` [m] - :param gravity: gravitational acceleration :math:`g` [m/s2] - :return: Froude number [-] + Parameters + ---------- + velocity: float + Characteristic velocity :math:`U`, in :math:`m.s^{-1}` + length: float + Characteristic length :math:`L`, in :math:`m` + gravity: float + Gravitational acceleration :math:`g`, in :math:`m.s^{-2}` + + Returns + ---------- + froude_number: float + Froude number (dimensionless) """ return velocity / np.sqrt(gravity * length) @@ -26,11 +35,21 @@ def weber( ) -> float: r"""Weber number :math:`We = \rho\,U^2\,L / \sigma`. - :param density: fluid density :math:`\rho` [kg/m3] - :param velocity: characteristic velocity :math:`U` [m/s] - :param length: characteristic length :math:`L` [m] - :param surface_tension: surface tension :math:`\sigma` [N/m] - :return: Weber number [-] + Parameters + ---------- + density: float + Fluid density :math:`\rho`, in :math:`kg.m^{-3}` + velocity: float + Characteristic velocity :math:`U`, in :math:`m.s^{-1}` + length: float + Characteristic length :math:`L`, in :math:`m` + surface_tension: float + Surface tension :math:`\sigma`, in :math:`N.m^{-1}` + + Returns + ---------- + weber_number: float + Weber number (dimensionless) """ return density * velocity**2 * length / surface_tension @@ -38,10 +57,19 @@ def weber( def sherwood(kl: float, length: float, diffusivity: float) -> float: r"""Sherwood number :math:`Sh = k_L\,L / D`. - :param kl: mass-transfer coefficient :math:`k_L` [m/s] - :param length: characteristic length :math:`L` [m] - :param diffusivity: mass diffusivity :math:`D` [m2/s] - :return: Sherwood number [-] + Parameters + ---------- + kl: float + Mass-transfer coefficient :math:`k_L`, in :math:`m.s^{-1}` + length: float + Characteristic length :math:`L`, in :math:`m` + diffusivity: float + Mass diffusivity :math:`D`, in :math:`m^2.s^{-1}` + + Returns + ---------- + sherwood_number: float + Sherwood number (dimensionless) """ return kl * length / diffusivity @@ -60,13 +88,29 @@ def compute_froude_number( :math:`|U_{\rm liq}|` at ``time_folder``, :math:`g` from ``constant/g``, and :math:`L` the passed length. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param length: characteristic length :math:`L` [m] - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(froude_number, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + length: float + Characteristic length :math:`L`, in :math:`m` + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + froude_number: float + Froude number (dimensionless) + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} @@ -92,13 +136,29 @@ def compute_weber_number( :math:`\sigma` from ``constant/phaseProperties``, and :math:`L` the passed length. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param length: characteristic length :math:`L` [m] - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(weber_number, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + length: float + Characteristic length :math:`L`, in :math:`m` + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + weber_number: float + Weber number (dimensionless) + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} @@ -128,14 +188,31 @@ def compute_sherwood_number( diffusivity :math:`D` read as ``D_`` from globalVars (the standard Sherwood definition; the turbulent contribution is deliberately excluded). - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param length: characteristic length :math:`L` [m] - :param species_name: species for which to compute kL and use D_ - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(sherwood_number, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + length: float + Characteristic length :math:`L`, in :math:`m` + species_name: str + Species for which to compute kL and use D_ + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + sherwood_number: float + Sherwood number (dimensionless) + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} diff --git a/bird/postprocess/post_quantities/kla.py b/bird/postprocess/post_quantities/kla.py index 29b5d66a..82082f03 100644 --- a/bird/postprocess/post_quantities/kla.py +++ b/bird/postprocess/post_quantities/kla.py @@ -281,11 +281,11 @@ def compute_instantaneous_kla( Returns ---------- kla_spec: dict - Instantaneous volume averaged kLa for each species, in h^-1 + Instantaneous volume averaged kLa for each species, in :math:`h^{-1}` Keys are species names Values are the kLa values cstar_spec: dict - Instantaneous volume averaged cstar for each species, in mol.m^-3 + Instantaneous volume averaged cstar for each species, in :math:`mol.m^{-3}` Keys are species names Values are the cstar values field_dict : dict @@ -387,11 +387,11 @@ def compute_instantaneous_kl( Returns ---------- kl_spec: dict - Instantaneous volume averaged kL for each species, in m.h^-1 + Instantaneous volume averaged kL for each species, in :math:`m.h^{-1}` Keys are species names Values are the kL values cstar_spec: dict - Instantaneous volume averaged cstar for each species, in mol.m^-3 + Instantaneous volume averaged cstar for each species, in :math:`mol.m^{-3}` Keys are species names Values are the cstar values field_dict : dict @@ -491,11 +491,11 @@ def compute_fitted_kla( Returns ---------- kla_spec: dict - Instantaneous volume averaged kLa for each species, in h^-1 + Instantaneous volume averaged kLa for each species, in :math:`h^{-1}` Keys are species names Values are dictionaries with key 'mean' (mean kLa value) and 'std' (1 standard deviation for the kLa value) cstar_spec: dict - Instantaneous volume averaged cstar for each species, in mol.m^-3 + Instantaneous volume averaged cstar for each species, in :math:`mol.m^{-3}` Keys are species names Values are dictionaries with key 'mean' (mean cstar value) and 'std' (1 standard deviation for the cstar value) field_dict : dict @@ -599,14 +599,39 @@ def compute_fitted_kl( species are divided by the interfacial area :math:`a = 6\,\epsilon / d`, evaluated at the last time folder. - :param case_folder: path to the case folder - :param species_names: species name(s) for which to compute kL - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param num_warmup: number of MCMC warmup samples - :param num_samples: number of posterior MCMC samples - :param field_dict: cache of already-read fields - :return: ``(kl_spec, cstar_spec, field_dict)`` with kL mean/std in :math:`m.h^{-1}` and cstar mean/std in :math:`mol.m^{-3}` + Parameters + ---------- + case_folder: str + Path to case folder + species_names: str | list[str] + List of species name for which to compute kL + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + num_warmup: int + Number of MCMC samples in the warmup phase + Defaults to 4000 + num_samples: int + Number of posterior MCMC samples generated + Defaults to 1000 + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + kl_spec: dict + Fitted volume averaged kL for each species, in :math:`m.h^{-1}` + Keys are species names + Values are dictionaries with key 'mean' (mean kL value) and 'std' (1 standard deviation for the kL value) + cstar_spec: dict + Fitted volume averaged cstar for each species, in :math:`mol.m^{-3}` + Keys are species names + Values are dictionaries with key 'mean' (mean cstar value) and 'std' (1 standard deviation for the cstar value) + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} diff --git a/bird/postprocess/post_quantities/loop_velocity.py b/bird/postprocess/post_quantities/loop_velocity.py index bbd0567e..25a2b8b4 100644 --- a/bird/postprocess/post_quantities/loop_velocity.py +++ b/bird/postprocess/post_quantities/loop_velocity.py @@ -39,10 +39,18 @@ def build_loop_direction_field( Cells in no box keep ``NaN`` (excluded from the average); a cell in more than one box is ambiguous and raises. - :param cell_centers: cell centres, shape ``(N, 3)`` - :param boxes: list of ``{"min": [x, y, z], "max": [x, y, z], - "direction": [dx, dy, dz]}``; ``direction`` is normalized internally - :return: direction field, shape ``(N, 3)``, ``NaN`` where uncovered + Parameters + ---------- + cell_centers: np.ndarray + Cell centres, shape ``(N, 3)`` + boxes: list[dict] + List of ``{"min": [x, y, z], "max": [x, y, z], "direction": [dx, dy, dz]}``; + ``direction`` is normalized internally + + Returns + ---------- + direction_field: np.ndarray + Direction field, shape ``(N, 3)``, ``NaN`` where uncovered """ cell_centers = np.asarray(cell_centers, dtype=float) n_cells = len(cell_centers) @@ -88,10 +96,19 @@ def build_loop_direction_field_from_path( nearest segment; cells farther away keep ``NaN`` (excluded). The polyline ordering sets the circulation sense. - :param cell_centers: cell centres, shape ``(N, 3)`` - :param path_points: ordered centerline vertices, shape ``(M, 3)`` - :param max_dist: cells beyond this distance from the path are left uncovered - :return: direction field, shape ``(N, 3)``, ``NaN`` where uncovered + Parameters + ---------- + cell_centers: np.ndarray + Cell centres, shape ``(N, 3)`` + path_points: np.ndarray + Ordered centerline vertices, shape ``(M, 3)`` + max_dist: float + Cells beyond this distance from the path are left uncovered + + Returns + ---------- + direction_field: np.ndarray + Direction field, shape ``(N, 3)``, ``NaN`` where uncovered """ cell_centers = np.asarray(cell_centers, dtype=float) path_points = np.asarray(path_points, dtype=float) @@ -145,10 +162,18 @@ def propose_loop_boxes_block_rect( ``transformPoints`` scale). A mismatch surfaces downstream as a zero-coverage error in :func:`build_loop_direction_field`. - :param mesh_geometry: the ``"Geometry"`` dict from the case ``mesh.json`` - :param rescale: uniform scale factor applied to the box coordinates; ``None`` - assumes 1.0 (base units) - :return: box list consumable by :func:`build_loop_direction_field` + Parameters + ---------- + mesh_geometry: dict + The ``"Geometry"`` dict from the case ``mesh.json`` + rescale: float | None + Uniform scale factor applied to the box coordinates; ``None`` assumes + 1.0 (base units) + + Returns + ---------- + boxes: list[dict] + Box list consumable by :func:`build_loop_direction_field` """ factor = 1.0 if rescale is None else float(rescale) segment_data = from_block_rect_to_seg(mesh_geometry, rescale=False) @@ -222,13 +247,26 @@ def compute_loop_velocity( Averaged over the liquid on the covered cells. Positive follows the prescribed circulation, negative is reversed. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param loop_direction_field: ``(N, 3)`` field from a builder, ``NaN`` on - uncovered cells - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(loop_velocity, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + loop_direction_field: np.ndarray + ``(N, 3)`` field from a builder, ``NaN`` on uncovered cells + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + loop_velocity: float + Volume averaged loop velocity, in :math:`m.s^{-1}` + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} diff --git a/bird/postprocess/post_quantities/phase.py b/bird/postprocess/post_quantities/phase.py index 108abcf7..a6d5bf00 100644 --- a/bird/postprocess/post_quantities/phase.py +++ b/bird/postprocess/post_quantities/phase.py @@ -195,9 +195,17 @@ def compute_ave_bubble_diam( def interfacial_area(gas_holdup: float, bubble_diam: float) -> float: r"""Gas-liquid interfacial area per unit volume :math:`a = 6\,\epsilon / d`. - :param gas_holdup: gas holdup :math:`\epsilon` [-] - :param bubble_diam: bubble diameter :math:`d` [m] - :return: interfacial area :math:`a` [1/m] + Parameters + ---------- + gas_holdup: float + Gas holdup :math:`\epsilon` (dimensionless) + bubble_diam: float + Bubble diameter :math:`d`, in :math:`m` + + Returns + ---------- + interfacial_area: float + Interfacial area :math:`a`, in :math:`m^{-1}` """ return 6.0 * gas_holdup / bubble_diam @@ -214,12 +222,27 @@ def compute_ave_liquid_density( Reads ``thermo:rho.liquid`` (then ``rho.liquid``); returns 1000 kg/m3 if neither field is written. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(density, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + density: float + Volume averaged liquid density, in :math:`kg.m^{-3}` + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} @@ -247,12 +270,27 @@ def compute_ave_liquid_velocity( ) -> tuple[float, dict]: r"""Volume-averaged liquid velocity magnitude :math:`|U_{\rm liq}|` over the liquid. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param n_cells: number of cells (deduced from the field read if None) - :param volume_time: time folder for the cell volumes (auto if None) - :param field_dict: cache of already-read fields - :return: ``(velocity_magnitude, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + volume_time : str | None + Time folder to read to get the cell volumes. + If None, finds volume time automatically + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + velocity_magnitude: float + Volume averaged liquid velocity magnitude, in :math:`m.s^{-1}` + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} diff --git a/bird/postprocess/post_quantities/transport.py b/bird/postprocess/post_quantities/transport.py index 57fc077d..6371b4a9 100644 --- a/bird/postprocess/post_quantities/transport.py +++ b/bird/postprocess/post_quantities/transport.py @@ -26,11 +26,24 @@ def compute_turbulent_diffusivity( is read from ``thermo:rho.liquid`` (then ``rho.liquid``), falling back to ``rho0MixLiq`` from ``globalVars`` and then 1000. - :param case_folder: path to the case folder - :param time_folder: name of the time folder to analyze - :param n_cells: number of cells (deduced from the field read if None) - :param field_dict: cache of already-read fields - :return: ``(turbulent_diffusivity, field_dict)`` + Parameters + ---------- + case_folder: str + Path to case folder + time_folder: str + Name of the time folder to analyze + n_cells : int | None + Number of cells in the domain. + If None, it will deduced from the field reading + field_dict : dict + Dictionary of fields used to avoid rereading the same fields to calculate different quantities + + Returns + ---------- + turbulent_diffusivity: float + Volume averaged turbulent mass diffusivity, in :math:`m^2.s^{-1}` + field_dict : dict + Dictionary of fields read """ if field_dict is None: field_dict = {} diff --git a/bird/postprocess/stats.py b/bird/postprocess/stats.py index 16c3f508..1898822a 100644 --- a/bird/postprocess/stats.py +++ b/bird/postprocess/stats.py @@ -199,11 +199,22 @@ def steady_stat( simulation time. Returns (nan, nan) for an empty or all-nan series and (value, 0.0) when a single sample falls in the window. - :param time_series: time series of the signal - :param time_values: sampling times of the series - :param window: length of the end window in time units; 10% of the total - time span if None - :return: (mean, 1-sigma uncertainty about the mean) + Parameters + ---------- + time_series: np.ndarray | list + Time series of the signal + time_values: np.ndarray | list + Sampling times of the series + window: float | None + Length of the end window in time units. + If None, 10% of the total time span is used + + Returns + ---------- + mean_val: float + Mean value over the tail window + unc_val: float + 1-sigma uncertainty about the mean """ time_series = np.asarray(time_series, dtype=float) time_values = np.asarray(time_values, dtype=float) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index f8b02d38..b78fb49c 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -374,11 +374,16 @@ def write_mixer_ball( ): """Append one ``ball`` mixer block to ``fvModels``. - :param mixer: a ready :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`. - :param power_mode: ``"from_P"`` (drive by ``mixer.power``) or - ``"from_Np_Vtip"`` (drive by ``mixer.Np`` and ``mixer.Vtip``). - :param momentum_mode: ``"axial"`` (thrust only) or ``"axial_and_swirl"`` - (thrust + tangential source using ``mixer.sigma``). + Parameters + ---------- + mixer: ActuatorMixer + A ready :class:`~bird.preprocess.dynamic_mixer.mixer.ActuatorMixer`. + power_mode: str + ``"from_P"`` (drive by ``mixer.power``) or ``"from_Np_Vtip"`` (drive by + ``mixer.Np`` and ``mixer.Vtip``). + momentum_mode: str + ``"axial"`` (thrust only) or ``"axial_and_swirl"`` (thrust + tangential + source using ``mixer.sigma``). """ if power_mode not in ("from_P", "from_Np_Vtip"): raise ValueError(f"unknown power_mode {power_mode!r}") @@ -542,8 +547,10 @@ def write_static_mixer_ball(mixer, output_folder): energy-neutral axial reaction; a lumped axial drag adds the viscous loss. The source is inactive when the inflow opposes the mixer orientation. - :param mixer: a ready - :class:`~bird.preprocess.dynamic_mixer.mixer.StaticMixer`. + Parameters + ---------- + mixer: StaticMixer + A ready :class:`~bird.preprocess.dynamic_mixer.mixer.StaticMixer`. """ nd = int(mixer.normal_dir) dn = ["dx", "dy", "dz"][nd] diff --git a/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index 92c99dd5..d8a190f0 100644 --- a/bird/preprocess/dynamic_mixer/mixer.py +++ b/bird/preprocess/dynamic_mixer/mixer.py @@ -171,10 +171,13 @@ def update_from_expl_dict(self, mixer_dict: dict) -> None: def update_from_loop_dict(self, mixer_dict: dict, geom_dict: dict) -> None: """Populate from a loop mixer dict. - :param mixer_dict: mixer entry with ``branch_id``, ``frac_space`` and, - optionally, ``radius`` as a fraction of the branch cross-section. - :param geom_dict: output of ``from_block_rect_to_seg`` (``segments`` and - ``blocksize``). + Parameters + ---------- + mixer_dict: dict + Mixer entry with ``branch_id``, ``frac_space`` and, optionally, + ``radius`` as a fraction of the branch cross-section. + geom_dict: dict + Output of ``from_block_rect_to_seg`` (``segments`` and ``blocksize``). """ segment = geom_dict["segments"][mixer_dict["branch_id"]] pos = segment["start"] + mixer_dict["frac_space"] * segment["conn"] @@ -274,11 +277,14 @@ def update_from_expl_dict(self, mixer_dict: dict) -> None: def update_from_loop_dict(self, mixer_dict: dict, geom_dict: dict) -> None: """Populate from a loop mixer dict. - :param mixer_dict: mixer entry with ``branch_id``, ``frac_space`` and, - optionally, ``radius`` as a fraction of the branch cross-section - (``0.5`` spans the whole tube). - :param geom_dict: output of ``from_block_rect_to_seg`` (``segments`` and - ``blocksize``). + Parameters + ---------- + mixer_dict: dict + Mixer entry with ``branch_id``, ``frac_space`` and, optionally, + ``radius`` as a fraction of the branch cross-section (``0.5`` spans + the whole tube). + geom_dict: dict + Output of ``from_block_rect_to_seg`` (``segments`` and ``blocksize``). """ segment = geom_dict["segments"][mixer_dict["branch_id"]] pos = segment["start"] + mixer_dict["frac_space"] * segment["conn"] diff --git a/bird/preprocess/json_gen/design_io.py b/bird/preprocess/json_gen/design_io.py index 7846bbff..7607f8e1 100644 --- a/bird/preprocess/json_gen/design_io.py +++ b/bird/preprocess/json_gen/design_io.py @@ -13,8 +13,11 @@ def generate_stl_patch(filename, bc_dict, geom_dict): def generate_dynamic_mixer(filename, mixers_list, geom_dict, model=None): """Write a mixers.json. - :param model: optional dict of top-level model selectors written verbatim - (e.g. ``{"volumetric_source": "ball", "power": "from_Np_Vtip", + Parameters + ---------- + model: + Optional dict of top-level model selectors written verbatim (e.g. + ``{"volumetric_source": "ball", "power": "from_Np_Vtip", "momentum_source": "axial_and_swirl"}``). ``None`` keeps the legacy pancake output. """ diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 254b722f..f05b1040 100644 --- a/bird/preprocess/json_gen/generate_designs.py +++ b/bird/preprocess/json_gen/generate_designs.py @@ -87,11 +87,18 @@ def sample_placement_designs( :func:`check_config` keeps only designs with at least one inlet and :func:`compare_config` rejects duplicates. Keys are contiguous ``0..n-1``. - :param branches_com: branch ids on which choices are placed. - :param branchcom_spots: ``branch_id -> array`` of candidate spot fractions. - :param n_designs: number of distinct valid designs to return. - :param choices: per-spot categorical choices (e.g. mixer/sparger/none). - :param max_attempts: give up after this many draws. + Parameters + ---------- + branches_com: + Branch ids on which choices are placed. + branchcom_spots: + ``branch_id -> array`` of candidate spot fractions. + n_designs: + Number of distinct valid designs to return. + choices: + Per-spot categorical choices (e.g. mixer/sparger/none). + max_attempts: + Give up after this many draws. """ config_dict = {} attempts = 0 @@ -706,9 +713,14 @@ def overwrite_qoi_params(case_folder, rhog, cstar_co2, cstar_h2): own values (the mixer power is NOT touched here -- get_qoi.py reads it from mixers.json). - :param rhog: gas density [kg/m3] used in the injection-power estimate. - :param cstar_co2: (low, high) uniform-prior bounds for the CO2 c*. - :param cstar_h2: (low, high) uniform-prior bounds for the H2 c*. + Parameters + ---------- + rhog: + Gas density in :math:`kg.m^{-3}` used in the injection-power estimate. + cstar_co2: + (low, high) uniform-prior bounds for the CO2 c*. + cstar_h2: + (low, high) uniform-prior bounds for the H2 c*. """ co2_lo, co2_hi = cstar_co2 h2_lo, h2_hi = cstar_h2 @@ -751,8 +763,11 @@ def overwrite_ncores(case_folder, n): def overwrite_controldict(case_folder, params): """Rewrite time-stepping entries in system/controlDict. - :param params: dict with any of ``deltaT``, ``endTime``, ``maxCo``, - ``maxDeltaT``; each present key overwrites its scalar entry. + Parameters + ---------- + params: + Dict with any of ``deltaT``, ``endTime``, ``maxCo``, ``maxDeltaT``; + each present key overwrites its scalar entry. """ filename = os.path.join(case_folder, "system", "controlDict") with open(filename, "r+") as f: From 3665021ca41c1bf8e0cf5282ab2cc1a698874a33 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:46:32 -0600 Subject: [PATCH 51/52] format --- bird/postprocess/post_quantities/phase.py | 4 ++-- bird/postprocess/stats.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bird/postprocess/post_quantities/phase.py b/bird/postprocess/post_quantities/phase.py index a6d5bf00..bfbdd0c5 100644 --- a/bird/postprocess/post_quantities/phase.py +++ b/bird/postprocess/post_quantities/phase.py @@ -30,9 +30,9 @@ def _read_liquid_density_field( except FileNotFoundError: continue try: - rho0 = float(read_global_vars(case_folder).get("rho0MixLiq", 1000.0)) + rho0 = float(read_global_vars(case_folder).get("rho0MixLiq", 1000.0)) except FileNotFoundError: - rho0 = 1000.0 + rho0 = 1000.0 logger.warning( f"No liquid density field in " f"{os.path.join(case_folder, time_folder)}, assuming {rho0} kg/m3" diff --git a/bird/postprocess/stats.py b/bird/postprocess/stats.py index 1898822a..963556e1 100644 --- a/bird/postprocess/stats.py +++ b/bird/postprocess/stats.py @@ -230,7 +230,9 @@ def steady_stat( windowed_values = time_values[in_window] if np.all(np.isnan(windowed_series)): return np.nan, np.nan - if windowed_series.size < 2 or np.all(windowed_series == windowed_series[0]): + if windowed_series.size < 2 or np.all( + windowed_series == windowed_series[0] + ): return float(windowed_series[0]), 0.0 mean_value, uncertainty_95 = calc_mean(windowed_series, windowed_values) From 986bdbc811f1ea78c20ee0eab687377b16b8efc1 Mon Sep 17 00:00:00 2001 From: Malik Date: Fri, 11 Sep 2026 07:54:13 -0600 Subject: [PATCH 52/52] new v --- bird/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bird/version.py b/bird/version.py index 30aea71c..57285602 100644 --- a/bird/version.py +++ b/bird/version.py @@ -1,3 +1,3 @@ """Bio reactor design version""" -__version__ = "0.0.58" +__version__ = "0.0.59"