Skip to content

Commit

Permalink
Isothermal domain bc (#684)
Browse files Browse the repository at this point in the history
  • Loading branch information
baperry2 authored Aug 30, 2023
1 parent 59e3145 commit e7ccd20
Show file tree
Hide file tree
Showing 20 changed files with 519 additions and 2 deletions.
11 changes: 11 additions & 0 deletions Docs/sphinx/BoundaryConditions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ PeleC manages boundary conditions in a form consistent with many AMReX codes. Gh

More complex boundary conditions require user input that is prescribed explicitly. Boundaries identified as ``UserBC`` or ``Hard`` in the inputs will be tagged as ``EXT_DIR`` in ``pc_hypfill``. Users will then fill the boundary values, by calling the helper function, ``bcnormal``. The ``bcnormal`` function fills an exterior (ghost) cell based on the value of the outermost interior cell. Its arguments include a problem-specific data structure, the location, direction, and orientation of the boundary being filled, and potentially fluctuating turbulent velocities from the `TurbInflow <https://amrex-combustion.github.io/PelePhysics/Utility.html#turbulent-inflows>`_ utility in PelePhysics. This gives the user flexibility to specify a variety of boundary conditions, including faces that contain both walls and inflow regions. Note that the external state ``s_ext`` is prepopulated with the same values as are used for the ``NoSlipWall`` condition, so the default if the ``bcnormal`` function does nothing is to specify a ``NoSlipWall``.

.. note::
To ensure conservation, when Godunov schemes are used the order of accuracy is reduced at boundaries specified using ``bcnormal``; PLM is used and the predictor step is omitted when computing fluxes through these boundaries. This does not affect any other boundary types or simulations using MOL.

Special care should be taken when prescribing subsonic ``Inflow`` or an ``Outflow`` boundary conditions. It might be tempting to directly impose target values in the boundary filler function (for ``Inflow``), or to perform a simple extrapolation (for ``Outflow``). However, this approach would fail to correctly respect the flow of information along solution characteristics - the system would be ill-posed and would lead to unphysical behavior. In particular, at a subsonic inflow boundary, at a subsonic inlet there is one outgoing characteristic, so one flow variable must be specified using information from inside the domain. Similarly, there is one incoming characteristic at outflow boundaries. The NSCBC method, described below, is the preffered method to account for this, but has not been ported to the all C++ version of PeleC. In the meantime, the recommended strategy for subsonic inflow and outflow boundaries for confined geometries such as nozzles and combustors is as follows:

* Subsonic Inflows: Specify the desired temperature, velocity, and composition (if relevant) in the ghost cells. Take the pressure from the domain interior. Based on these values, compute the density, internal energy, and total energy for the ghost cells.
Expand All @@ -28,6 +31,14 @@ Special care should be taken when prescribing subsonic ``Inflow`` or an ``Outflo

A detailed analysis comparing various boundary condition strategies and demonstrating their implementation is available for the :ref:`EB-ConvergingNozzle` case.

Isothermal Walls
~~~~~~~~~~~~~~~~

By default, the boundaries specified as ``NoSlipWall`` and ``SlipWall`` are adiabatic. For isothermal wall boundaries, energy fluxes through the isothermal wall are computed separately, rather than being based on values populated in the ghost cells. To activate computation of isothermal wallfluxes, use the input file option ``pelec.do_isothermal_walls = 1`` and then specify the desired wall temperatures using, for example, ``pelec.domlo_wall_temp = -1 -1 300.0`` and ``pelec.domhi_isothermal_temp = -1 -1 400.0``, which would leave the x and y boundaries as adiabatic, make the lower z boundary isothermal at 300 K, and make the upper z boundary isothermal at 400 K. Any boundary with a negative (or zero) value for the specified temperature is treated as adiabatic; boundaries that are not ``NoSlipWall``, ``SlipWall``, ``UserBC``, or ``Hard`` must always have a negative value specified.

Navier-Stokes Characteristic Boundary Conditions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. warning::

This following is currently deprecated as the GS-NSCBC boundary condition has not been ported from Fortran to C++.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/sphinx/verification/masscons/figure_dir0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/sphinx/verification/masscons/figure_dir1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 35 additions & 1 deletion Docs/sphinx/verification/verification.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.. role:: cpp(code)
:language: c++


.. _Verification:


Expand Down Expand Up @@ -247,3 +247,37 @@ constant Smagorinsky Large Eddy Simulation model.

.. image:: /verification/les/p_error.png
:width: 300pt

Conservation and Isothermal Boundaries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A simple test cass labeled ``MassCons`` is used to verify mass and energy conservation for all major numerical schemes used in PeleC (MOL without slopes, MOL with slopes, Godunov PLM, Godunov PPM). A python script is also run for all applicable test cases without inflows, outflows, or forcing, to ensure conservation during regression testing to ensure the conservation is maintained. The results shown below demonstrate the machine-precision level conservation of mass and energy for all numerical schemes. The case is arbitrary flow in a box with different types of boundaries (``SlipWall``, ``NoSlipWall``, ``UserBC``, including isothermal options). Note energy is conserved for the isothermal case without hydro turned on because of symmetry in the boundary conditions, but is not conserved for the case with hydro because inclusion of hydrodynamic effects breaks the symmetry.

- Mass Conservation:

.. image:: /verification/masscons/figure_conservation_mass.png

- Energy Conservation:

.. image:: /verification/masscons/figure_conservation_energy.png

This case does not include EB, but the conservation script is run for some of the EB test cases (EB-C9, EB-C11, EB-C12). However, it should be noted that the testing suite does not cover cases where EBs intersect the domain boundary at a sharp angle.

The case with isothermal walls and no hydro allows the convergence of the treatment of diffusion and isothermal boundaries to be verified without using MMS. This case has an initial temperature of 700 K in the 2D domain and temperatures of 600 K, 800 K, 650 K, and 750 K for the low x, high x, low y, and high y boundaries, respectively. Verification is performed at an early time such that thermal diffusion from the various boundaries have not imacted each other yet. Therefore, the solutions are compared against the analytical result for diffusion into a semi-infinite medium:

.. math::
\frac{T - T_{wall}}{T_{0} - T_{wall}} = \rm{erf}(x/\sqrt{4Dt})
where `x` is the distance from the wall.

- x temperature profile:

.. image:: /verification/masscons/figure_dir0.png

- y temperature profile:

.. image:: /verification/masscons/figure_dir1.png

- Convergence:

.. image:: /verification/masscons/figure_convergence.png
85 changes: 85 additions & 0 deletions Exec/RegTests/MassCons/masscons-isothermal-whydro.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# ------------------ INPUTS TO MAIN PROGRAM -------------------
max_step = 400
stop_time = 0.2

# PROBLEM SIZE & GEOMETRY
geometry.is_periodic = 0 0 0
geometry.coord_sys = 0 # 0 => cart, 1 => RZ 2=>spherical
geometry.prob_lo = -0.5 -0.5 -0.5
geometry.prob_hi = 0.5 0.5 0.5
amr.n_cell = 16 16 16

# >>>>>>>>>>>>> BC KEYWORDS <<<<<<<<<<<<<<<<<<<<<<
# Interior, UserBC, Sysmmetry, SlipWall, NoSlipWall
# >>>>>>>>>>>>> BC KEYWORDS <<<<<<<<<<<<<<<<<<<<<<

pelec.lo_bc = "SlipWall" "NoSlipWall" "SlipWall"
pelec.hi_bc = "UserBC" "UserBC" "UserBC"
prob.wall_type = 1 0 1

pelec.do_isothermal_walls = true
pelec.domlo_isothermal_temp = 600 650 670
pelec.domhi_isothermal_temp = 800 750 730

# WHICH PHYSICS
pelec.ppm_type = 0
pelec.do_hydro = 1
pelec.do_mol = 0
pelec.diffuse_vel = 1
pelec.diffuse_temp = 1
pelec.diffuse_spec = 1
pelec.do_react = 0
pelec.diffuse_enth = 1
pelec.add_ext_src = 0
pelec.external_forcing = 0.0 0.0 0.0

transport.const_viscosity = 0
transport.const_conductivity = 2.7271624e+04

# TIME STEP CONTROL
pelec.cfl = 0.8 # cfl number for hyperbolic system
pelec.init_shrink = 1.0 # scale back initial timestep
pelec.change_max = 1.05 # scale back initial timestep
pelec.dt_cutoff = 5.e-20 # level 0 timestep below which we halt
pelec.fixed_dt = 0.4e-6

# DIAGNOSTICS & VERBOSITY
pelec.sum_interval = 1 # timesteps between computing mass
pelec.v = 1 # verbosity in PeleC.cpp
amr.v = 1 # verbosity in Amr.cpp
amr.data_log = datlog

# REFINEMENT / REGRIDDING
amr.max_level = 0 # maximum level number allowed
amr.ref_ratio = 2 2 2 2 # refinement ratio
amr.regrid_int = 2 2 2 2 # how often to regrid
amr.blocking_factor = 4 # block factor in grid generation
amr.max_grid_size = 64
amr.n_error_buf = 12 8 2 2 # number of buffer cells in error est

# CHECKPOINT FILES
amr.checkpoint_files_output = 0
amr.check_file = chk # root name of checkpoint file
amr.check_int = 500 # number of timesteps between checkpoints

# PLOTFILES
amr.plot_files_output = 1
amr.plot_file = plt # root name of plotfile
amr.plot_int = 400 # number of timesteps between plotfiles
amr.plot_vars = density Temp
amr.derive_plot_vars = x_velocity y_velocity z_velocity magvel magvort pressure
pelec.plot_rhoy = 0
pelec.plot_massfrac = 1

# PROBLEM PARAMETERS
prob.T_mean = 700.0
prob.u0 = 0.0
prob.v0 = 0.0
prob.w0 = 0.0

# Problem setup
eb2.geom_type = "all_regular"

amrex.fpe_trap_invalid = 0
amrex.fpe_trap_zero = 0
amrex.fpe_trap_overflow = 0
85 changes: 85 additions & 0 deletions Exec/RegTests/MassCons/masscons-isothermal.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# ------------------ INPUTS TO MAIN PROGRAM -------------------
max_step = 400
stop_time = 0.2

# PROBLEM SIZE & GEOMETRY
geometry.is_periodic = 0 0 0
geometry.coord_sys = 0 # 0 => cart, 1 => RZ 2=>spherical
geometry.prob_lo = -0.5 -0.5 -0.5
geometry.prob_hi = 0.5 0.5 0.5
amr.n_cell = 16 16 16

# >>>>>>>>>>>>> BC KEYWORDS <<<<<<<<<<<<<<<<<<<<<<
# Interior, UserBC, Symmetry, SlipWall, NoSlipWall
# >>>>>>>>>>>>> BC KEYWORDS <<<<<<<<<<<<<<<<<<<<<<

pelec.lo_bc = "SlipWall" "NoSlipWall" "SlipWall"
pelec.hi_bc = "UserBC" "UserBC" "UserBC"
prob.wall_type = 1 0 1

pelec.do_isothermal_walls = true
pelec.domlo_isothermal_temp = 600 650 670
pelec.domhi_isothermal_temp = 800 750 730

# WHICH PHYSICS
pelec.ppm_type = 0
pelec.do_hydro = 0
pelec.do_mol = 0
pelec.diffuse_vel = 1
pelec.diffuse_temp = 1
pelec.diffuse_spec = 1
pelec.do_react = 0
pelec.diffuse_enth = 1
pelec.add_ext_src = 0
pelec.external_forcing = 0.0 0.0 0.0

transport.const_viscosity = 0
transport.const_conductivity = 2.7271624e+04

# TIME STEP CONTROL
pelec.cfl = 0.8 # cfl number for hyperbolic system
pelec.init_shrink = 1.0 # scale back initial timestep
pelec.change_max = 1.05 # scale back initial timestep
pelec.dt_cutoff = 5.e-20 # level 0 timestep below which we halt
pelec.fixed_dt = 0.4e-6

# DIAGNOSTICS & VERBOSITY
pelec.sum_interval = 1 # timesteps between computing mass
pelec.v = 1 # verbosity in PeleC.cpp
amr.v = 1 # verbosity in Amr.cpp
amr.data_log = datlog

# REFINEMENT / REGRIDDING
amr.max_level = 0 # maximum level number allowed
amr.ref_ratio = 2 2 2 2 # refinement ratio
amr.regrid_int = 2 2 2 2 # how often to regrid
amr.blocking_factor = 4 # block factor in grid generation
amr.max_grid_size = 64
amr.n_error_buf = 12 8 2 2 # number of buffer cells in error est

# CHECKPOINT FILES
amr.checkpoint_files_output = 0
amr.check_file = chk # root name of checkpoint file
amr.check_int = 500 # number of timesteps between checkpoints

# PLOTFILES
amr.plot_files_output = 1
amr.plot_file = plt # root name of plotfile
amr.plot_int = 400 # number of timesteps between plotfiles
amr.plot_vars = density Temp
amr.derive_plot_vars = x_velocity y_velocity z_velocity magvel magvort pressure
pelec.plot_rhoy = 0
pelec.plot_massfrac = 1

# PROBLEM PARAMETERS
prob.T_mean = 700.0
prob.u0 = 0.0
prob.v0 = 0.0
prob.w0 = 0.0

# Problem setup
eb2.geom_type = "all_regular"

amrex.fpe_trap_invalid = 0
amrex.fpe_trap_zero = 0
amrex.fpe_trap_overflow = 0
62 changes: 62 additions & 0 deletions Exec/RegTests/MassCons/run_isothermal_study.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt
from scipy.special import erf

npoints = [16, 32, 64, 128, 256]

#for grid in grid:
alpha = 7.5362000690846E+00

pltfile = 'plt00400'

error = {}
for ngrid in npoints:
error[ngrid] = {}
os.system('rm -r plt*0')
os.system('mpirun -n 4 PeleC2d.gnu.MPI.ex masscons-isothermal.inp amr.n_cell="{} {} {}"'.format(ngrid, ngrid, ngrid))
for idir in ['0', '1']:
os.system('fextract.gnu.ex -d {} -s slice{} {}'.format(idir,idir,pltfile))
fname = 'slice'+idir
os.system("sed 's/\#/ /g' "+fname+" > "+fname+'_')
data = pd.read_csv(fname+'_', skiprows=2, sep='\s+')

with open(fname) as f:
junk = f.readline()
timetext = f.readline()
time = float(timetext.split()[-1])

coord = {'0':'x','1':'y','2':'z'}[idir]

data['zeta1'] = (data[coord] + 0.5) /np.sqrt(4 * alpha * time)
data['zeta2'] = (0.5 - data[coord]) /np.sqrt(4 * alpha * time)

dT = {'0':100,'1':50,'2':30}[idir]

data['Tdelta2'] = -dT * erf(data['zeta2'] )
data['Tdelta1'] = dT * erf(data['zeta1'] )
data['Ttrue' ] = 700.0 + data['Tdelta2'] + data['Tdelta1']

plt.figure(idir)
plt.plot(data[coord], data['Temp'], '-',label=ngrid)
if ngrid == npoints[-1]:
plt.plot(data[coord], data['Ttrue'], 'k:', label ='analytical')
plt.legend(frameon=False)
plt.xlabel(coord + ' (cm)')
plt.ylabel('T (K)')
error[ngrid][idir+'max'] = np.max(np.abs( data['Ttrue' ] - data['Temp'] )) #np.linalg.norm( data['Ttrue' ] - data['Temp'], ord=2) / np.sqrt(len(data[coord]))
error[ngrid][idir+'mse'] = np.linalg.norm( data['Ttrue' ] - data['Temp'], ord=2) / np.sqrt(len(data[coord]))
plt.savefig("figure_dir"+idir+'.png')

error = pd.DataFrame(error).T
print(error)
plt.figure()
plt.loglog(error.index, error['0mse'], 'r-o', label='x-direction')
plt.loglog(error.index, error['1mse'], 'b-o', label='y-direction')
plt.loglog(error.index, 100*(1.0/error.index)**2, 'k:', label='2nd order')
plt.ylabel('Error')
plt.xlabel('N')
plt.xlim([8,512])
plt.legend(frameon=False)
plt.savefig('figure_convergence.png')
37 changes: 37 additions & 0 deletions Exec/RegTests/MassCons/run_masscons_study.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt

inputs = ['mol-1', 'mol-2', 'plm', 'ppm', 'isothermal', 'isothermal-whydro']

for iname in inputs:
os.system('rm -r datlog plt*0')
os.system('./PeleC2d.gnu.MPI.ex masscons-{}.inp max_step=200'.format(iname))
data = pd.read_fwf('datlog')
plt.figure('mass')
plt.plot(data.index, (data['mass']-data['mass'][0])/data['mass'][0], label=iname)

if iname is not 'isothermal-whydro':
plt.figure('energy')
plt.plot(data.index, (data['rho_E']-data['rho_E'][0])/data['rho_E'][0], label = iname)

plt.figure('mass')
plt.xlabel('Timestep')
plt.ylabel('Relative Mass Change')
plt.ylim([-1e-14, 1e-14])
plt.legend(frameon=False)
plt.tight_layout()
plt.savefig('figure_conservation_mass.png')
plt.clf()
plt.close()

plt.figure('energy')
plt.xlabel('Timestep')
plt.ylabel('Relative Energy Change')
plt.ylim([-1e-14, 1e-14])
plt.legend(frameon=False)
plt.tight_layout()
plt.savefig('figure_conservation_energy.png')
plt.clf()
plt.close()
Loading

0 comments on commit e7ccd20

Please sign in to comment.