diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 425ae77a..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 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 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 pip install --upgrade pip pip install . @@ -218,6 +221,18 @@ jobs: run: | cd experimental_cases/OF9/deckwer19 bash run.sh + - name: Run Uloop Exp1 + run: | + cd experimental_cases/OF9/uloop_valadbeigy_exp1 + bash run.sh + - name: Run Uloop Exp2 + run: | + cd experimental_cases/OF9/uloop_valadbeigy_exp2 + bash run.sh + - name: Run Uloop Exp3 + run: | + cd experimental_cases/OF9/uloop_valadbeigy_exp3 + bash run.sh - name: Run side sparger tutorial run: | cd tutorial_cases/OF9/side_sparger @@ -237,7 +252,15 @@ jobs: - name: Run mixing loop reactor tutorial run: | cd tutorial_cases/OF9/loop_reactor_mixing - bash run.sh + bash run.sh + - name: Run mixing loop reactor with swirl tutorial + run: | + cd tutorial_cases/OF9/loop_reactor_mixing_swirl + bash run.sh + - name: Run mixing loop reactor with static mixer tutorial + run: | + cd tutorial_cases/OF9/loop_reactor_mixing_static + bash run.sh - name: Run airlift reactor tutorial run: | cd tutorial_cases/OF9/airlift_40m @@ -274,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 @@ -281,7 +306,6 @@ jobs: - name: Install dependencies run: | - micromamba install --yes -n test-env -c conda-forge paraview pip install --upgrade pip pip install . 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/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/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) diff --git a/bird/preprocess/dynamic_mixer/io_fvModels.py b/bird/preprocess/dynamic_mixer/io_fvModels.py index 414dfdf6..f8b02d38 100644 --- a/bird/preprocess/dynamic_mixer/io_fvModels.py +++ b/bird/preprocess/dynamic_mixer/io_fvModels.py @@ -326,6 +326,358 @@ 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_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" + # 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") + 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}] -= {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( + 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}] -= {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") + 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/bird/preprocess/dynamic_mixer/mixer.py b/bird/preprocess/dynamic_mixer/mixer.py index 524ff43c..92c99dd5 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 @@ -93,3 +108,215 @@ def check_status(self, blocks=None): logger.info(f"\tbranch = {blocks}") self.ready = True + + +class ActuatorMixer: + """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 + + +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/bird/preprocess/dynamic_mixer/mixing_fvModels.py b/bird/preprocess/dynamic_mixer/mixing_fvModels.py index 6a4e99e6..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 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,7 +29,27 @@ 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" or input_dict.get("static_mixers"): + 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 +75,42 @@ 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 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 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() + 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) + 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/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/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 diff --git a/bird/preprocess/json_gen/generate_designs.py b/bird/preprocess/json_gen/generate_designs.py index 862de36a..254b722f 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 @@ -5,7 +6,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 * @@ -37,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: @@ -61,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): @@ -581,3 +660,456 @@ 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) + + +# 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") + 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 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", + 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" + with open(os.path.join(case_folder, "script_single"), "w+") as f: + f.write("#!/bin/bash\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(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") + f.write("decomposePar -fileHandler collated\n") + f.write(f"srun -n {cores} {solver} -parallel -fileHandler collated\n") + 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_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, + sims_per_node=26, + cores_per_sim=4, + account="gas2fuels", + solver="birdmultiphaseEulerFoam", + walltime="47:59:00", +): + """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(f"#SBATCH --job-name=lev_{pack_name}\n") + f.write("#SBATCH --nodes=1\n") + f.write("#SBATCH --exclusive\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") + 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 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, + scale, + n_sim, + study_folder, + mixer_params, + 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=16, + cores_per_node=128, + controldict_params=None, + walltime="47:59:00", +): + """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 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. `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``) + written into every case of this level via :func:`overwrite_controldict`; + left ``None`` the template controlDict is used unchanged. + """ + # 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") + ) + # 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) + + # 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( + { + "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 / 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() + 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": mixer_params["sign"][branch], + "swirl_sign": mixer_params["swirl_sign"][branch], + "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_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) + 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, walltime=walltime + ) + 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, + sims_per_node=sims_per_node, + cores_per_sim=cores_per_sim, + 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( + os.path.join(study_folder, "branchcom_spots.pkl"), branchcom_spots + ) 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/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 -------------------------------------------------- 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/0.orig/N2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/N2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/O2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/O2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/T.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/T.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/U.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/U.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/Ydefault.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/Z.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/alpha.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/alpha.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/alphat.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/alphat.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/k.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/k.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/nut.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/nut.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/omega.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/omega.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/p b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/0.orig/p_rgh b/experimental_cases/OF9/uloop_valadbeigy_exp1/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean new file mode 100755 index 00000000..bf27685b --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/Allclean @@ -0,0 +1,23 @@ +#!/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" +rm -rf "processor*" +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp1/build_uloop_hex.py b/experimental_cases/OF9/uloop_valadbeigy_exp1/build_uloop_hex.py new file mode 100644 index 00000000..43cb6cba --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/build_uloop_hex.py @@ -0,0 +1,524 @@ +""" +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/OF9/uloop_valadbeigy_exp1/constant/fvModels b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/g b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/globalVars b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/globalVars_temp b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/momentumTransport.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/momentumTransport.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/phaseProperties b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/phaseProperties_constantd b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp1/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/get_mixing_time.py b/experimental_cases/OF9/uloop_valadbeigy_exp1/get_mixing_time.py new file mode 100644 index 00000000..ffe78675 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/get_mixing_time.py @@ -0,0 +1,218 @@ +"""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/OF9/uloop_valadbeigy_exp1/presteps.sh b/experimental_cases/OF9/uloop_valadbeigy_exp1/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/run.sh b/experimental_cases/OF9/uloop_valadbeigy_exp1/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/script b/experimental_cases/OF9/uloop_valadbeigy_exp1/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post new file mode 100755 index 00000000..f1577763 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp1/script_post @@ -0,0 +1,13 @@ +#!/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 + +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/OF9/uloop_valadbeigy_exp1/stitch_and_check.sh b/experimental_cases/OF9/uloop_valadbeigy_exp1/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/controlDict b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/createPatchDict b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/decomposeParDict b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/fvConstraints b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/fvSchemes b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/fvSolution b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/inlets_outlets.json b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/mixers.json b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/mixers.json new file mode 100644 index 00000000..1f51bc16 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/system/setFieldsDict b/experimental_cases/OF9/uloop_valadbeigy_exp1/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp1/writeGlobalVars.py b/experimental_cases/OF9/uloop_valadbeigy_exp1/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/N2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/N2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/O2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/O2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/T.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/T.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/U.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/U.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/Ydefault.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/Z.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/alpha.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/alpha.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/alphat.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/alphat.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/k.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/k.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/nut.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/nut.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/omega.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/omega.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/p b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/0.orig/p_rgh b/experimental_cases/OF9/uloop_valadbeigy_exp2/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp2/Allclean new file mode 100755 index 00000000..174b6310 --- /dev/null +++ b/experimental_cases/OF9/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" +rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp2/build_uloop_hex.py b/experimental_cases/OF9/uloop_valadbeigy_exp2/build_uloop_hex.py new file mode 100644 index 00000000..43cb6cba --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp2/build_uloop_hex.py @@ -0,0 +1,524 @@ +""" +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/OF9/uloop_valadbeigy_exp2/constant/fvModels b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/g b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/globalVars b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/globalVars_temp b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/momentumTransport.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/momentumTransport.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/phaseProperties b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/phaseProperties_constantd b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp2/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/get_mixing_time.py b/experimental_cases/OF9/uloop_valadbeigy_exp2/get_mixing_time.py new file mode 100644 index 00000000..ffe78675 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp2/get_mixing_time.py @@ -0,0 +1,218 @@ +"""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/OF9/uloop_valadbeigy_exp2/presteps.sh b/experimental_cases/OF9/uloop_valadbeigy_exp2/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/run.sh b/experimental_cases/OF9/uloop_valadbeigy_exp2/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/script b/experimental_cases/OF9/uloop_valadbeigy_exp2/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post new file mode 100755 index 00000000..f1577763 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp2/script_post @@ -0,0 +1,13 @@ +#!/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 + +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/OF9/uloop_valadbeigy_exp2/stitch_and_check.sh b/experimental_cases/OF9/uloop_valadbeigy_exp2/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/controlDict b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/createPatchDict b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/decomposeParDict b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/fvConstraints b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/fvSchemes b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/fvSolution b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/inlets_outlets.json b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/mixers.json b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/mixers.json new file mode 100644 index 00000000..eccd2af9 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/system/setFieldsDict b/experimental_cases/OF9/uloop_valadbeigy_exp2/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp2/writeGlobalVars.py b/experimental_cases/OF9/uloop_valadbeigy_exp2/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/N2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/N2.gas new file mode 100644 index 00000000..d52e4d25 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/N2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/N2.liquid new file mode 100644 index 00000000..9cea536f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/O2.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/O2.gas new file mode 100644 index 00000000..8225d524 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/O2.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/O2.liquid new file mode 100644 index 00000000..2cfefccb --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/T.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/T.gas new file mode 100644 index 00000000..8388cb6d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/T.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/T.liquid new file mode 100644 index 00000000..89c826e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/U.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/U.gas new file mode 100644 index 00000000..27a4d894 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/U.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/U.liquid new file mode 100644 index 00000000..ceebde58 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/Ydefault.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/Ydefault.gas new file mode 100644 index 00000000..03b3da41 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/Ydefault.liquid new file mode 100644 index 00000000..b7c305e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/Z.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/Z.liquid new file mode 100644 index 00000000..9529319c --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/alpha.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/alpha.gas new file mode 100644 index 00000000..2258d0a6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/alpha.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/alpha.liquid new file mode 100644 index 00000000..d6470775 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/alphat.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/alphat.gas new file mode 100644 index 00000000..928026d5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/alphat.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/alphat.liquid new file mode 100644 index 00000000..1bbd1cca --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/k.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/k.gas new file mode 100644 index 00000000..461ac6e6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/k.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/k.liquid new file mode 100644 index 00000000..17a7ca05 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/nut.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/nut.gas new file mode 100644 index 00000000..b3dea556 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/nut.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/nut.liquid new file mode 100644 index 00000000..b8303c6a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/omega.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/omega.gas new file mode 100644 index 00000000..ee1c4607 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/omega.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/omega.liquid new file mode 100644 index 00000000..55f48dcc --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/p b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/p new file mode 100644 index 00000000..2c787dc3 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/0.orig/p_rgh b/experimental_cases/OF9/uloop_valadbeigy_exp3/0.orig/p_rgh new file mode 100644 index 00000000..2cc1f127 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/Allclean b/experimental_cases/OF9/uloop_valadbeigy_exp3/Allclean new file mode 100755 index 00000000..174b6310 --- /dev/null +++ b/experimental_cases/OF9/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" +rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/experimental_cases/OF9/uloop_valadbeigy_exp3/build_uloop_hex.py b/experimental_cases/OF9/uloop_valadbeigy_exp3/build_uloop_hex.py new file mode 100644 index 00000000..43cb6cba --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp3/build_uloop_hex.py @@ -0,0 +1,524 @@ +""" +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/OF9/uloop_valadbeigy_exp3/constant/fvModels b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/fvModels new file mode 100644 index 00000000..b8553170 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/g b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/globalVars b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/globalVars new file mode 100644 index 00000000..ef6762ad --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/globalVars_temp b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/globalVars_temp new file mode 100644 index 00000000..178935a4 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/momentumTransport.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/momentumTransport.gas new file mode 100644 index 00000000..cca64eef --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/momentumTransport.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/momentumTransport.liquid new file mode 100644 index 00000000..df3e15b5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/phaseProperties b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/phaseProperties new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/phaseProperties_constantd b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/phaseProperties_constantd new file mode 100644 index 00000000..d8d0e1c5 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..bbec9049 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid b/experimental_cases/OF9/uloop_valadbeigy_exp3/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..b0c78662 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/get_mixing_time.py b/experimental_cases/OF9/uloop_valadbeigy_exp3/get_mixing_time.py new file mode 100644 index 00000000..ffe78675 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp3/get_mixing_time.py @@ -0,0 +1,218 @@ +"""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/OF9/uloop_valadbeigy_exp3/presteps.sh b/experimental_cases/OF9/uloop_valadbeigy_exp3/presteps.sh new file mode 100755 index 00000000..d32003ce --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/run.sh b/experimental_cases/OF9/uloop_valadbeigy_exp3/run.sh new file mode 100755 index 00000000..c9d5f3cd --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/script b/experimental_cases/OF9/uloop_valadbeigy_exp3/script new file mode 100644 index 00000000..06eaf486 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/script_post b/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post new file mode 100755 index 00000000..f1577763 --- /dev/null +++ b/experimental_cases/OF9/uloop_valadbeigy_exp3/script_post @@ -0,0 +1,13 @@ +#!/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 + +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/OF9/uloop_valadbeigy_exp3/stitch_and_check.sh b/experimental_cases/OF9/uloop_valadbeigy_exp3/stitch_and_check.sh new file mode 100755 index 00000000..d83110d9 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/controlDict b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/controlDict new file mode 100644 index 00000000..cbee600d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/createPatchDict b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/createPatchDict new file mode 100644 index 00000000..ceca5e01 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/decomposeParDict b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/fvConstraints b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/fvSchemes b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/fvSchemes new file mode 100644 index 00000000..4052644d --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/fvSolution b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/fvSolution new file mode 100644 index 00000000..64b22685 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/inlets_outlets.json b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/inlets_outlets.json new file mode 100644 index 00000000..5233240a --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/mixers.json b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/mixers.json new file mode 100644 index 00000000..41606a06 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/system/setFieldsDict b/experimental_cases/OF9/uloop_valadbeigy_exp3/system/setFieldsDict new file mode 100644 index 00000000..354c50b6 --- /dev/null +++ b/experimental_cases/OF9/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/OF9/uloop_valadbeigy_exp3/writeGlobalVars.py b/experimental_cases/OF9/uloop_valadbeigy_exp3/writeGlobalVars.py new file mode 100644 index 00000000..f20defef --- /dev/null +++ b/experimental_cases/OF9/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/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' diff --git a/pyproject.toml b/pyproject.toml index 28e99d65..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] @@ -151,3 +152,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" diff --git a/tests/preprocess/test_case_gen.py b/tests/preprocess/test_case_gen.py index fbb15b26..2abe5791 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 @@ -129,3 +130,257 @@ def random_sample(branches_com, branchcom_spots, config_dict={}): save_config_dict( f"{study_folder}/branchcom_spots.pkl", branchcom_spots ) + + +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( + 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"] + + +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 + ) + + +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", + ] 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 diff --git a/tests/preprocess/test_static_mixer.py b/tests/preprocess/test_static_mixer.py new file mode 100644 index 00000000..cbfa52ae --- /dev/null +++ b/tests/preprocess/test_static_mixer.py @@ -0,0 +1,267 @@ +import os +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 +from bird.preprocess.dynamic_mixer.mixing_fvModels import write_fvModel +from bird.utilities.parser import parse_json + + +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 + + +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 + # 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 + + +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 + # 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(): + # 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 + + +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("};") 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/0.orig/CO2.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/CO2.gas new file mode 100644 index 00000000..e4165b1a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/CO2.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/CO2.liquid new file mode 100644 index 00000000..4b8ea6a0 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/H2.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/H2.gas new file mode 100644 index 00000000..9f66b2d2 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/H2.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/H2.liquid new file mode 100644 index 00000000..65ae8d34 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/N2.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/N2.gas new file mode 100644 index 00000000..c1d7225f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/T.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/T.gas new file mode 100644 index 00000000..1202c340 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/T.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/T.liquid new file mode 100644 index 00000000..d6c1836a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/U.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/U.gas new file mode 100644 index 00000000..e696566f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/U.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/U.liquid new file mode 100644 index 00000000..1879e020 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/Ydefault.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/Ydefault.gas new file mode 100644 index 00000000..fba2945d --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/Ydefault.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/Ydefault.liquid new file mode 100644 index 00000000..a5108564 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/alpha.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/alpha.gas new file mode 100644 index 00000000..1e303fbe --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/alpha.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/alpha.liquid new file mode 100644 index 00000000..5c92070b --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/alphat.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/alphat.gas new file mode 100644 index 00000000..b867958f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/alphat.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/alphat.liquid new file mode 100644 index 00000000..2569c3ee --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/epsilon.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/epsilon.gas new file mode 100644 index 00000000..707a1cda --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/epsilon.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/epsilon.liquid new file mode 100644 index 00000000..0a4236fd --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/f.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/f.gas new file mode 100644 index 00000000..76ee77a9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/k.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/k.gas new file mode 100644 index 00000000..4a3d44ca --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/k.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/k.liquid new file mode 100644 index 00000000..cde8f6c1 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/nut.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/nut.gas new file mode 100644 index 00000000..ba16dd4c --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/nut.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/nut.liquid new file mode 100644 index 00000000..1442e07f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/p b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/p new file mode 100644 index 00000000..b3a295fb --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/0.orig/p_rgh b/tutorial_cases/OF9/loop_reactor_mixing_static/0.orig/p_rgh new file mode 100644 index 00000000..88ee7d80 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/Allclean b/tutorial_cases/OF9/loop_reactor_mixing_static/Allclean new file mode 100755 index 00000000..174b6310 --- /dev/null +++ b/tutorial_cases/OF9/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" +rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/tutorial_cases/OF9/loop_reactor_mixing_static/README.md b/tutorial_cases/OF9/loop_reactor_mixing_static/README.md new file mode 100644 index 00000000..f8a070ec --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/computeQOI.sh b/tutorial_cases/OF9/loop_reactor_mixing_static/computeQOI.sh new file mode 100644 index 00000000..3756ed7f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/fvModels b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/fvModels new file mode 100644 index 00000000..6b37fb16 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/g b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/globalVars b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/globalVars new file mode 100644 index 00000000..c0dce472 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/globalVars_temp b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/globalVars_temp new file mode 100644 index 00000000..dfddd649 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/momentumTransport.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/momentumTransport.gas new file mode 100644 index 00000000..ca916714 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/momentumTransport.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/momentumTransport.liquid new file mode 100644 index 00000000..2063de0d --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/phaseProperties b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/phaseProperties new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/phaseProperties_constantd b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/phaseProperties_constantd new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/phaseProperties_pbe b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/phaseProperties_pbe new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/thermophysicalProperties.gas b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..11b1c4b9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid b/tutorial_cases/OF9/loop_reactor_mixing_static/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..d324ec51 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/get_qoi.py b/tutorial_cases/OF9/loop_reactor_mixing_static/get_qoi.py new file mode 100644 index 00000000..7f3897ed --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/presteps.sh b/tutorial_cases/OF9/loop_reactor_mixing_static/presteps.sh new file mode 100644 index 00000000..bfcff75f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/read_history.py b/tutorial_cases/OF9/loop_reactor_mixing_static/read_history.py new file mode 100644 index 00000000..c27eae94 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/run.sh b/tutorial_cases/OF9/loop_reactor_mixing_static/run.sh new file mode 100644 index 00000000..8ec96fb0 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/script b/tutorial_cases/OF9/loop_reactor_mixing_static/script new file mode 100755 index 00000000..efe675ff --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/script_post b/tutorial_cases/OF9/loop_reactor_mixing_static/script_post new file mode 100755 index 00000000..aabbc33e --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/blockMeshDict b/tutorial_cases/OF9/loop_reactor_mixing_static/system/blockMeshDict new file mode 100644 index 00000000..0bb60950 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/controlDict b/tutorial_cases/OF9/loop_reactor_mixing_static/system/controlDict new file mode 100644 index 00000000..f4665ed8 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/decomposeParDict b/tutorial_cases/OF9/loop_reactor_mixing_static/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/fvConstraints b/tutorial_cases/OF9/loop_reactor_mixing_static/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/fvSchemes b/tutorial_cases/OF9/loop_reactor_mixing_static/system/fvSchemes new file mode 100644 index 00000000..52e6e13a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/fvSolution b/tutorial_cases/OF9/loop_reactor_mixing_static/system/fvSolution new file mode 100644 index 00000000..2e69fdfa --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/inlets_outlets.json b/tutorial_cases/OF9/loop_reactor_mixing_static/system/inlets_outlets.json new file mode 100644 index 00000000..a083d47f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/mesh.json b/tutorial_cases/OF9/loop_reactor_mixing_static/system/mesh.json new file mode 100644 index 00000000..29841d7e --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/mixers.json b/tutorial_cases/OF9/loop_reactor_mixing_static/system/mixers.json new file mode 100644 index 00000000..87557d6b --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/system/setFieldsDict b/tutorial_cases/OF9/loop_reactor_mixing_static/system/setFieldsDict new file mode 100644 index 00000000..89a797b9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_static/writeGlobalVars.py b/tutorial_cases/OF9/loop_reactor_mixing_static/writeGlobalVars.py new file mode 100644 index 00000000..e64d69e3 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/CO2.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/CO2.gas new file mode 100644 index 00000000..e4165b1a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/CO2.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/CO2.liquid new file mode 100644 index 00000000..4b8ea6a0 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/H2.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/H2.gas new file mode 100644 index 00000000..9f66b2d2 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/H2.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/H2.liquid new file mode 100644 index 00000000..65ae8d34 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/N2.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/N2.gas new file mode 100644 index 00000000..c1d7225f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/T.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/T.gas new file mode 100644 index 00000000..1202c340 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/T.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/T.liquid new file mode 100644 index 00000000..d6c1836a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/U.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/U.gas new file mode 100644 index 00000000..e696566f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/U.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/U.liquid new file mode 100644 index 00000000..1879e020 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/Ydefault.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/Ydefault.gas new file mode 100644 index 00000000..fba2945d --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/Ydefault.liquid new file mode 100644 index 00000000..a5108564 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/alpha.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/alpha.gas new file mode 100644 index 00000000..1e303fbe --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/alpha.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/alpha.liquid new file mode 100644 index 00000000..5c92070b --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/alphat.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/alphat.gas new file mode 100644 index 00000000..b867958f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/alphat.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/alphat.liquid new file mode 100644 index 00000000..2569c3ee --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/epsilon.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/epsilon.gas new file mode 100644 index 00000000..707a1cda --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/epsilon.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/epsilon.liquid new file mode 100644 index 00000000..0a4236fd --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/f.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/f.gas new file mode 100644 index 00000000..76ee77a9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/k.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/k.gas new file mode 100644 index 00000000..4a3d44ca --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/k.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/k.liquid new file mode 100644 index 00000000..cde8f6c1 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/nut.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/nut.gas new file mode 100644 index 00000000..ba16dd4c --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/nut.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/nut.liquid new file mode 100644 index 00000000..1442e07f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/p b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/p new file mode 100644 index 00000000..b3a295fb --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/0.orig/p_rgh b/tutorial_cases/OF9/loop_reactor_mixing_swirl/0.orig/p_rgh new file mode 100644 index 00000000..88ee7d80 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/Allclean b/tutorial_cases/OF9/loop_reactor_mixing_swirl/Allclean new file mode 100755 index 00000000..174b6310 --- /dev/null +++ b/tutorial_cases/OF9/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" +rm -rf "processor*" +# rm -f constant/fvModels +rm -f *.obj +rm -f *.stl +rm -f *.txt + +#------------------------------------------------------------------------------ diff --git a/tutorial_cases/OF9/loop_reactor_mixing_swirl/README.md b/tutorial_cases/OF9/loop_reactor_mixing_swirl/README.md new file mode 100644 index 00000000..794e422d --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/computeQOI.sh b/tutorial_cases/OF9/loop_reactor_mixing_swirl/computeQOI.sh new file mode 100644 index 00000000..3756ed7f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/fvModels b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/fvModels new file mode 100644 index 00000000..51497b7c --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/g b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/g new file mode 100644 index 00000000..770a5619 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/globalVars b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/globalVars new file mode 100644 index 00000000..c0dce472 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/globalVars_temp b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/globalVars_temp new file mode 100644 index 00000000..dfddd649 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/momentumTransport.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/momentumTransport.gas new file mode 100644 index 00000000..ca916714 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/momentumTransport.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/momentumTransport.liquid new file mode 100644 index 00000000..2063de0d --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/phaseProperties b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/phaseProperties new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/phaseProperties_constantd b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/phaseProperties_constantd new file mode 100644 index 00000000..e029df99 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/phaseProperties_pbe b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/phaseProperties_pbe new file mode 100644 index 00000000..a3c90f5a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/thermophysicalProperties.gas new file mode 100644 index 00000000..11b1c4b9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid b/tutorial_cases/OF9/loop_reactor_mixing_swirl/constant/thermophysicalProperties.liquid new file mode 100644 index 00000000..d324ec51 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/get_qoi.py b/tutorial_cases/OF9/loop_reactor_mixing_swirl/get_qoi.py new file mode 100644 index 00000000..7f3897ed --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/presteps.sh b/tutorial_cases/OF9/loop_reactor_mixing_swirl/presteps.sh new file mode 100644 index 00000000..bfcff75f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/read_history.py b/tutorial_cases/OF9/loop_reactor_mixing_swirl/read_history.py new file mode 100644 index 00000000..c27eae94 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/run.sh b/tutorial_cases/OF9/loop_reactor_mixing_swirl/run.sh new file mode 100644 index 00000000..8ec96fb0 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/script b/tutorial_cases/OF9/loop_reactor_mixing_swirl/script new file mode 100755 index 00000000..efe675ff --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/script_post b/tutorial_cases/OF9/loop_reactor_mixing_swirl/script_post new file mode 100755 index 00000000..aabbc33e --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/blockMeshDict b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/blockMeshDict new file mode 100644 index 00000000..0bb60950 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/controlDict b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/controlDict new file mode 100644 index 00000000..f4665ed8 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/decomposeParDict b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/decomposeParDict new file mode 100755 index 00000000..f8397e73 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/fvConstraints b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/fvConstraints new file mode 100644 index 00000000..334f1c8f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/fvSchemes b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/fvSchemes new file mode 100644 index 00000000..52e6e13a --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/fvSolution b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/fvSolution new file mode 100644 index 00000000..2e69fdfa --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/inlets_outlets.json b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/inlets_outlets.json new file mode 100644 index 00000000..a083d47f --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/mesh.json b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/mesh.json new file mode 100644 index 00000000..29841d7e --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/mixers.json b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/mixers.json new file mode 100644 index 00000000..4c88041b --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/system/setFieldsDict b/tutorial_cases/OF9/loop_reactor_mixing_swirl/system/setFieldsDict new file mode 100644 index 00000000..89a797b9 --- /dev/null +++ b/tutorial_cases/OF9/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/OF9/loop_reactor_mixing_swirl/writeGlobalVars.py b/tutorial_cases/OF9/loop_reactor_mixing_swirl/writeGlobalVars.py new file mode 100644 index 00000000..e64d69e3 --- /dev/null +++ b/tutorial_cases/OF9/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/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 c58bc65f..00000000 --- a/tutorial_cases/OF9/runall.sh +++ /dev/null @@ -1,53 +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 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