diff --git a/.clang-tidy b/.clang-tidy index cb5335d..451691f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -16,6 +16,7 @@ Checks: 'bugprone-*, -readability-function-cognitive-complexity' WarningsAsErrors: '' HeaderFilterRegex: '.*' +HeaderFileExtensions: ['', "H", 'h', 'hh', 'hpp', 'hxx'] FormatStyle: none User: user CheckOptions: @@ -55,6 +56,12 @@ CheckOptions: value: llvm - key: modernize-use-nullptr.NullMacros value: 'NULL' + - { key: readability-identifier-length.MinimumVariableNameLength, value: 2 } + - { key: readability-identifier-length.IgnoredVariableNames, value: "^[ijkp]$" } + - { key: readability-identifier-length.MinimumParameterNameLength, value: 2 } + - { key: readability-identifier-length.IgnoredParameterNames, value: "^[ijknp]$" } + - { key: readability-identifier-length.MinimumExceptionNameLength, value: 2 } + - { key: readability-identifier-length.MinimumLoopCounterNameLength, value: 1 } - { key: readability-identifier-naming.NamespaceCase, value: lower_case } - { key: readability-identifier-naming.ClassCase, value: CamelCase } - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c81aadd..9793f40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV - name: Install Ccache run: | wget https://github.com/ccache/ccache/releases/download/v4.8/ccache-4.8-linux-x86_64.tar.xz @@ -143,7 +143,7 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV cmake -E make_directory ${{runner.workspace}}/deps - name: Dependencies run: | @@ -264,7 +264,7 @@ jobs: GPU-AMD: name: GPU-HIP needs: [Formatting, CPU-GNUmake] - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone uses: actions/checkout@v4 @@ -276,18 +276,17 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV - name: Dependencies run: | ${{github.workspace}}/Submodules/AMReX/.github/workflows/dependencies/ubuntu_free_disk_space.sh - curl -O https://repo.radeon.com/rocm/rocm.gpg.key - sudo apt-key add rocm.gpg.key - echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/5.6.1/ ubuntu main' \ - | sudo tee /etc/apt/sources.list.d/rocm.list - echo 'export PATH=/opt/rocm/llvm/bin:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin:$PATH' \ - | sudo tee -a /etc/profile.d/rocm.sh + sudo mkdir --parents --mode=0755 /etc/apt/keyrings + wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | gpg --dearmor | sudo tee /etc/apt/keyrings/rocm.gpg > /dev/null + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/rocm/apt/6.3.3 noble main" | sudo tee --append /etc/apt/sources.list.d/rocm.list + echo -e 'Package: *\nPin: release o=repo.radeon.com\nPin-Priority: 600' | sudo tee /etc/apt/preferences.d/rocm-pin-600 + echo 'export PATH=/opt/rocm/llvm/bin:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin:$PATH' | sudo tee -a /etc/profile.d/rocm.sh sudo apt-get update - sudo apt-get install -y rocm-dev rocrand-dev rocprim-dev + sudo apt-get install -y --no-install-recommends build-essential rocm-dev rocrand-dev rocprim-dev hiprand-dev - name: Install Ccache run: | wget https://github.com/ccache/ccache/releases/download/v4.8/ccache-4.8-linux-x86_64.tar.xz @@ -346,7 +345,7 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV echo "CCACHE_DEPEND=1" >> $GITHUB_ENV - name: Dependencies run: | @@ -458,7 +457,7 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV - name: Install Ccache run: | wget https://github.com/ccache/ccache/releases/download/v4.8/ccache-4.8-linux-x86_64.tar.xz @@ -520,7 +519,7 @@ jobs: echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV echo "CCACHE_COMPRESSLEVEL=5" >> $GITHUB_ENV echo "CCACHE_LOGFILE=${{github.workspace}}/ccache.log.txt" >> $GITHUB_ENV - echo "CCACHE_MAXSIZE=1G" >> $GITHUB_ENV + echo "CCACHE_MAXSIZE=500M" >> $GITHUB_ENV - name: Install Ccache run: | wget https://github.com/ccache/ccache/releases/download/v4.8/ccache-4.8-linux-x86_64.tar.xz diff --git a/Build/GNUmakefile b/Build/GNUmakefile index fa6eddd..644897f 100644 --- a/Build/GNUmakefile +++ b/Build/GNUmakefile @@ -9,7 +9,7 @@ DIM = 3 COMP = gnu -USE_MPI = TRUE +USE_MPI = TRUE USE_OMP = FALSE USE_CUDA = FALSE USE_EB = TRUE diff --git a/Docs/sphinx/LBM.rst b/Docs/sphinx/LBM.rst index a83b15d..47487dc 100644 --- a/Docs/sphinx/LBM.rst +++ b/Docs/sphinx/LBM.rst @@ -50,4 +50,9 @@ where :math:`u` is the velocity vector, :math:`\rho` is the density, :math:`w_i` u(x, t) &= \frac{1}{\rho} \sum_{i} e_i f_i(x, t) -MARBLES implements both the D2Q9 and D3Q27 LBM approaches for two dimensional and three dimensional flow, respectively. +MARBLES implements both the D3Q27 LBM approach for two dimensional and three dimensional flow, respectively. + +For the thermal version of MARBLES, please refer to additional theory related to the additional energy lattice and cross coupling, +in the PhD thesis +"Sawant, Nilesh. 'Kinetic Modeling of Reactive Flows.'. ETH Zurich, 2023. https://doi.org/10.3929/ETHZ-B-000607045." + diff --git a/Docs/sphinx/VandV.rst b/Docs/sphinx/VandV.rst index fd55618..8de1b2a 100644 --- a/Docs/sphinx/VandV.rst +++ b/Docs/sphinx/VandV.rst @@ -24,3 +24,54 @@ This demonstrates MARBLES ability to simulate flow through complex, porous media .. image:: /figs/pine_box.gif :width: 600pt + + +Viscosity verification +---------------------- + +This test case demonstrates MARBLES ability to maintain the correct viscosity over a wide range of temperatures. +Viscosity is computed from the simulation by tracking the maximum of velocity over time arising from an initial +condition consisting of a sinusoidal velocity perturbation. +The temperature is not restricted to 1/3, but it can be set to any value less than or equal to 1/3. +This feature has been enabled by incorporating product-form of the equilibrium distribition which +improves stability due to maximisation of the entropy and the incorporation of an extended lattice +Boltzmann approach which adds a non-local correction term to the pressure tensor to correct the insufficient +Galilean invariance of the standard lattice at the third order moment. + +Input and post processing files: `Tests/test_files/viscosityTest/` + +.. image:: /figs/kinematicViscosity.png + :width: 400pt + + +Thermal diffusivity verification +--------------------------------- + +This test case demonstrates MARBLES ability to maintain the correct thermal diffusivity over a wide range of temperatures, +as well as at different Prandtl numbers, adiabatic exponents and mean molecular masses. +Themal diffusivity is computed from the simulation by tracking the maximum of temperature over time arising from an initial +condition consisting of a sinusoidal temperature perturbation. +The capability to solve for temperature has been enabled by an additional lattice which conserves the total energy of the fluid. +The new lattice representing energy has been two way coupled with the existing momentum lattice which had been augmented with +product-form equilibrium and extended pressure term to compensate the third order error. The new energy lattice adds an +energy equation, while the multi-relaxation on the energy lattice enables a variable Prandtl number and an adjustable adiabatic +exponent. The mean molecular mass is allowed to be a variable because the product form of the equilibrium on the +first lattice allows the variance of the equilibrium distribution to be RT instead of T. + +Input and post processing files: `Tests/test_files/thermalDiffusivityTest/` + +.. image:: /figs/thermalDiffusivity.png + :width: 400pt + +Sod test tube +---------------------- + +This test case demonstrates MARBLES ability to solve compressible flows with realistic parameters of practical interest. +The correct position of the wave structures confirm that the speed of sound is correct in the thermal version of the solver. The model +is the same as that built for the thermal diffusivity test. The sod shock test marks the completion of the MARBLES solver to the +extent of a contunuum limit, single-component, single-phase, transient computational fluid dynamics solver with mass, momentum and energy equations. + +Input and post processing files: `Tests/test_files/sodTest/` + +.. image:: /figs/sodShock.png + :width: 600pt \ No newline at end of file diff --git a/Docs/sphinx/figs/kinematicViscosity.png b/Docs/sphinx/figs/kinematicViscosity.png new file mode 100644 index 0000000..d60d7f1 Binary files /dev/null and b/Docs/sphinx/figs/kinematicViscosity.png differ diff --git a/Docs/sphinx/figs/sodShock.png b/Docs/sphinx/figs/sodShock.png new file mode 100644 index 0000000..1c2850a Binary files /dev/null and b/Docs/sphinx/figs/sodShock.png differ diff --git a/Docs/sphinx/figs/thermalDiffusivity.png b/Docs/sphinx/figs/thermalDiffusivity.png new file mode 100644 index 0000000..d173123 Binary files /dev/null and b/Docs/sphinx/figs/thermalDiffusivity.png differ diff --git a/Source/BC.H b/Source/BC.H index 5367bfe..f333e3f 100644 --- a/Source/BC.H +++ b/Source/BC.H @@ -14,8 +14,10 @@ static constexpr int PERIODIC = 0; static constexpr int NOSLIPWALL = 1; static constexpr int VELOCITY = 2; static constexpr int PRESSURE = 3; -static constexpr int OUTFLOW = 4; static constexpr int OUTFLOW_ZEROTH_ORDER = 5; +static constexpr int SLIPWALLXNORMAL = 6; +static constexpr int SLIPWALLYNORMAL = 7; +static constexpr int SLIPWALLZNORMAL = 8; template struct BCFill @@ -27,13 +29,23 @@ struct BCFill stencil::Stencil().evs; const amrex::GpuArray m_bounce_dirs = stencil::Stencil().bounce_dirs; + const amrex::GpuArray m_bounce_Xdir = + stencil::Stencil().bounce_Xdir; + const amrex::GpuArray m_bounce_Ydir = + stencil::Stencil().bounce_Ydir; + const amrex::GpuArray m_bounce_Zdir = + stencil::Stencil().bounce_Zdir; const amrex::GpuArray m_weights = stencil::Stencil().weights; + const amrex::Real m_theta0 = stencil::Stencil::THETA0; + amrex::RealVect m_zero_vec = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + const amrex::Real m_mesh_speed; const amrex::GpuArray m_bc_type = {0}; const amrex::IntVect m_ng = {AMREX_D_DECL(0, 0, 0)}; const VelBCOpType m_vel_bc_op; + bool m_is_energy_lattice; AMREX_GPU_HOST constexpr explicit BCFill( @@ -41,11 +53,13 @@ struct BCFill const amrex::GpuArray& bc_type, const amrex::IntVect& ng, - const VelBCOpType& vel_bc_op) + const VelBCOpType& vel_bc_op, + const bool& m_is_energy_lattice_ = false) : m_mesh_speed(mesh_speed) , m_bc_type(bc_type) , m_ng(ng) , m_vel_bc_op(vel_bc_op) + , m_is_energy_lattice(m_is_energy_lattice_) {} AMREX_GPU_DEVICE @@ -69,14 +83,123 @@ struct BCFill AMREX_GPU_DEVICE AMREX_FORCE_INLINE - void velocity_bc( + void bounce_back_xbc( + const amrex::IntVect& iv, + const int q, + const amrex::IntVect& ev, + amrex::Array4 const& data) const + { + // Prepare the ghost cell layer of f_ for + // streaming due to bounce back. 2D e.g., for + // the ghost cell at at (-1, -1), store the + // value f_(0, 0) associated with e=[-1, -1] and + // orient it such that it points e=[1, 1]. This + // reproduces the bounce back effect directly + // when the streaming step is performed. + + data(iv, q) = data(iv + ev, m_bounce_Xdir[q]); + } + + AMREX_GPU_DEVICE + AMREX_FORCE_INLINE + void bounce_back_ybc( + const amrex::IntVect& iv, + const int q, + const amrex::IntVect& ev, + amrex::Array4 const& data) const + { + // Prepare the ghost cell layer of f_ for + // streaming due to bounce back. 2D e.g., for + // the ghost cell at at (-1, -1), store the + // value f_(0, 0) associated with e=[-1, -1] and + // orient it such that it points e=[1, 1]. This + // reproduces the bounce back effect directly + // when the streaming step is performed. + + data(iv, q) = data(iv + ev, m_bounce_Ydir[q]); + } + + AMREX_GPU_DEVICE + AMREX_FORCE_INLINE + void bounce_back_zbc( + const amrex::IntVect& iv, + const int q, + const amrex::IntVect& ev, + amrex::Array4 const& data) const + { + // Prepare the ghost cell layer of f_ for + // streaming due to bounce back. 2D e.g., for + // the ghost cell at at (-1, -1), store the + // value f_(0, 0) associated with e=[-1, -1] and + // orient it such that it points e=[1, 1]. This + // reproduces the bounce back effect directly + // when the streaming step is performed. + + data(iv, q) = data(iv + ev, m_bounce_Zdir[q]); + } + + AMREX_GPU_DEVICE + AMREX_FORCE_INLINE + void velocity_bc_g( + const amrex::IntVect& iv, + const int q, + const amrex::IntVect& ev, + const int /*idir*/, + const int /*ndir*/, + const amrex::Real& rho_bc, + const amrex::RealVect& vel_bc, + const amrex::Real& R, + const amrex::Real& temperature, + const amrex::Real& adiabatic_exponent, + amrex::Array4 const& data) const + { + // Prepare the ghost cell layer of f_ for + // streaming due to a prescribed velocity. This + // is done by assigning all the values of f_ on + // this ghost layer to be the equilibrium + // distributions associated with the desired + // velocity. They will naturally exert their + // effect on the interior fluid points during + // the streaming step. + + // In this case, a value for u, v, and w must be + // specified, either hard coded or set by a + // user-specified function + + const amrex::Real cv = R / (adiabatic_exponent - 1.0); + + const amrex::Real two_rho_e = + get_energy(temperature, rho_bc, vel_bc, cv); + + amrex::Real rxx_eq(0.0), ryy_eq(0.0), rzz_eq(0.0), rxy_eq(0.0), + rxz_eq(0.0), ryz_eq(0.0); + + amrex::RealVect heat_flux = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + get_equilibrium_moments( + rho_bc, vel_bc, two_rho_e, cv, R, heat_flux, rxx_eq, ryy_eq, rzz_eq, + rxy_eq, rxz_eq, ryz_eq); + + amrex::GpuArray flux_of_heat_flux = { + rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, ryz_eq}; + + set_extended_grad_expansion_generic( + two_rho_e, heat_flux, flux_of_heat_flux, m_mesh_speed, m_weights[q], + ev, m_theta0, m_zero_vec, 1.0, data(iv, q)); + } + + AMREX_GPU_DEVICE + AMREX_FORCE_INLINE + void velocity_bc_f( const amrex::IntVect& iv, const int q, const amrex::IntVect& ev, const int idir, const int ndir, const amrex::RealVect& vel_bc, - amrex::Array4 const& data) const + const amrex::Real& RT, + amrex::Array4 const& data, + amrex::Real& rho_bc_out) const { // Prepare the ghost cell layer of f_ for // streaming due to a prescribed velocity. This @@ -114,19 +237,23 @@ struct BCFill (rho_out + rho_tan) / (1.0 - ndir * vel_bc[idir]); set_equilibrium_value( - rho_bc, vel_bc, m_mesh_speed, m_weights[q], ev, data(iv, q)); + rho_bc, vel_bc, RT, m_mesh_speed, m_weights[q], ev, data(iv, q)); + + rho_bc_out = rho_bc; } AMREX_GPU_DEVICE AMREX_FORCE_INLINE - void pressure_bc( + void pressure_bc_f( const amrex::IntVect& iv, const int q, const amrex::IntVect& ev, const int idir, const int ndir, const amrex::Real rho_bc, - amrex::Array4 const& data) const + const amrex::Real& RT, + amrex::Array4 const& data, + amrex::Real& rho_bc_out) const { // Prepare the ghost cell layer of f_ for // streaming due to a prescribed @@ -161,64 +288,61 @@ struct BCFill vel_bc[idir] = ndir * (1.0 - (rho_out + rho_tan) / rho_bc); set_equilibrium_value( - rho_bc, vel_bc, m_mesh_speed, m_weights[q], ev, data(iv, q)); + rho_bc, vel_bc, RT, m_mesh_speed, m_weights[q], ev, data(iv, q)); + + rho_bc_out = rho_out + rho_tan; } AMREX_GPU_DEVICE AMREX_FORCE_INLINE - void outflow_bc( + void pressure_bc_g( const amrex::IntVect& iv, const int q, const amrex::IntVect& ev, const int idir, const int ndir, + const amrex::Real rho_bc_out, + const amrex::Real rho_bc, + const amrex::Real& R, + const amrex::Real& temperature, + const amrex::Real& adiabatic_exponent, amrex::Array4 const& data) const { // Prepare the ghost cell layer of f_ for - // streaming due to an outflow condition This - // copies the rate of change from the last two - // interior cell onto the ghost layer such that - // when streaming you have the effect of "no - // change" in the direction across the boundary. - amrex::IntVect iv_shift(amrex::IntVect::TheDimensionVector(idir)); + // streaming due to a prescribed + // pressure/density. This is done by assigning + // all the values of f_ on this ghost layer to + // be the equilibrium distributions associated + // with the desired density. They will naturally + // exert their effect on the interior fluid + // points during the streaming step. - if (AMREX_D_TERM( - ndir * iv_shift[0] == ev[0], &&ndir * iv_shift[1] == ev[1], - &&ndir * iv_shift[2] == ev[2])) { - - amrex::Real rho = 0.0; - amrex::RealVect vel(AMREX_D_DECL(0.0, 0.0, 0.0)); - for (int qq = 0; qq < constants::N_MICRO_STATES; qq++) { - rho += data(iv + ndir * iv_shift, qq); - const auto& ev_qq = m_evs[qq]; - AMREX_D_DECL( - vel[0] += ev_qq[0] * data(iv + ndir * iv_shift, qq), - vel[1] += ev_qq[1] * data(iv + ndir * iv_shift, qq), - vel[2] += ev_qq[2] * data(iv + ndir * iv_shift, qq)); - } + // Build the 3-part rho calculation at the + // (iv+ev) fluid cell - vel *= m_mesh_speed / rho; + amrex::RealVect vel_bc(AMREX_D_DECL(0.0, 0.0, 0.0)); + vel_bc[idir] = ndir * (1.0 - (rho_bc_out) / rho_bc); - amrex::Real f_eq = 0.0; - amrex::Real f_star_eq = 0.0; + const amrex::Real cv = R / (adiabatic_exponent - 1.0); - const int bounce_q = m_bounce_dirs[q]; - const auto& ev_star = m_evs[bounce_q]; + const amrex::Real two_rho_e = + get_energy(temperature, rho_bc, vel_bc, cv); - set_equilibrium_value( - rho, vel, m_mesh_speed, m_weights[q], ev, f_eq); + amrex::Real rxx_eq(0.0), ryy_eq(0.0), rzz_eq(0.0), rxy_eq(0.0), + rxz_eq(0.0), ryz_eq(0.0); - set_equilibrium_value( - rho, vel, m_mesh_speed, m_weights[bounce_q], ev_star, - f_star_eq); + amrex::RealVect heat_flux = {AMREX_D_DECL(0.0, 0.0, 0.0)}; - data(iv, q) = - f_eq + data(iv + ndir * iv_shift, bounce_q) - f_star_eq; + get_equilibrium_moments( + rho_bc, vel_bc, two_rho_e, cv, R, heat_flux, rxx_eq, ryy_eq, rzz_eq, + rxy_eq, rxz_eq, ryz_eq); - } else { - data(iv, q) = 2.0 * data(iv + 1 * ndir * iv_shift, q) - - data(iv + 2 * ndir * iv_shift, q); - } + amrex::GpuArray flux_of_heat_flux = { + rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, ryz_eq}; + + set_extended_grad_expansion_generic( + two_rho_e, heat_flux, flux_of_heat_flux, m_mesh_speed, m_weights[q], + ev, m_theta0, m_zero_vec, 1.0, data(iv, q)); } AMREX_GPU_DEVICE @@ -290,24 +414,76 @@ struct BCFill // bounds if (inside.contains(ivn)) { - if (m_bc_type[bc_idx] == 1) { + if (m_bc_type[bc_idx] == NOSLIPWALL) { bounce_back_bc(iv, q, ev, data); - } else if (m_bc_type[bc_idx] == 2) { + } else if (m_bc_type[bc_idx] == VELOCITY) { amrex::RealVect vel_bc( AMREX_D_DECL(0.0, 0.0, 0.0)); + amrex::Real specific_gas_constant(1.0), + temperature(1.0 / 3.0); + amrex::Real gamma(5.0 / 3.0); + + amrex::Real rho_bcout(1.0); + m_vel_bc_op( - iv, idir, normal_dir, time, geom, vel_bc); - velocity_bc( - iv, q, ev, idir, normal_dir, vel_bc, data); - } else if (m_bc_type[bc_idx] == 3) { + iv, idir, normal_dir, time, geom, vel_bc, + specific_gas_constant, temperature, gamma); + + if (m_is_energy_lattice) { + rho_bcout = 1.0; + + velocity_bc_g( + iv, q, ev, idir, normal_dir, rho_bcout, + vel_bc, specific_gas_constant, + temperature, gamma, data); + } else { + velocity_bc_f( + iv, q, ev, idir, normal_dir, vel_bc, + specific_gas_constant * temperature, + data, rho_bcout); + } + + } else if (m_bc_type[bc_idx] == PRESSURE) { + const amrex::Real rho_bc = 1.0; - pressure_bc( - iv, q, ev, idir, normal_dir, rho_bc, data); - } else if (m_bc_type[bc_idx] == 4) { - outflow_bc(iv, q, ev, idir, normal_dir, data); - } else if (m_bc_type[bc_idx] == 5) { + + amrex::RealVect vel_bc( + AMREX_D_DECL(0.0, 0.0, 0.0)); + amrex::Real specific_gas_constant(1.0), + temperature(1.0 / 3.0); + amrex::Real gamma(5.0 / 3.0); + + amrex::Real rho_bcout(1.0); + + m_vel_bc_op( + iv, idir, normal_dir, time, geom, vel_bc, + specific_gas_constant, temperature, gamma); + + if (m_is_energy_lattice) { + + rho_bcout = 1.0; + pressure_bc_g( + iv, q, ev, idir, normal_dir, rho_bcout, + rho_bc, specific_gas_constant, + temperature, gamma, data); + + } else { + pressure_bc_f( + iv, q, ev, idir, normal_dir, rho_bc, + specific_gas_constant * temperature, + data, rho_bcout); + } + + } else if ( + m_bc_type[bc_idx] == OUTFLOW_ZEROTH_ORDER) { simple_outflow_bc( iv, q, ev, idir, normal_dir, data); + } else if (m_bc_type[bc_idx] == SLIPWALLXNORMAL) { + bounce_back_xbc(iv, q, ev, data); + } else if (m_bc_type[bc_idx] == SLIPWALLYNORMAL) { + bounce_back_ybc(iv, q, ev, data); + } else if (m_bc_type[bc_idx] == SLIPWALLZNORMAL) { + bounce_back_zbc(iv, q, ev, data); } } } @@ -326,20 +502,27 @@ struct BCOpCreator explicit BCOpCreator( const amrex::Real& mesh_speed, const amrex::GpuArray& bc_type, - const amrex::IntVect& ng) - : m_mesh_speed(mesh_speed), m_bc_type(bc_type), m_ng(ng), m_vel_bc_op() + const amrex::IntVect& ng, + bool m_is_energy_lattice_ = false) + : m_mesh_speed(mesh_speed) + , m_bc_type(bc_type) + , m_ng(ng) + , m_vel_bc_op() + , m_is_energy_lattice(m_is_energy_lattice_) {} FunctorType operator()() const { return FunctorType{ - m_mesh_speed, m_bc_type, m_ng, m_vel_bc_op.device_instance()}; + m_mesh_speed, m_bc_type, m_ng, m_vel_bc_op.device_instance(), + m_is_energy_lattice}; } const amrex::Real m_mesh_speed; const amrex::GpuArray m_bc_type = {0}; const amrex::IntVect m_ng = {AMREX_D_DECL(0, 0, 0)}; VelBCOp m_vel_bc_op; + bool m_is_energy_lattice; }; } // namespace lbm::bc diff --git a/Source/Constants.H b/Source/Constants.H index 55da79a..e0a4aaa 100644 --- a/Source/Constants.H +++ b/Source/Constants.H @@ -4,25 +4,48 @@ #include namespace lbm::constants { -static constexpr int N_MACRO_STATES = 5; + +static constexpr int N_MACRO_STATES = 19; static constexpr int RHO_IDX = 0; static constexpr int VELX_IDX = 1; static constexpr int VELY_IDX = 2; static constexpr int VELZ_IDX = 3; static constexpr int VMAG_IDX = 4; +static constexpr int TWO_RHO_E_IDX = 5; +static constexpr int Q_CORR_X_IDX = 6; +static constexpr int Q_CORR_Y_IDX = 7; +static constexpr int Q_CORR_Z_IDX = 8; + +static constexpr int PXX_IDX = 9; +static constexpr int PYY_IDX = 10; +static constexpr int PZZ_IDX = 11; +static constexpr int PXY_IDX = 12; +static constexpr int PXZ_IDX = 13; +static constexpr int PYZ_IDX = 14; + +static constexpr int QX_IDX = 15; +static constexpr int QY_IDX = 16; +static constexpr int QZ_IDX = 17; + +static constexpr int TEMPERATURE_IDX = 18; + #if AMREX_SPACEDIM == 2 static constexpr int N_MICRO_STATES = 9; #else static constexpr int N_MICRO_STATES = 27; #endif -static constexpr int N_DERIVED = 4; +static constexpr int N_DERIVED = 7; static constexpr int VORTX_IDX = 0; static constexpr int VORTY_IDX = 1; static constexpr int VORTZ_IDX = 2; static constexpr int VORTM_IDX = 3; +static constexpr int D_Q_CORR_X_IDX = 4; +static constexpr int D_Q_CORR_Y_IDX = 5; +static constexpr int D_Q_CORR_Z_IDX = 6; + static constexpr int N_IS_FLUID = 2; static constexpr amrex::Real ROOT3 = @@ -40,6 +63,8 @@ static constexpr amrex::Real LARGE_NUM = static constexpr int DATWIDTH = 24; static constexpr int DATPRECISION = 16; +static constexpr amrex::Real AIR_MOLAR_MASS = 28.96; + } // namespace lbm::constants #endif diff --git a/Source/FillPatchOps.H b/Source/FillPatchOps.H index d4fd103..74b0362 100644 --- a/Source/FillPatchOps.H +++ b/Source/FillPatchOps.H @@ -37,12 +37,14 @@ public: const amrex::Vector& ref_ratio, const amrex::Vector& bcs, BCOpCreator bc_op, - amrex::Vector& f_) + amrex::Vector& f_, + bool is_energy_lattice = false) : m_geom(geom) , m_ref_ratio(ref_ratio) , m_bcs(bcs) , m_op(std::move(bc_op)) , m_f(f_) + , m_is_energy_lattice(is_energy_lattice) {} // compute a new multifab by coping in phi from valid region and filling @@ -133,6 +135,7 @@ protected: const BCOpCreator m_op; amrex::Vector& m_f; amrex::Interpolater* m_mapper = &amrex::cell_cons_interp; + bool m_is_energy_lattice; }; } // namespace lbm #endif diff --git a/Source/IC.H b/Source/IC.H index 1e84216..80db6db 100644 --- a/Source/IC.H +++ b/Source/IC.H @@ -16,6 +16,17 @@ struct Constant { amrex::Real density{1.0}; amrex::RealVect velocity = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + amrex::RealVect mach_components = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; AMREX_GPU_DEVICE void operator()( @@ -27,6 +38,23 @@ struct Constant rho = density; vel = velocity; } + + AMREX_GPU_DEVICE void thermal_initialise( + const amrex::IntVect& /*iv*/, + amrex::GeometryData const& /*geom*/, + amrex::Real& rho, + amrex::RealVect& vel, + amrex::Real& temperature, + amrex::Real& R, + amrex::Real& gamma) const + { + rho = density; + vel = velocity; + + temperature = initial_temperature; + R = R_u / m_bar; + gamma = adiabatic_exponent; + } }; using DeviceType = DeviceOp; @@ -49,6 +77,16 @@ struct TaylorGreen amrex::RealVect omega = {AMREX_D_DECL(1.0, 1.0, 1.0)}; amrex::Real L{1.0 / M_PI}; + amrex::Real initial_temperature = 1.0 / 3.0; + const amrex::Real adiabatic_exponent = 5.0 / 3.0; + + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + AMREX_GPU_DEVICE void operator()( const amrex::IntVect& iv, @@ -77,6 +115,42 @@ struct TaylorGreen std::sin(omega1 * y / L) * std::cos(omega2 * z / L), vel[2] = 0.0); } + + AMREX_GPU_DEVICE + void thermal_initialise( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel, + amrex::Real& temperature, + amrex::Real& R, + amrex::Real& gamma) const + { + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + const amrex::Real x = prob_lo[0] + (iv[0] + 0.5) * dx[0]; + const amrex::Real y = prob_lo[1] + (iv[1] + 0.5) * dx[1]; + const amrex::Real z = + AMREX_D_PICK(, 0.0, prob_lo[2] + (iv[2] + 0.5) * dx[2]); + const amrex::Real omega0 = omega[0]; + const amrex::Real omega1 = omega[1]; + const amrex::Real omega2 = AMREX_D_PICK(, 0.0, omega[2]); + + rho = rho0 + rho0 * v0 * v0 / 16.0 * + (std::cos(2.0 * omega0 * x / L) + + std::cos(2.0 * omega1 * y / L)) * + (std::cos(2.0 * omega2 * z / L) + 2.0); + AMREX_D_DECL( + vel[0] = v0 * std::sin(omega0 * x / L) * + std::cos(omega1 * y / L) * std::cos(omega2 * z / L), + vel[1] = -v0 * std::cos(omega0 * x / L) * + std::sin(omega1 * y / L) * std::cos(omega2 * z / L), + vel[2] = 0.0); + + temperature = initial_temperature; + R = R_u / m_bar; + gamma = adiabatic_exponent; + } }; using DeviceType = DeviceOp; @@ -90,6 +164,268 @@ struct TaylorGreen DeviceOp m_op; }; +struct ViscosityTest +{ + struct DeviceOp + { + amrex::Real wave_length{1.0}; + amrex::Real density{1.0}; + amrex::RealVect velocity = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + amrex::RealVect mach_components = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + + AMREX_GPU_DEVICE + void operator()( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel) const + { + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real y = prob_lo[1] + (iv[1] + 0.5 * 0.0) * dx[1]; + + rho = density; + + const amrex::Real a0 = 0.010 * speed_of_sound_ref; + + vel[0] = velocity[0] + a0 * std::sin(2.0 * M_PI * y / wave_length); + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + } + + AMREX_GPU_DEVICE + void thermal_initialise( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel, + amrex::Real& temperature, + amrex::Real& R, + amrex::Real& gamma) const + { + + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real y = prob_lo[1] + (iv[1] + 0.5 * 0.0) * dx[1]; + + rho = density; + + const amrex::Real a0 = 0.010 * speed_of_sound_ref; + + vel[0] = velocity[0] + a0 * std::sin(2.0 * M_PI * y / wave_length); + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + + temperature = initial_temperature; + R = R_u / m_bar; + gamma = adiabatic_exponent; + } + }; + + using DeviceType = DeviceOp; + + explicit ViscosityTest(); + + static std::string identifier() { return "ic_viscosity_test"; } + + DeviceType device_instance() const { return m_op; } + + DeviceOp m_op; +}; + +struct ThermalDiffusivityTest +{ + struct DeviceOp + { + amrex::Real wave_length{1.0}; + amrex::Real density{1.0}; + amrex::RealVect velocity = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + amrex::RealVect mach_components = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + + AMREX_GPU_DEVICE + void operator()( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel) const + { + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real y = prob_lo[1] + (iv[1] + 0.5 * 0.0) * dx[1]; + + const amrex::Real a0 = 0.0010 * initial_temperature; + + rho = density + a0 * std::sin(2.0 * M_PI * y / wave_length); + + vel[0] = velocity[0]; + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + } + + AMREX_GPU_DEVICE + void thermal_initialise( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel, + amrex::Real& temperature, + amrex::Real& R, + amrex::Real& gamma) const + { + + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real y = prob_lo[1] + (iv[1] + 0.5 * 0.0) * dx[1]; + + const amrex::Real a0 = 0.0010 * initial_temperature; + + R = R_u / m_bar; + const amrex::Real pressure = density * R * initial_temperature; + rho = density + a0 * std::sin(2.0 * M_PI * y / wave_length); + + vel[0] = velocity[0]; + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + + gamma = adiabatic_exponent; + + temperature = pressure / (rho * R); + } + }; + + using DeviceType = DeviceOp; + + explicit ThermalDiffusivityTest(); + + static std::string identifier() { return "ic_thermaldiffusivity_test"; } + + DeviceType device_instance() const { return m_op; } + + DeviceOp m_op; +}; + +struct SodTest +{ + struct DeviceOp + { + amrex::Real density_ratio{1.0}; + amrex::Real temperature_ratio{1.0}; + amrex::Real x_discontinuity{10.0}; + amrex::Real density{1.0}; + amrex::RealVect velocity = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + amrex::RealVect mach_components = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + amrex::Real initial_temperature = 1.0 / 3.0; + + amrex::Real adiabatic_exponent = 5.0 / 3.0; + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + + AMREX_GPU_DEVICE + void operator()( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel) const + { + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real x = prob_lo[0] + (iv[0] + 0.5 * 0.0) * dx[0]; + + vel[0] = velocity[0]; + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + + rho = density + 0.5 * + (1.0 + std::tanh((x - x_discontinuity) * 3.0)) * + (density_ratio * density - density); + } + + AMREX_GPU_DEVICE + void thermal_initialise( + const amrex::IntVect& iv, + amrex::GeometryData const& geom, + amrex::Real& rho, + amrex::RealVect& vel, + amrex::Real& temperature, + amrex::Real& R, + amrex::Real& gamma) const + { + + const amrex::Real* prob_lo = geom.ProbLo(); + const amrex::Real* dx = geom.CellSize(); + + const amrex::Real x = prob_lo[0] + (iv[0] + 0.5 * 0.0) * dx[0]; + + R = R_u / m_bar; + + vel[0] = velocity[0]; + vel[1] = velocity[1]; + if (AMREX_SPACEDIM == 3) { + vel[2] = velocity[2]; + } + + gamma = adiabatic_exponent; + + rho = density + 0.5 * + (1.0 + std::tanh((x - x_discontinuity) * 3.0)) * + (density_ratio * density - density); + temperature = initial_temperature + + 0.5 * (1.0 + std::tanh((x - x_discontinuity) * 3.0)) * + (temperature_ratio * initial_temperature - + initial_temperature); + } + }; + + using DeviceType = DeviceOp; + + explicit SodTest(); + + static std::string identifier() { return "ic_sod_test"; } + + DeviceType device_instance() const { return m_op; } + + DeviceOp m_op; +}; + class InitializerBase { public: @@ -113,6 +449,14 @@ public: : m_mesh_speed(mesh_speed), m_op(ic_op), m_f(f) {} + Initializer( + const amrex::Real& mesh_speed, + const ICOp& ic_op, + amrex::Vector& f, + amrex::Vector& g) + : m_mesh_speed(mesh_speed), m_op(ic_op), m_f(f), m_g(g) + {} + ~Initializer() override = default; void initialize(const int lev, amrex::GeometryData const& geom) override @@ -121,28 +465,70 @@ public: const auto& evs = stencil.evs; const auto& weight = stencil.weights; auto const& f_arrs = m_f[lev].arrays(); + auto const& g_arrs = m_g[lev].arrays(); const amrex::Real l_mesh_speed = m_mesh_speed; ICDeviceOp ic(m_op.device_instance()); - amrex::ParallelFor( - m_f[lev], m_f[lev].nGrowVect(), constants::N_MICRO_STATES, - [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k, int q) noexcept { - const amrex::Real wt = weight[q]; - const auto& ev = evs[q]; - - const amrex::IntVect iv(AMREX_D_DECL(i, j, k)); - amrex::Real rho = 1.0; - amrex::RealVect vel(AMREX_D_DECL(0.0, 0.0, 0.0)); - ic(iv, geom, rho, vel); - - set_equilibrium_value( - rho, vel, l_mesh_speed, wt, ev, f_arrs[nbx](i, j, k, q)); - }); + + amrex::RealVect zero_vec = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + const amrex::Real theta0 = stencil::Stencil::THETA0; + + if (ic.model_type == 1) { + amrex::ParallelFor( + m_f[lev], m_f[lev].nGrowVect(), constants::N_MICRO_STATES, + [=] AMREX_GPU_DEVICE( + int nbx, int i, int j, int k, int q) noexcept { + const amrex::Real wt = weight[q]; + const auto& ev = evs[q]; + + const amrex::IntVect iv(AMREX_D_DECL(i, j, k)); + amrex::Real rho = 1.0; + amrex::RealVect vel(AMREX_D_DECL(0.0, 0.0, 0.0)); + amrex::Real temperature = 1.0 / 3.0; + amrex::Real specific_gas_constant = + ic.R_u / constants::AIR_MOLAR_MASS; + amrex::Real gamma = 1.667; + + ic.thermal_initialise( + iv, geom, rho, vel, temperature, specific_gas_constant, + gamma); + + set_equilibrium_value( + rho, vel, specific_gas_constant * temperature, + l_mesh_speed, wt, ev, f_arrs[nbx](i, j, k, q)); + + amrex::Real cv = specific_gas_constant / (gamma - 1.0); + + amrex::Real two_rho_e = + get_energy(temperature, rho, vel, cv); + + amrex::Real /*qxEq, qyEq, qzEq,*/ rxx_eq(0.0), ryy_eq(0.0), + rzz_eq(0.0), rxy_eq(0.0), rxz_eq(0.0), ryz_eq(0.0); + + amrex::RealVect heat_flux = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + + get_equilibrium_moments( + rho, vel, two_rho_e, cv, specific_gas_constant, + heat_flux, rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, + ryz_eq); + + amrex::GpuArray flux_of_heat_flux = { + rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, ryz_eq}; + + set_extended_grad_expansion_generic( + two_rho_e, heat_flux, flux_of_heat_flux, l_mesh_speed, + wt, ev, theta0, zero_vec, 1.0, g_arrs[nbx](i, j, k, q)); + }); + } else { + amrex::Abort("Invalid model_type"); + } + amrex::Gpu::synchronize(); } const amrex::Real m_mesh_speed; const ICOp m_op; amrex::Vector& m_f; + amrex::Vector& m_g; }; } // namespace lbm::ic diff --git a/Source/IC.cpp b/Source/IC.cpp index 517f796..72098f3 100644 --- a/Source/IC.cpp +++ b/Source/IC.cpp @@ -11,6 +11,24 @@ Constant::Constant() for (int n = 0; n < velocity.size(); n++) { m_op.velocity[n] = velocity[n]; } + + m_op.model_type = 1; + amrex::Vector mach_components{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("mach_components", mach_components, 0, AMREX_SPACEDIM); + for (int n = 0; n < mach_components.size(); n++) { + m_op.mach_components[n] = mach_components[n]; + } + + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + + for (int n = 0; n < mach_components.size(); n++) { + m_op.velocity[n] = m_op.mach_components[n] * m_op.speed_of_sound_ref; + } } TaylorGreen::TaylorGreen() @@ -26,4 +44,101 @@ TaylorGreen::TaylorGreen() } } +ViscosityTest::ViscosityTest() +{ + amrex::ParmParse pp(identifier()); + pp.query("density", m_op.density); + + amrex::Vector velocity{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("velocity", velocity, 0, AMREX_SPACEDIM); + for (int n = 0; n < velocity.size(); n++) { + m_op.velocity[n] = velocity[n]; + } + + pp.query("wave_length", m_op.wave_length); + m_op.model_type = 1; + amrex::Vector mach_components{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("mach_components", mach_components, 0, AMREX_SPACEDIM); + for (int n = 0; n < mach_components.size(); n++) { + m_op.mach_components[n] = mach_components[n]; + } + + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + + for (int n = 0; n < mach_components.size(); n++) { + m_op.velocity[n] = m_op.mach_components[n] * m_op.speed_of_sound_ref; + } +} + +ThermalDiffusivityTest::ThermalDiffusivityTest() +{ + amrex::ParmParse pp(identifier()); + pp.query("density", m_op.density); + + amrex::Vector velocity{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("velocity", velocity, 0, AMREX_SPACEDIM); + for (int n = 0; n < velocity.size(); n++) { + m_op.velocity[n] = velocity[n]; + } + + pp.query("wave_length", m_op.wave_length); + m_op.model_type = 1; + amrex::Vector mach_components{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("mach_components", mach_components, 0, AMREX_SPACEDIM); + for (int n = 0; n < mach_components.size(); n++) { + m_op.mach_components[n] = mach_components[n]; + } + + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + + for (int n = 0; n < mach_components.size(); n++) { + m_op.velocity[n] = m_op.mach_components[n] * m_op.speed_of_sound_ref; + } +} + +SodTest::SodTest() +{ + amrex::ParmParse pp(identifier()); + pp.query("density", m_op.density); + + amrex::Vector velocity{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("velocity", velocity, 0, AMREX_SPACEDIM); + for (int n = 0; n < velocity.size(); n++) { + m_op.velocity[n] = velocity[n]; + } + + pp.query("density_ratio", m_op.density_ratio); + pp.query("temperature_ratio", m_op.temperature_ratio); + pp.query("x_discontinuity", m_op.x_discontinuity); + + m_op.model_type = 1; + amrex::Vector mach_components{AMREX_D_DECL(0, 0, 0)}; + pp.queryarr("mach_components", mach_components, 0, AMREX_SPACEDIM); + for (int n = 0; n < mach_components.size(); n++) { + m_op.mach_components[n] = mach_components[n]; + } + + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + + for (int n = 0; n < mach_components.size(); n++) { + m_op.velocity[n] = m_op.mach_components[n] * m_op.speed_of_sound_ref; + } +} + } // namespace lbm::ic diff --git a/Source/LBM.H b/Source/LBM.H index b7a352f..0b15322 100644 --- a/Source/LBM.H +++ b/Source/LBM.H @@ -76,11 +76,12 @@ public: // convert macrodata to equilibrium void macrodata_to_equilibrium(const int lev); - // calculate the macro fluid properties from the distributions + // calculate the macro fluid properties from the distributions and store + // part of (4.45) of http://dx.doi.org/10.3929/ethz-b-000607045 void f_to_macrodata(const int lev); // Stream the information to the neighbor particles - void stream(const int lev); + void stream(const int lev, amrex::Vector& fs); // Collide the particles void collide(const int lev); @@ -91,6 +92,9 @@ public: // Compute derived quantities void compute_derived(const int lev); + // Compute corrections + void compute_q_corrections(const int lev); + // Compute forces on EB void compute_eb_forces(); @@ -206,13 +210,16 @@ private: amrex::Vector m_lbm_varnames; amrex::Vector m_macrodata_varnames; amrex::Vector m_microdata_varnames; + amrex::Vector m_microdata_g_varnames; amrex::Vector m_deriveddata_varnames; amrex::Vector m_idata_varnames; // array of multifabs to store the solution at each level of refinement amrex::Vector m_macrodata; amrex::Vector m_f; + amrex::Vector m_g; amrex::Vector m_eq; + amrex::Vector m_eq_g; amrex::Vector m_derived; amrex::Vector m_is_fluid; amrex::Vector m_plt_mf; @@ -233,6 +240,7 @@ private: amrex::Vector m_bcs; // 1-component std::unique_ptr m_fillpatch_op; + std::unique_ptr m_fillpatch_g_op; amrex::Vector>> m_factory; @@ -263,6 +271,7 @@ private: amrex::Real m_dx_outer = 1.0; amrex::Real m_dt_outer = 1.0; amrex::Real m_nu = 1.0; + amrex::Real m_alpha = 1.0; // save streaming data to plot file bool m_save_streaming = true; @@ -286,6 +295,26 @@ private: std::unique_ptr m_ic_op; std::string m_ic_type; + + // LBM Scheme selector. "energyD3Q27" activates product equilibrium, + // energy equation etc. + std::string m_model_type = "energyD3Q27"; + + // Initial temperature. + amrex::Real m_initialTemperature = 1.0 / 3.0; + + // Adiabatic exponent. + amrex::Real m_adiabaticExponent = 5.0 / 3.0; + + // Universal Gas constant, LB unit. Never change. + const amrex::Real m_R_u = constants::AIR_MOLAR_MASS; + + // Mean molecular mass, Safe default air. Unit kg/kmol. + amrex::Real m_m_bar = constants::AIR_MOLAR_MASS; + + // Set the actual reference speed of sound + amrex::Real m_speedOfSound_Ref = std::sqrt( + m_adiabaticExponent * (m_R_u / m_m_bar) * m_initialTemperature); }; } // namespace lbm #endif diff --git a/Source/LBM.cpp b/Source/LBM.cpp index e1426eb..1d3cb31 100644 --- a/Source/LBM.cpp +++ b/Source/LBM.cpp @@ -16,6 +16,22 @@ LBM::LBM() m_macrodata_varnames.push_back("vel_y"); m_macrodata_varnames.push_back("vel_z"); m_macrodata_varnames.push_back("vel_mag"); + + m_macrodata_varnames.push_back("two_rho_e"); + m_macrodata_varnames.push_back("QCorrX"); + m_macrodata_varnames.push_back("QCorrY"); + m_macrodata_varnames.push_back("QCorrZ"); + m_macrodata_varnames.push_back("pxx"); + m_macrodata_varnames.push_back("pyy"); + m_macrodata_varnames.push_back("pzz"); + m_macrodata_varnames.push_back("pxy"); + m_macrodata_varnames.push_back("pxz"); + m_macrodata_varnames.push_back("pyz"); + m_macrodata_varnames.push_back("qx"); + m_macrodata_varnames.push_back("qy"); + m_macrodata_varnames.push_back("qz"); + m_macrodata_varnames.push_back("temperature"); + const size_t n_zero = 2; for (int q = 0; q < constants::N_MICRO_STATES; q++) { const auto num_str = std::to_string(q); @@ -24,10 +40,24 @@ LBM::LBM() num_str; m_microdata_varnames.push_back("f_" + zero_padded_str); } + + for (int q = 0; q < constants::N_MICRO_STATES; q++) { + const auto num_str = std::to_string(q); + const auto zero_padded_str = + std::string(n_zero - std::min(n_zero, num_str.length()), '0') + + num_str; + m_microdata_g_varnames.push_back("g_" + zero_padded_str); + } + m_deriveddata_varnames.push_back("vort_x"); m_deriveddata_varnames.push_back("vort_y"); m_deriveddata_varnames.push_back("vort_z"); m_deriveddata_varnames.push_back("vort_mag"); + + m_deriveddata_varnames.push_back("dQCorrX"); + m_deriveddata_varnames.push_back("dQCorrY"); + m_deriveddata_varnames.push_back("dQCorrZ"); + m_idata_varnames.push_back("is_fluid"); m_idata_varnames.push_back("eb_boundary"); for (const auto& vname : m_macrodata_varnames) { @@ -37,6 +67,10 @@ LBM::LBM() for (const auto& vname : m_microdata_varnames) { m_lbm_varnames.push_back(vname); } + + for (const auto& vname : m_microdata_g_varnames) { + m_lbm_varnames.push_back(vname); + } } if (m_save_derived) { for (const auto& vname : m_deriveddata_varnames) { @@ -61,7 +95,9 @@ LBM::LBM() m_macrodata.resize(nlevs_max); m_f.resize(nlevs_max); + m_g.resize(nlevs_max); m_eq.resize(nlevs_max); + m_eq_g.resize(nlevs_max); m_derived.resize(nlevs_max); m_is_fluid.resize(nlevs_max); m_plt_mf.resize(nlevs_max); @@ -79,8 +115,11 @@ LBM::LBM() } } else if ( (m_bc_lo[idim] == bc::NOSLIPWALL) || + (m_bc_lo[idim] == bc::SLIPWALLXNORMAL) || + (m_bc_lo[idim] == bc::SLIPWALLYNORMAL) || + (m_bc_lo[idim] == bc::SLIPWALLZNORMAL) || (m_bc_lo[idim] == bc::VELOCITY) || - (m_bc_lo[idim] == bc::PRESSURE) || (m_bc_lo[idim] == bc::OUTFLOW) || + (m_bc_lo[idim] == bc::PRESSURE) || (m_bc_lo[idim] == bc::OUTFLOW_ZEROTH_ORDER)) { for (auto& bc : m_bcs) { bc.setLo(idim, amrex::BCType::ext_dir); @@ -96,8 +135,11 @@ LBM::LBM() } } else if ( (m_bc_hi[idim] == bc::NOSLIPWALL) || + (m_bc_hi[idim] == bc::SLIPWALLXNORMAL) || + (m_bc_hi[idim] == bc::SLIPWALLYNORMAL) || + (m_bc_hi[idim] == bc::SLIPWALLZNORMAL) || (m_bc_hi[idim] == bc::VELOCITY) || - (m_bc_hi[idim] == bc::PRESSURE) || (m_bc_hi[idim] == bc::OUTFLOW) || + (m_bc_hi[idim] == bc::PRESSURE) || (m_bc_hi[idim] == bc::OUTFLOW_ZEROTH_ORDER)) { for (auto& bc : m_bcs) { bc.setHi(idim, amrex::BCType::ext_dir); @@ -121,6 +163,7 @@ void LBM::init_data() const amrex::Real time = 0.0; set_ics(); InitFromScratch(time); + average_down(amrex::IntVect(0)); compute_dt(); @@ -230,7 +273,10 @@ void LBM::read_parameters() pp.query("dx_outer", m_dx_outer); pp.query("dt_outer", m_dt_outer); + pp.query("nu", m_nu); + m_alpha = m_nu; + pp.query("alpha", m_alpha); pp.query("save_streaming", m_save_streaming); pp.query("save_derived", m_save_derived); @@ -238,8 +284,17 @@ void LBM::read_parameters() pp.query("compute_forces", m_compute_forces); pp.query("forces_file", m_forces_file); + pp.query("initial_temperature", m_initialTemperature); + + pp.query("adiabatic_exponent", m_adiabaticExponent); + pp.query("mean_molecular_mass", m_m_bar); + + m_speedOfSound_Ref = std::sqrt( + m_adiabaticExponent * (m_R_u / m_m_bar) * m_initialTemperature); + m_mesh_speed = m_dx_outer / m_dt_outer; m_cs = m_mesh_speed / constants::ROOT3; + m_cs_2 = m_cs * m_cs; } } @@ -356,6 +411,9 @@ void LBM::evolve() << std::endl; m_fillpatch_op->fillpatch(0, cur_time, m_f[0]); + + m_fillpatch_g_op->fillpatch(0, cur_time, m_g[0]); + time_step(0, cur_time, 1); post_time_step(); @@ -436,6 +494,9 @@ void LBM::time_step(const int lev, const amrex::Real time, const int iteration) if (lev < finest_level) { m_fillpatch_op->fillpatch(lev + 1, m_ts_new[lev + 1], m_f[lev + 1]); + + m_fillpatch_g_op->fillpatch(lev + 1, m_ts_new[lev + 1], m_g[lev + 1]); + for (int i = 1; i <= m_nsubsteps[lev + 1]; ++i) { time_step(lev + 1, time + (i - 1) * m_dts[lev + 1], i); } @@ -464,15 +525,15 @@ void LBM::advance( m_ts_old[lev] = m_ts_new[lev]; // old time is now current time (time) m_ts_new[lev] += dt_lev; // new time is ahead - stream(lev); + stream(lev, m_f); + + stream(lev, m_g); if (lev < finest_level) { average_down_to(lev, amrex::IntVect(1)); } collide(lev); - - sanity_check_f(lev); } void LBM::post_time_step() @@ -487,24 +548,24 @@ void LBM::post_time_step() } // Stream the information to the neighbor particles -void LBM::stream(const int lev) +void LBM::stream(const int lev, amrex::Vector& fs) { BL_PROFILE("LBM::stream()"); amrex::MultiFab f_star( boxArray(lev), DistributionMap(lev), constants::N_MICRO_STATES, - m_f[lev].nGrow(), amrex::MFInfo(), *(m_factory[lev])); + fs[lev].nGrow(), amrex::MFInfo(), *(m_factory[lev])); f_star.setVal(-1.0); auto const& fs_arrs = f_star.arrays(); auto const& is_fluid_arrs = m_is_fluid[lev].const_arrays(); - auto const& f_arrs = m_f[lev].const_arrays(); + auto const& f_arrs = fs[lev].const_arrays(); const stencil::Stencil stencil; const auto& evs = stencil.evs; const auto& bounce_dirs = stencil.bounce_dirs; amrex::ParallelFor( - m_f[lev], m_f[lev].nGrowVect(), constants::N_MICRO_STATES, + fs[lev], fs[lev].nGrowVect(), constants::N_MICRO_STATES, [=] AMREX_GPU_DEVICE( int nbx, int i, int j, int AMREX_D_PICK(, /*k*/, k), int q) noexcept { @@ -531,9 +592,8 @@ void LBM::stream(const int lev) amrex::Gpu::synchronize(); amrex::MultiFab::Copy( - m_f[lev], f_star, 0, 0, constants::N_MICRO_STATES, - m_f[lev].nGrowVect()); - m_f[lev].FillBoundary(Geom(lev).periodicity()); + fs[lev], f_star, 0, 0, constants::N_MICRO_STATES, fs[lev].nGrowVect()); + fs[lev].FillBoundary(Geom(lev).periodicity()); } // Collide the particles @@ -543,12 +603,14 @@ void LBM::collide(const int lev) f_to_macrodata(lev); + compute_q_corrections(lev); + macrodata_to_equilibrium(lev); relax_f_to_equilibrium(lev); } -// convert macrodata to equilibrium +// convert macrodata to equilibrium. void LBM::macrodata_to_equilibrium(const int lev) { BL_PROFILE("LBM::macrodata_to_equilibrium()"); @@ -556,11 +618,24 @@ void LBM::macrodata_to_equilibrium(const int lev) auto const& md_arrs = m_macrodata[lev].const_arrays(); auto const& is_fluid_arrs = m_is_fluid[lev].const_arrays(); auto const& eq_arrs = m_eq[lev].arrays(); + auto const& eq_arrs_g = m_eq_g[lev].arrays(); const amrex::Real l_mesh_speed = m_mesh_speed; + AMREX_ASSERT(m_macrodata[lev].nGrow() > m_derived[lev].nGrow()); + auto const& d_arrs = m_derived[lev].const_arrays(); + const stencil::Stencil stencil; const auto& evs = stencil.evs; const auto& weight = stencil.weights; + + const amrex::RealVect zero_vec = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + const amrex::Real specific_gas_constant = m_R_u / m_m_bar; + const amrex::Real cv = specific_gas_constant / (m_adiabaticExponent - 1.0); + const amrex::Real nu = m_nu; + const amrex::Real dt = m_dts[lev]; + const amrex::Real alpha = m_alpha; + const amrex::Real theta0 = stencil::Stencil::THETA0; + amrex::ParallelFor( m_eq[lev], m_eq[lev].nGrowVect(), constants::N_MICRO_STATES, [=] AMREX_GPU_DEVICE( @@ -571,6 +646,8 @@ void LBM::macrodata_to_equilibrium(const int lev) const auto md_arr = md_arrs[nbx]; const auto eq_arr = eq_arrs[nbx]; + const auto eq_arr_g = eq_arrs_g[nbx]; + const auto d_arr = d_arrs[nbx]; const amrex::Real rho = md_arr(iv, constants::RHO_IDX); const amrex::RealVect vel = {AMREX_D_DECL( @@ -578,25 +655,122 @@ void LBM::macrodata_to_equilibrium(const int lev) md_arr(iv, constants::VELY_IDX), md_arr(iv, constants::VELZ_IDX))}; + const amrex::Real two_rho_e = + md_arr(iv, constants::TWO_RHO_E_IDX); + const amrex::Real wt = weight[q]; const auto& ev = evs[q]; - set_equilibrium_value( - rho, vel, l_mesh_speed, wt, ev, eq_arr(iv, q)); + amrex::Real temperature = + md_arr(iv, constants::TEMPERATURE_IDX); + + amrex::Real omega = + 1.0 / + (nu / (specific_gas_constant * temperature * dt) + 0.5); + amrex::Real omega_one = + 1.0 / + (alpha / (specific_gas_constant * temperature * dt) + 0.5); + amrex::Real omega_one_by_omega = omega_one / omega; + amrex::Real omega_corr = (2.0 - omega) / (2.0 * omega * rho); + + amrex::Real pxx_ext = + vel[0] * vel[0] + specific_gas_constant * temperature + + dt * (omega_corr)*d_arr(iv, constants::D_Q_CORR_X_IDX); + amrex::Real pyy_ext = + vel[1] * vel[1] + specific_gas_constant * temperature + + dt * (omega_corr)*d_arr(iv, constants::D_Q_CORR_Y_IDX); + amrex::Real pzz_ext(0.0); + if (AMREX_SPACEDIM == 3) { + pzz_ext = + vel[2] * vel[2] + specific_gas_constant * temperature + + dt * (omega_corr)*d_arr(iv, constants::D_Q_CORR_Z_IDX); + } + + set_extended_equilibrium_value( + rho, vel, pxx_ext, pyy_ext, pzz_ext, l_mesh_speed, wt, ev, + eq_arr(iv, q)); + + amrex::Real AMREX_D_DECL(qx_eq = 0.0, qy_eq = 0.0, qz_eq = 0.0); + amrex::Real rxx_eq(0.0), ryy_eq(0.0), rzz_eq(0.0), rxy_eq(0.0), + rxz_eq(0.0), ryz_eq(0.0); + + amrex::RealVect heat_flux = {AMREX_D_DECL(0.0, 0.0, 0.0)}; + get_equilibrium_moments( + rho, vel, two_rho_e, cv, specific_gas_constant, heat_flux, + rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, ryz_eq); + + qx_eq = heat_flux[0]; + qy_eq = heat_flux[1]; + AMREX_3D_ONLY(qz_eq = heat_flux[2]); + + const amrex::Real pxx = md_arr(iv, constants::PXX_IDX); + const amrex::Real pyy = md_arr(iv, constants::PYY_IDX); + AMREX_3D_ONLY( + const amrex::Real pzz = md_arr(iv, constants::PZZ_IDX)); + const amrex::Real pxy = md_arr(iv, constants::PXY_IDX); + AMREX_3D_ONLY( + const amrex::Real pxz = md_arr(iv, constants::PXZ_IDX)); + AMREX_3D_ONLY( + const amrex::Real pyz = md_arr(iv, constants::PYZ_IDX)); + + const amrex::Real qx = md_arr(iv, constants::QX_IDX); + const amrex::Real qy = md_arr(iv, constants::QY_IDX); + AMREX_3D_ONLY( + const amrex::Real qz = md_arr(iv, constants::QZ_IDX)); + + qx_eq *= omega_one_by_omega; + qy_eq *= omega_one_by_omega; + AMREX_3D_ONLY(qz_eq *= omega_one_by_omega); + + qx_eq += (1.0 - omega_one_by_omega) * + (qx AMREX_D_TERM( + -2.0 * vel[0] * pxx, -2.0 * vel[1] * pxy, + -2.0 * vel[2] * pxz) - + vel[0] * dt * d_arr(iv, constants::D_Q_CORR_X_IDX)); + + qy_eq += (1.0 - omega_one_by_omega) * + (qy AMREX_D_TERM( + -2.0 * vel[0] * pxy, -2.0 * vel[1] * pyy, + -2.0 * vel[2] * pyz) - + vel[1] * dt * d_arr(iv, constants::D_Q_CORR_Y_IDX)); + + AMREX_3D_ONLY( + qz_eq += + (1.0 - omega_one_by_omega) * + (qz - 2.0 * vel[0] * pxz - 2.0 * vel[1] * pyz - + 2.0 * vel[2] * pzz - + vel[2] * dt * d_arr(iv, constants::D_Q_CORR_Z_IDX))); + + amrex::RealVect heat_flux_mrt = { + AMREX_D_DECL(qx_eq, qy_eq, qz_eq)}; + + amrex::GpuArray flux_of_heat_flux = { + rxx_eq, ryy_eq, rzz_eq, rxy_eq, rxz_eq, ryz_eq}; + + set_extended_grad_expansion_generic( + two_rho_e, heat_flux_mrt, flux_of_heat_flux, l_mesh_speed, + wt, ev, theta0, zero_vec, 1.0, eq_arr_g(iv, q)); } }); amrex::Gpu::synchronize(); } -// Relax the particles toward the equilibrium state +// Relax the particles toward the equilibrium state. void LBM::relax_f_to_equilibrium(const int lev) { BL_PROFILE("LBM::relax_f_to_equilibrium()"); auto const& is_fluid_arrs = m_is_fluid[lev].const_arrays(); auto const& eq_arrs = m_eq[lev].const_arrays(); + auto const& eq_arrs_g = m_eq_g[lev].const_arrays(); auto const& f_arrs = m_f[lev].arrays(); - const amrex::Real tau = m_nu / (m_dts[lev] * m_cs_2) + 0.5; + auto const& g_arrs = m_g[lev].arrays(); + auto const& md_arrs = m_macrodata[lev].arrays(); + + amrex::Real specific_gas_constant = (m_R_u / m_m_bar); + amrex::Real nu = m_nu; + amrex::Real dt = m_dts[lev]; + amrex::ParallelFor( m_f[lev], m_eq[lev].nGrowVect(), constants::N_MICRO_STATES, [=] AMREX_GPU_DEVICE( @@ -606,11 +780,25 @@ void LBM::relax_f_to_equilibrium(const int lev) if (is_fluid_arrs[nbx](iv, 0) == 1) { const auto f_arr = f_arrs[nbx]; const auto eq_arr = eq_arrs[nbx]; - f_arr(iv, q) -= 1.0 / tau * (f_arr(iv, q) - eq_arr(iv, q)); + const auto md_arr = md_arrs[nbx]; + + const auto g_arr = g_arrs[nbx]; + const auto eq_arr_g = eq_arrs_g[nbx]; + + amrex::Real temperature = + md_arr(iv, constants::TEMPERATURE_IDX); + amrex::Real omega = + 1.0 / + (nu / (specific_gas_constant * temperature * dt) + 0.5); + + f_arr(iv, q) += omega * (eq_arr(iv, q) - f_arr(iv, q)); + + g_arr(iv, q) += omega * (eq_arr_g(iv, q) - g_arr(iv, q)); } }); amrex::Gpu::synchronize(); m_f[lev].FillBoundary(Geom(lev).periodicity()); + m_g[lev].FillBoundary(Geom(lev).periodicity()); } // calculate the macro fluid properties from the distributions @@ -620,7 +808,10 @@ void LBM::f_to_macrodata(const int lev) auto const& md_arrs = m_macrodata[lev].arrays(); auto const& is_fluid_arrs = m_is_fluid[lev].const_arrays(); auto const& f_arrs = m_f[lev].const_arrays(); + auto const& g_arrs = m_g[lev].const_arrays(); const amrex::Real l_mesh_speed = m_mesh_speed; + amrex::Real specific_gas_constant = m_R_u / m_m_bar; + amrex::Real cv = specific_gas_constant / (m_adiabaticExponent - 1.0); const stencil::Stencil stencil; const auto& evs = stencil.evs; @@ -632,15 +823,41 @@ void LBM::f_to_macrodata(const int lev) if (is_fluid_arrs[nbx](iv, 0) == 1) { const auto f_arr = f_arrs[nbx]; + const auto g_arr = g_arrs[nbx]; const auto md_arr = md_arrs[nbx]; - amrex::Real rho = 0.0, AMREX_D_DECL(u = 0.0, v = 0.0, w = 0.0); + amrex::Real rho = 0.0, u = 0.0, v = 0.0, w = 0.0; + + amrex::Real pxx(0.0), pyy(0.0), pzz(0.0), pxy(0.0), pxz(0.0), + pyz(0.0); + amrex::Real two_rho_e = 0.0, + AMREX_D_DECL(qx = 0.0, qy = 0.0, qz = 0.0); + for (int q = 0; q < constants::N_MICRO_STATES; q++) { rho += f_arr(iv, q); const auto& ev = evs[q]; AMREX_D_DECL( u += ev[0] * f_arr(iv, q), v += ev[1] * f_arr(iv, q), w += ev[2] * f_arr(iv, q)); + + pxx += ev[0] * ev[0] * f_arr(iv, q); + pyy += ev[1] * ev[1] * f_arr(iv, q); + if (AMREX_SPACEDIM == 3) { + pzz += ev[2] * ev[2] * f_arr(iv, q); + } + pxy += ev[0] * ev[1] * f_arr(iv, q); + if (AMREX_SPACEDIM == 3) { + pxz += ev[0] * ev[2] * f_arr(iv, q); + } + if (AMREX_SPACEDIM == 3) { + pyz += ev[1] * ev[2] * f_arr(iv, q); + } + + two_rho_e += g_arr(iv, q); + + AMREX_D_DECL( + qx += ev[0] * g_arr(iv, q), qy += ev[1] * g_arr(iv, q), + qz += ev[2] * g_arr(iv, q)); } AMREX_D_DECL( u *= l_mesh_speed / rho, v *= l_mesh_speed / rho, @@ -653,6 +870,34 @@ void LBM::f_to_macrodata(const int lev) md_arr(iv, constants::VELZ_IDX) = w); md_arr(iv, constants::VMAG_IDX) = std::sqrt(AMREX_D_TERM(u * u, +v * v, +w * w)); + + md_arr(iv, constants::PXX_IDX) = pxx; + md_arr(iv, constants::PYY_IDX) = pyy; + md_arr(iv, constants::PZZ_IDX) = pzz; + md_arr(iv, constants::PXY_IDX) = pxy; + md_arr(iv, constants::PXZ_IDX) = pxz; + md_arr(iv, constants::PYZ_IDX) = pyz; + + md_arr(iv, constants::TWO_RHO_E_IDX) = two_rho_e; + AMREX_D_DECL( + md_arr(iv, constants::QX_IDX) = qx, + md_arr(iv, constants::QY_IDX) = qy, + md_arr(iv, constants::QZ_IDX) = qz); + + amrex::Real temperature = + get_temperature(two_rho_e, rho, u, v, w, cv); + + md_arr(iv, constants::TEMPERATURE_IDX) = temperature; + + md_arr(iv, constants::Q_CORR_X_IDX) = + rho * u * + ((1.0 - 3.0 * specific_gas_constant * temperature) - u * u); + md_arr(iv, constants::Q_CORR_Y_IDX) = + rho * v * + ((1.0 - 3.0 * specific_gas_constant * temperature) - v * v); + md_arr(iv, constants::Q_CORR_Z_IDX) = + rho * w * + ((1.0 - 3.0 * specific_gas_constant * temperature) - w * w); } }); amrex::Gpu::synchronize(); @@ -708,6 +953,49 @@ void LBM::compute_derived(const int lev) amrex::Gpu::synchronize(); } +// Compute derived quantities + +void LBM::compute_q_corrections(const int lev) +{ + BL_PROFILE("LBM::compute_derived()"); + AMREX_ASSERT(m_macrodata[lev].nGrow() > m_derived[lev].nGrow()); + const auto& idx = geom[lev].InvCellSizeArray(); + + auto const& md_arrs = m_macrodata[lev].const_arrays(); + auto const& is_fluid_arrs = m_is_fluid[lev].const_arrays(); + auto const& d_arrs = m_derived[lev].arrays(); + const amrex::Box& dbox = geom[lev].Domain(); + amrex::ParallelFor( + m_derived[lev], m_derived[lev].nGrowVect(), + [=] AMREX_GPU_DEVICE( + int nbx, int i, int j, int AMREX_D_PICK(, /*k*/, k)) noexcept { + const auto md_arr = md_arrs[nbx]; + const auto if_arr = is_fluid_arrs[nbx]; + const auto d_arr = d_arrs[nbx]; + const amrex::IntVect iv(AMREX_D_DECL(i, j, k)); + + if (if_arr(iv, 0) == 1) { + const amrex::Real d_qxxx = gradient( + 0, constants::Q_CORR_X_IDX, iv, idx, dbox, if_arr, md_arr); + const amrex::Real d_qyyy = gradient( + 1, constants::Q_CORR_Y_IDX, iv, idx, dbox, if_arr, md_arr); + + amrex::Real d_qzzz = 0.0; + + if (AMREX_SPACEDIM == 3) { + d_qzzz = gradient( + 2, constants::Q_CORR_Z_IDX, iv, idx, dbox, if_arr, + md_arr); + } + + d_arr(iv, constants::D_Q_CORR_X_IDX) = d_qxxx; + d_arr(iv, constants::D_Q_CORR_Y_IDX) = d_qyyy; + d_arr(iv, constants::D_Q_CORR_Z_IDX) = d_qzzz; + } + }); + amrex::Gpu::synchronize(); +} + // Compute forces on EB void LBM::compute_eb_forces() { @@ -820,11 +1108,17 @@ void LBM::MakeNewLevelFromCoarse( m_f[lev].define( ba, dm, m_f[lev - 1].nComp(), m_f[lev - 1].nGrow(), amrex::MFInfo(), *(m_factory[lev])); + m_g[lev].define( + ba, dm, m_g[lev - 1].nComp(), m_g[lev - 1].nGrow(), amrex::MFInfo(), + *(m_factory[lev])); m_is_fluid[lev].define( ba, dm, m_is_fluid[lev - 1].nComp(), m_is_fluid[lev - 1].nGrow()); m_eq[lev].define( ba, dm, m_eq[lev - 1].nComp(), m_eq[lev - 1].nGrow(), amrex::MFInfo(), *(m_factory[lev])); + m_eq_g[lev].define( + ba, dm, m_eq_g[lev - 1].nComp(), m_eq_g[lev - 1].nGrow(), + amrex::MFInfo(), *(m_factory[lev])); m_derived[lev].define( ba, dm, m_derived[lev - 1].nComp(), m_derived[lev - 1].nGrow(), amrex::MFInfo(), *(m_factory[lev])); @@ -837,12 +1131,21 @@ void LBM::MakeNewLevelFromCoarse( initialize_is_fluid(lev); initialize_mask(lev); m_fillpatch_op->fillpatch_from_coarse(lev, time, m_f[lev]); + + m_fillpatch_g_op->fillpatch_from_coarse(lev, time, m_g[lev]); + m_macrodata[lev].setVal(0.0); m_eq[lev].setVal(0.0); + m_eq_g[lev].setVal(0.0); m_derived[lev].setVal(0.0); + f_to_macrodata(lev); + macrodata_to_equilibrium(lev); + compute_derived(lev); + + compute_q_corrections(lev); } // Make a new level from scratch using provided BoxArray and @@ -865,10 +1168,16 @@ void LBM::MakeNewLevelFromScratch( m_f[lev].define( ba, dm, constants::N_MICRO_STATES, m_f_nghost, amrex::MFInfo(), *(m_factory[lev])); + m_g[lev].define( + ba, dm, constants::N_MICRO_STATES, m_f_nghost, amrex::MFInfo(), + *(m_factory[lev])); m_is_fluid[lev].define(ba, dm, constants::N_IS_FLUID, m_f[lev].nGrow()); m_eq[lev].define( ba, dm, constants::N_MICRO_STATES, m_eq_nghost, amrex::MFInfo(), *(m_factory[lev])); + m_eq_g[lev].define( + ba, dm, constants::N_MICRO_STATES, m_eq_nghost, amrex::MFInfo(), + *(m_factory[lev])); m_derived[lev].define( ba, dm, constants::N_DERIVED, m_derived_nghost, amrex::MFInfo(), *(m_factory[lev])); @@ -883,10 +1192,16 @@ void LBM::MakeNewLevelFromScratch( initialize_f(lev); m_macrodata[lev].setVal(0.0); m_eq[lev].setVal(0.0); + m_eq_g[lev].setVal(0.0); m_derived[lev].setVal(0.0); + f_to_macrodata(lev); + macrodata_to_equilibrium(lev); + compute_derived(lev); + + compute_q_corrections(lev); } void LBM::initialize_f(const int lev) @@ -898,8 +1213,7 @@ void LBM::initialize_f(const int lev) fill_f_inside_eb(lev); m_f[lev].FillBoundary(Geom(lev).periodicity()); - - sanity_check_f(lev); + m_g[lev].FillBoundary(Geom(lev).periodicity()); } void LBM::initialize_is_fluid(const int lev) @@ -970,27 +1284,22 @@ void LBM::initialize_mask(const int lev) void LBM::fill_f_inside_eb(const int lev) { BL_PROFILE("LBM::fill_f_inside_eb()"); - const amrex::Real rho_inside = 0.0; - const amrex::RealVect vel_inside(AMREX_D_DECL(0.0, 0.0, 0.0)); - const amrex::Real l_mesh_speed = m_mesh_speed; auto const& f_arrs = m_f[lev].arrays(); + auto const& g_arrs = m_g[lev].arrays(); + auto const& is_fluid_arrs = m_is_fluid[lev].arrays(); - const stencil::Stencil stencil; - const auto& evs = stencil.evs; - const auto& weight = stencil.weights; + amrex::ParallelFor( m_f[lev], m_f[lev].nGrowVect(), constants::N_MICRO_STATES, [=] AMREX_GPU_DEVICE(int nbx, int i, int j, int k, int q) noexcept { if (is_fluid_arrs[nbx](i, j, k, 0) == 0) { - const amrex::Real wt = weight[q]; - const auto& ev = evs[q]; - set_equilibrium_value( - rho_inside, vel_inside, l_mesh_speed, wt, ev, - f_arrs[nbx](i, j, k, q)); + set_population_zero(f_arrs[nbx](i, j, k, q)); + set_population_zero(g_arrs[nbx](i, j, k, q)); } }); + amrex::Gpu::synchronize(); } @@ -1019,7 +1328,9 @@ void LBM::ClearLevel(int lev) BL_PROFILE("LBM::ClearLevel()"); m_macrodata[lev].clear(); m_f[lev].clear(); + m_g[lev].clear(); m_eq[lev].clear(); + m_eq_g[lev].clear(); m_derived[lev].clear(); m_is_fluid[lev].clear(); m_plt_mf[lev].clear(); @@ -1029,27 +1340,70 @@ void LBM::ClearLevel(int lev) // Set the user defined BC functions void LBM::set_bcs() { + BL_PROFILE("LBM::set_bcs()"); + const bool is_an_energy_lattice(true); + if (m_velocity_bc_type == "noop") { + using VelBCOp = bc::BCOpCreator; + m_fillpatch_op = std::make_unique>( geom, refRatio(), m_bcs, VelBCOp(m_mesh_speed, m_bc_type, m_f[0].nGrowVect()), m_f); + + m_fillpatch_g_op = std::make_unique>( + geom, refRatio(), m_bcs, + VelBCOp( + m_mesh_speed, m_bc_type, m_g[0].nGrowVect(), + is_an_energy_lattice), + m_g, is_an_energy_lattice); + } else if (m_velocity_bc_type == "constant") { + using VelBCOp = bc::BCOpCreator; + m_fillpatch_op = std::make_unique>( geom, refRatio(), m_bcs, VelBCOp(m_mesh_speed, m_bc_type, m_f[0].nGrowVect()), m_f); + + m_fillpatch_g_op = std::make_unique>( + geom, refRatio(), m_bcs, + VelBCOp( + m_mesh_speed, m_bc_type, m_g[0].nGrowVect(), + is_an_energy_lattice), + m_g, is_an_energy_lattice); + } else if (m_velocity_bc_type == "channel") { + using VelBCOp = bc::BCOpCreator; + m_fillpatch_op = std::make_unique>( geom, refRatio(), m_bcs, VelBCOp(m_mesh_speed, m_bc_type, m_f[0].nGrowVect()), m_f); + + m_fillpatch_g_op = std::make_unique>( + geom, refRatio(), m_bcs, + VelBCOp( + m_mesh_speed, m_bc_type, m_g[0].nGrowVect(), + is_an_energy_lattice), + m_g, is_an_energy_lattice); + } else if (m_velocity_bc_type == "parabolic") { + using VelBCOp = bc::BCOpCreator; + m_fillpatch_op = std::make_unique>( geom, refRatio(), m_bcs, VelBCOp(m_mesh_speed, m_bc_type, m_f[0].nGrowVect()), m_f); + + m_fillpatch_g_op = std::make_unique>( + geom, refRatio(), m_bcs, + VelBCOp( + m_mesh_speed, m_bc_type, m_g[0].nGrowVect(), + is_an_energy_lattice), + m_g, is_an_energy_lattice); + } else { amrex::Abort("LBM::set_bcs(): Unknown velocity BC"); } @@ -1060,10 +1414,20 @@ void LBM::set_ics() BL_PROFILE("LBM::set_ics()"); if (m_ic_type == "constant") { m_ic_op = std::make_unique>( - m_mesh_speed, ic::Constant(ic::Constant()), m_f); + m_mesh_speed, ic::Constant(ic::Constant()), m_f, m_g); } else if (m_ic_type == "taylorgreen") { m_ic_op = std::make_unique>( - m_mesh_speed, ic::TaylorGreen(ic::TaylorGreen()), m_f); + m_mesh_speed, ic::TaylorGreen(ic::TaylorGreen()), m_f, m_g); + } else if (m_ic_type == "viscosity_test") { + m_ic_op = std::make_unique>( + m_mesh_speed, ic::ViscosityTest(ic::ViscosityTest()), m_f, m_g); + } else if (m_ic_type == "thermaldiffusivity_test") { + m_ic_op = std::make_unique>( + m_mesh_speed, + ic::ThermalDiffusivityTest(ic::ThermalDiffusivityTest()), m_f, m_g); + } else if (m_ic_type == "sod_test") { + m_ic_op = std::make_unique>( + m_mesh_speed, ic::SodTest(ic::SodTest()), m_f, m_g); } else { amrex::Abort( "LBM::set_ics(): User must specify a valid initial condition"); @@ -1074,12 +1438,16 @@ void LBM::set_ics() bool LBM::check_field_existence(const std::string& name) { BL_PROFILE("LBM::check_field_existence()"); - const auto vnames = { - m_macrodata_varnames, m_microdata_varnames, m_deriveddata_varnames, - m_idata_varnames}; - return std::any_of(vnames.begin(), vnames.end(), [=](const auto& vn) { - return get_field_component(name, vn) != -1; - }); + + { + const auto vnames = { + m_macrodata_varnames, m_microdata_varnames, m_microdata_g_varnames, + m_deriveddata_varnames, m_idata_varnames}; + + return std::any_of(vnames.begin(), vnames.end(), [=](const auto& vn) { + return get_field_component(name, vn) != -1; + }); + } } // Get field component @@ -1116,6 +1484,10 @@ LBM::get_field(const std::string& name, const int lev, const int ngrow) if (srccomp_mid != -1) { amrex::MultiFab::Copy(*mf, m_f[lev], srccomp_mid, 0, nc, ngrow); } + const int srccomp_g_mid = get_field_component(name, m_microdata_g_varnames); + if (srccomp_g_mid != -1) { + amrex::MultiFab::Copy(*mf, m_g[lev], srccomp_g_mid, 0, nc, ngrow); + } const int srccomp_mdd = get_field_component(name, m_deriveddata_varnames); if (srccomp_mdd != -1) { amrex::MultiFab::Copy(*mf, m_derived[lev], srccomp_mid, 0, nc, ngrow); @@ -1154,6 +1526,10 @@ void LBM::average_down_to(int crse_lev, amrex::IntVect crse_ng) m_f[crse_lev + 1], m_f[crse_lev], Geom(crse_lev), crse_ng, refRatio(crse_lev)); + average_down_with_ghosts( + m_g[crse_lev + 1], m_g[crse_lev], Geom(crse_lev), crse_ng, + refRatio(crse_lev)); + amrex::Gpu::synchronize(); } @@ -1209,15 +1585,24 @@ amrex::Vector LBM::plot_file_mf() boxArray(lev), DistributionMap(lev), static_cast(plot_file_var_names().size()), 0); int cnt = 0; + amrex::MultiFab::Copy( m_plt_mf[lev], m_macrodata[lev], 0, cnt, m_macrodata[lev].nComp(), 0); cnt += m_macrodata[lev].nComp(); + if (m_save_streaming) { amrex::MultiFab::Copy( m_plt_mf[lev], m_f[lev], 0, cnt, m_f[lev].nComp(), 0); cnt += m_f[lev].nComp(); } + + if (m_save_streaming) { + amrex::MultiFab::Copy( + m_plt_mf[lev], m_g[lev], 0, cnt, m_g[lev].nComp(), 0); + cnt += m_g[lev].nComp(); + } + if (m_save_derived) { amrex::MultiFab::Copy( m_plt_mf[lev], m_derived[lev], 0, cnt, m_derived[lev].nComp(), @@ -1258,6 +1643,7 @@ void LBM::write_checkpoint_file() const { BL_PROFILE("LBM::write_checkpoint_file()"); const auto& varnames = m_microdata_varnames; + const auto& varnames_g = m_microdata_g_varnames; // chk00010 write a checkpoint file with this root directory // chk00010/Header this contains information you need to save (e.g., @@ -1338,12 +1724,19 @@ void LBM::write_checkpoint_file() const m_f[lev], amrex::MultiFabFileFullPrefix( lev, checkpointname, "Level_", varnames[0])); } + + for (int lev = 0; lev <= finest_level; ++lev) { + amrex::VisMF::Write( + m_g[lev], amrex::MultiFabFileFullPrefix( + lev, checkpointname, "Level_", varnames_g[0])); + } } void LBM::read_checkpoint_file() { BL_PROFILE("LBM::read_checkpoint_file()"); const auto& varnames = m_microdata_varnames; + const auto& varnames_g = m_microdata_g_varnames; amrex::Print() << "Restarting from checkpoint file " << m_restart_chkfile << std::endl; @@ -1419,6 +1812,8 @@ void LBM::read_checkpoint_file() Geom(lev), ba, dm, {5, 5, 5}, amrex::EBSupport::basic); m_f[lev].define( ba, dm, ncomp, m_f_nghost, amrex::MFInfo(), *(m_factory[lev])); + m_g[lev].define( + ba, dm, ncomp, m_f_nghost, amrex::MFInfo(), *(m_factory[lev])); m_macrodata[lev].define( ba, dm, constants::N_MACRO_STATES, m_macrodata_nghost, amrex::MFInfo(), *(m_factory[lev])); @@ -1426,6 +1821,9 @@ void LBM::read_checkpoint_file() m_eq[lev].define( ba, dm, constants::N_MICRO_STATES, m_eq_nghost, amrex::MFInfo(), *(m_factory[lev])); + m_eq_g[lev].define( + ba, dm, constants::N_MICRO_STATES, m_eq_nghost, amrex::MFInfo(), + *(m_factory[lev])); m_derived[lev].define( ba, dm, constants::N_DERIVED, m_derived_nghost, amrex::MFInfo(), *(m_factory[lev])); @@ -1439,18 +1837,31 @@ void LBM::read_checkpoint_file() lev, m_restart_chkfile, "Level_", varnames[0])); } + for (int lev = 0; lev <= finest_level; ++lev) { + amrex::VisMF::Read( + m_g[lev], amrex::MultiFabFileFullPrefix( + lev, m_restart_chkfile, "Level_", varnames_g[0])); + } + // Populate the other data for (int lev = 0; lev <= finest_level; ++lev) { initialize_is_fluid(lev); initialize_mask(lev); fill_f_inside_eb(lev); m_f[lev].FillBoundary(Geom(lev).periodicity()); + m_g[lev].FillBoundary(Geom(lev).periodicity()); m_macrodata[lev].setVal(0.0); m_eq[lev].setVal(0.0); + m_eq_g[lev].setVal(0.0); m_derived[lev].setVal(0.0); + f_to_macrodata(lev); + macrodata_to_equilibrium(lev); + compute_derived(lev); + + compute_q_corrections(lev); } } diff --git a/Source/Stencil.H b/Source/Stencil.H index 8e58b37..f6fc6bb 100644 --- a/Source/Stencil.H +++ b/Source/Stencil.H @@ -12,6 +12,10 @@ struct Stencil Stencil() = default; #if AMREX_SPACEDIM == 2 + + static constexpr amrex::Real THETA0 = 1.0 / 3.0; + static constexpr amrex::Real INVTHETA0 = (1.0 / THETA0); + const amrex::GpuArray evs = { amrex::IntVect(0, 0), amrex::IntVect(1, 0), amrex::IntVect(-1, 0), amrex::IntVect(0, 1), amrex::IntVect(0, -1), amrex::IntVect(1, 1), @@ -23,34 +27,145 @@ struct Stencil const amrex::GpuArray weights = { 4.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 36.0, 1.0 / 36.0, 1.0 / 36.0, 1.0 / 36.0}; + + const amrex::GpuArray bounce_Xdir = { + 0, 2, 1, 3, 4, 8, 7, 6, 5}; + + const amrex::GpuArray bounce_Ydir = { + 0, 1, 2, 4, 3, 7, 8, 5, 6}; + + const amrex::GpuArray bounce_Zdir = { + 0, 1, 2, 3, 4, 5, 6, 7, 8}; + #else + + static constexpr amrex::Real THETA0 = 1.0 / 3.0; + static constexpr amrex::Real INVTHETA0 = (1.0 / THETA0); + + static constexpr int CSC1 = 1; // simple cubic + static constexpr int CFCC1 = 1; // face centered cubic + static constexpr int CBCC1 = 1; // body centered cubic + const amrex::GpuArray evs = { - amrex::IntVect(0, 0, 0), amrex::IntVect(1, 0, 0), - amrex::IntVect(-1, 0, 0), amrex::IntVect(0, 1, 0), - amrex::IntVect(0, -1, 0), amrex::IntVect(0, 0, 1), - amrex::IntVect(0, 0, -1), amrex::IntVect(1, 1, 0), - amrex::IntVect(-1, -1, 0), amrex::IntVect(1, -1, 0), - amrex::IntVect(-1, 1, 0), amrex::IntVect(1, 0, 1), - amrex::IntVect(-1, 0, -1), amrex::IntVect(1, 0, -1), - amrex::IntVect(-1, 0, 1), amrex::IntVect(0, 1, 1), - amrex::IntVect(0, -1, -1), amrex::IntVect(0, 1, -1), - amrex::IntVect(0, -1, 1), amrex::IntVect(1, 1, 1), - amrex::IntVect(-1, -1, -1), amrex::IntVect(1, 1, -1), - amrex::IntVect(-1, -1, 1), amrex::IntVect(1, -1, 1), - amrex::IntVect(-1, 1, -1), amrex::IntVect(-1, 1, 1), - amrex::IntVect(1, -1, -1)}; + amrex::IntVect(0, 0, 0), - const amrex::GpuArray bounce_dirs = { - 0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, - 13, 16, 15, 18, 17, 20, 19, 22, 21, 24, 23, 26, 25}; + amrex::IntVect(CSC1, 0, 0), + amrex::IntVect(-CSC1, 0, 0), + amrex::IntVect(0, CSC1, 0), + amrex::IntVect(0, -CSC1, 0), + amrex::IntVect(0, 0, CSC1), + amrex::IntVect(0, 0, -CSC1), + + amrex::IntVect(CFCC1, CFCC1, 0), + amrex::IntVect(-CFCC1, -CFCC1, 0), + amrex::IntVect(CFCC1, -CFCC1, 0), + amrex::IntVect(-CFCC1, CFCC1, 0), + amrex::IntVect(CFCC1, 0, CFCC1), + amrex::IntVect(-CFCC1, 0, -CFCC1), + amrex::IntVect(CFCC1, 0, -CFCC1), + amrex::IntVect(-CFCC1, 0, CFCC1), + amrex::IntVect(0, CFCC1, CFCC1), + amrex::IntVect(0, -CFCC1, -CFCC1), + amrex::IntVect(0, CFCC1, -CFCC1), + amrex::IntVect(0, -CFCC1, CFCC1), + + amrex::IntVect(CBCC1, CBCC1, CBCC1), + amrex::IntVect(-CBCC1, -CBCC1, -CBCC1), + amrex::IntVect(CBCC1, -CBCC1, CBCC1), + amrex::IntVect(-CBCC1, CBCC1, -CBCC1), + amrex::IntVect(CBCC1, -CBCC1, -CBCC1), + amrex::IntVect(-CBCC1, CBCC1, CBCC1), + amrex::IntVect(CBCC1, CBCC1, -CBCC1), + amrex::IntVect(-CBCC1, -CBCC1, CBCC1)}; + + static constexpr amrex::Real WSC1 = 2.0 / 27.0; + static constexpr amrex::Real WFCC1 = 1.0 / 54.0; + static constexpr amrex::Real WBCC1 = 1.0 / 216.0; + static constexpr amrex::Real WO = + 1.0 - (6.0 * (WSC1) + 12.0 * (WFCC1) + 8.0 * (WBCC1)); const amrex::GpuArray weights = { - 8.0 / 27.0, 2.0 / 27.0, 2.0 / 27.0, 2.0 / 27.0, 2.0 / 27.0, - 2.0 / 27.0, 2.0 / 27.0, 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, - 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, - 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, 1.0 / 54.0, 1.0 / 216.0, - 1.0 / 216.0, 1.0 / 216.0, 1.0 / 216.0, 1.0 / 216.0, 1.0 / 216.0, - 1.0 / 216.0, 1.0 / 216.0}; + WO, WSC1, WSC1, WSC1, WSC1, WSC1, WSC1, WFCC1, WFCC1, + WFCC1, WFCC1, WFCC1, WFCC1, WFCC1, WFCC1, WFCC1, WFCC1, WFCC1, + WFCC1, WBCC1, WBCC1, WBCC1, WBCC1, WBCC1, WBCC1, WBCC1, WBCC1}; + + enum dvD3Q27 { + DV_ZERO_ZERO_ZERO, + + DV_P1_ZERO_ZERO, + DV_M1_ZERO_ZERO, + DV_ZERO_P1_ZERO, + DV_ZERO_M1_ZERO, + DV_ZERO_ZERO_P1, + DV_ZERO_ZERO_M1, + + DV_P1_P1_ZERO, + DV_M1_M1_ZERO, + DV_P1_M1_ZERO, + DV_M1_P1_ZERO, + DV_P1_ZERO_P1, + DV_M1_ZERO_M1, + DV_P1_ZERO_M1, + DV_M1_ZERO_P1, + DV_ZERO_P1_P1, + DV_ZERO_M1_M1, + DV_ZERO_P1_M1, + DV_ZERO_M1_P1, + + DV_P1_P1_P1, + DV_M1_M1_M1, + DV_P1_M1_P1, + DV_M1_P1_M1, + DV_P1_M1_M1, + DV_M1_P1_P1, + DV_P1_P1_M1, + DV_M1_M1_P1 + }; + + const amrex::GpuArray bounce_dirs = { + DV_ZERO_ZERO_ZERO, DV_M1_ZERO_ZERO, DV_P1_ZERO_ZERO, DV_ZERO_M1_ZERO, + DV_ZERO_P1_ZERO, DV_ZERO_ZERO_M1, DV_ZERO_ZERO_P1, + + DV_M1_M1_ZERO, DV_P1_P1_ZERO, DV_M1_P1_ZERO, DV_P1_M1_ZERO, + DV_M1_ZERO_M1, DV_P1_ZERO_P1, DV_M1_ZERO_P1, DV_P1_ZERO_M1, + DV_ZERO_M1_M1, DV_ZERO_P1_P1, DV_ZERO_M1_P1, DV_ZERO_P1_M1, + + DV_M1_M1_M1, DV_P1_P1_P1, DV_M1_P1_M1, DV_P1_M1_P1, + DV_M1_P1_P1, DV_P1_M1_M1, DV_M1_M1_P1, DV_P1_P1_M1}; + + const amrex::GpuArray bounce_Xdir = { + DV_ZERO_ZERO_ZERO, DV_M1_ZERO_ZERO, DV_P1_ZERO_ZERO, DV_ZERO_P1_ZERO, + DV_ZERO_M1_ZERO, DV_ZERO_ZERO_P1, DV_ZERO_ZERO_M1, + + DV_M1_P1_ZERO, DV_P1_M1_ZERO, DV_M1_M1_ZERO, DV_P1_P1_ZERO, + DV_M1_ZERO_P1, DV_P1_ZERO_M1, DV_M1_ZERO_M1, DV_P1_ZERO_P1, + DV_ZERO_P1_P1, DV_ZERO_M1_M1, DV_ZERO_P1_M1, DV_ZERO_M1_P1, + + DV_M1_P1_P1, DV_P1_M1_M1, DV_M1_M1_P1, DV_P1_P1_M1, + DV_M1_M1_M1, DV_P1_P1_P1, DV_M1_P1_M1, DV_P1_M1_P1}; + + const amrex::GpuArray bounce_Ydir = { + DV_ZERO_ZERO_ZERO, DV_P1_ZERO_ZERO, DV_M1_ZERO_ZERO, DV_ZERO_M1_ZERO, + DV_ZERO_P1_ZERO, DV_ZERO_ZERO_P1, DV_ZERO_ZERO_M1, + + DV_P1_M1_ZERO, DV_M1_P1_ZERO, DV_P1_P1_ZERO, DV_M1_M1_ZERO, + DV_P1_ZERO_P1, DV_M1_ZERO_M1, DV_P1_ZERO_M1, DV_M1_ZERO_P1, + DV_ZERO_M1_P1, DV_ZERO_P1_M1, DV_ZERO_M1_M1, DV_ZERO_P1_P1, + + DV_P1_M1_P1, DV_M1_P1_M1, DV_P1_P1_P1, DV_M1_M1_M1, + DV_P1_P1_M1, DV_M1_M1_P1, DV_P1_M1_M1, DV_M1_P1_P1}; + + const amrex::GpuArray bounce_Zdir = { + DV_ZERO_ZERO_ZERO, DV_P1_ZERO_ZERO, DV_M1_ZERO_ZERO, DV_ZERO_P1_ZERO, + DV_ZERO_M1_ZERO, DV_ZERO_ZERO_M1, DV_ZERO_ZERO_P1, + + DV_P1_P1_ZERO, DV_M1_M1_ZERO, DV_P1_M1_ZERO, DV_M1_P1_ZERO, + DV_P1_ZERO_M1, DV_M1_ZERO_P1, DV_P1_ZERO_P1, DV_M1_ZERO_M1, + DV_ZERO_P1_M1, DV_ZERO_M1_P1, DV_ZERO_P1_P1, DV_ZERO_M1_M1, + + DV_P1_P1_M1, DV_M1_M1_P1, DV_P1_M1_M1, DV_M1_P1_P1, + DV_P1_M1_P1, DV_M1_P1_M1, DV_P1_P1_P1, DV_M1_M1_M1}; + #endif }; diff --git a/Source/Stencil.cpp b/Source/Stencil.cpp index 1328b93..45c631a 100644 --- a/Source/Stencil.cpp +++ b/Source/Stencil.cpp @@ -8,6 +8,7 @@ void check_stencil() const auto& evs = stencil.evs; const auto& weight = stencil.weights; const auto& bounce_dirs = stencil.bounce_dirs; + for (int q = 0; q < constants::N_MICRO_STATES; q++) { const int bounce_q = bounce_dirs[q]; diff --git a/Source/Utilities.H b/Source/Utilities.H index abc4ce9..6402690 100644 --- a/Source/Utilities.H +++ b/Source/Utilities.H @@ -8,36 +8,289 @@ #include "Constants.H" namespace lbm { - AMREX_GPU_DEVICE AMREX_INLINE void set_equilibrium_value( const amrex::Real& rho, const amrex::RealVect& vel, - const amrex::Real& mesh_speed, - const amrex::Real& wt, + const amrex::Real& r_temperature, + const amrex::Real& /*mesh_speed*/, + const amrex::Real& /*wt*/, + const amrex::IntVect& ev, + amrex::Real& eq) +{ + // Warning! Achtung! Strictly for D3Q27 only + // This entropic equilibrium is very stable. Relaxes all 27 moments. + // Unfortunately D3Q27 lattice has only 24 independent moments. For the + // standard lattice, e.g. D3Q27, c_x^3 = c_x , think (-1)^3 = -1. So Qxxx, + // Qyyy and Qzzz are always wrong. We correct them in pxx, pyy and pzz + // during collision. + + const amrex::Real pxx = vel[0] * vel[0] + r_temperature; + const amrex::Real pyy = vel[1] * vel[1] + r_temperature; + amrex::Real pzz = 0.0; + if (AMREX_SPACEDIM == 3) { + pzz = vel[2] * vel[2] + r_temperature; + } + + const amrex::Real phix = + ev[0] * 0.5 * vel[0] + std::abs(ev[0]) * (1.50 * pxx - 1.0) - pxx + 1.0; + const amrex::Real phiy = + ev[1] * 0.5 * vel[1] + std::abs(ev[1]) * (1.50 * pyy - 1.0) - pyy + 1.0; + amrex::Real phiz = 1.0; + if (AMREX_SPACEDIM == 3) { + phiz = ev[2] * 0.5 * vel[2] + std::abs(ev[2]) * (1.50 * pzz - 1.0) - + pzz + 1.0; + } + + eq = rho * phix * phiy * phiz; +} + +AMREX_GPU_DEVICE AMREX_INLINE void set_extended_equilibrium_value( + const amrex::Real& rho, + const amrex::RealVect& vel, + const amrex::Real& pxx, + const amrex::Real& pyy, + const amrex::Real& pzz, + const amrex::Real& /*mesh_speed*/, + const amrex::Real& /*wt*/, const amrex::IntVect& ev, amrex::Real& eq) { - const amrex::Real e_dot_u = - mesh_speed * - (AMREX_D_TERM(ev[0] * vel[0], +ev[1] * vel[1], +ev[2] * vel[2])); - const amrex::Real umag_2 = - AMREX_D_TERM(vel[0] * vel[0], +vel[1] * vel[1], +vel[2] * vel[2]); - const amrex::Real cs = mesh_speed / constants::ROOT3; - const amrex::Real cs_2 = cs * cs; - - // If you make the assumption dx = dt = 1, then - // c = dx/dt = 1/1 = 1 and - // mesh_speed_of_sound = c/sqrt(3) = 1/sqrt(3) - // and these simplifications fall out - // const amrex::Real c1 = 3.0 * e_dot_u; - // const amrex::Real c2 = 4.5 * e_dot_u * e_dot_u; - // const amrex::Real c3 = -1.5 * umag_2; - - const amrex::Real c1 = e_dot_u / cs_2; - const amrex::Real c2 = e_dot_u * e_dot_u / (2.0 * cs_2 * cs_2); - const amrex::Real c3 = -umag_2 / (2.0 * cs_2); - - eq = rho * wt * (1.0 + c1 + c2 + c3); + // Warning! Achtung! Strictly for D3Q27 only + const amrex::Real phix = + ev[0] * 0.5 * vel[0] + std::abs(ev[0]) * (1.50 * pxx - 1.0) - pxx + 1.0; + const amrex::Real phiy = + ev[1] * 0.5 * vel[1] + std::abs(ev[1]) * (1.50 * pyy - 1.0) - pyy + 1.0; + amrex::Real phiz = 1.0; + if (AMREX_SPACEDIM == 3) { + phiz = ev[2] * 0.5 * vel[2] + std::abs(ev[2]) * (1.50 * pzz - 1.0) - + pzz + 1.0; + } + + eq = rho * phix * phiy * phiz; +} + +AMREX_GPU_DEVICE AMREX_INLINE void set_extended_grad_expansion_generic( + const amrex::Real& rho, + const amrex::RealVect& momentum, + const amrex::GpuArray& flux_of_momentum, + /*const amrex::Real& pxx, + const amrex::Real& pyy, + const amrex::Real& pzz, + const amrex::Real& pxy, + const amrex::Real& pxz, + const amrex::Real& pyz,*/ + const amrex::Real& /*mesh_speed*/, + const amrex::Real& wt, + const amrex::IntVect& ev, + const amrex::Real& theta0, + const amrex::RealVect& frame_velocity, + const amrex::Real& s, + amrex::Real& f) +{ + // Note: This is lattice independent, as long as the correct lattice + // temperature theta0 is passed. theta0 = \sum_i w_i cx_i * cx_i + + const amrex::Real jx = momentum[0]; + const amrex::Real jy = momentum[1]; + AMREX_3D_ONLY(const amrex::Real jz = momentum[2]); + + // Note: ux, uy, uz are not flow velocities. + // s is a special scaling factor not related to flow temperature + // Unless absolutely confident about what they do, please use + // ux=uy=uz=0 and s=1, always. Thank you for your understanding. + // This is a special grad expansion with some future proofing. + // Reference (A.93) of https://doi.org/10.3929/ethz-b-000607045 + const amrex::Real ux = frame_velocity[0]; + const amrex::Real uy = frame_velocity[1]; + AMREX_3D_ONLY(const amrex::Real uz = frame_velocity[2]); + + const amrex::Real AMREX_D_DECL( + pxx = flux_of_momentum[0], pyy = flux_of_momentum[1], + pzz = flux_of_momentum[2]); + + AMREX_2D_ONLY(const amrex::Real pxy = flux_of_momentum[3]); + + AMREX_3D_ONLY(const amrex::Real pxy = flux_of_momentum[3]); + AMREX_3D_ONLY(const amrex::Real pxz = flux_of_momentum[4]); + AMREX_3D_ONLY(const amrex::Real pyz = flux_of_momentum[5]); + + const amrex::Real stheta0 = s * theta0; + const amrex::Real one_bystheta0 = 1.0 / stheta0; + const amrex::Real AMREX_D_DECL( + a1x = ((jx)-rho * ux) * one_bystheta0, + a1y = ((jy)-rho * uy) * one_bystheta0, + a1z = ((jz)-rho * uz) * one_bystheta0); + + const amrex::Real AMREX_D_DECL( + a2xx = ((pxx)-rho * s * stheta0 - rho * ux * ux - ux * ((jx)-rho * ux) - + ux * ((jx)-rho * ux)) * + one_bystheta0 * one_bystheta0, + a2yy = ((pyy)-rho * s * stheta0 - rho * uy * uy - uy * ((jy)-rho * uy) - + uy * ((jy)-rho * uy)) * + one_bystheta0 * one_bystheta0, + a2zz = ((pzz)-rho * s * stheta0 - rho * uz * uz - uz * ((jz)-rho * uz) - + uz * ((jz)-rho * uz)) * + one_bystheta0 * one_bystheta0); + + AMREX_2D_ONLY( + const amrex::Real a2xy = ((pxy)-0 - rho * ux * uy - + ux * ((jy)-rho * uy) - uy * ((jx)-rho * ux)) * + one_bystheta0 * one_bystheta0); + + AMREX_3D_ONLY( + const amrex::Real a2xy = ((pxy)-0 - rho * ux * uy - + ux * ((jy)-rho * uy) - uy * ((jx)-rho * ux)) * + one_bystheta0 * one_bystheta0); + + AMREX_3D_ONLY(const amrex::Real a2xz = + ((pxz)-0 - rho * ux * uz - ux * ((jz)-rho * uz) - + uz * ((jx)-rho * ux)) * + one_bystheta0 * one_bystheta0;); + + AMREX_3D_ONLY(const amrex::Real a2yz = + ((pyz)-0 - rho * uy * uz - uy * ((jz)-rho * uz) - + uz * ((jy)-rho * uy)) * + one_bystheta0 * one_bystheta0;); + + f = rho + AMREX_D_TERM(a1x * ev[0], +a1y * ev[1], +a1z * ev[2]); + + f += + 0.5 * + (AMREX_D_TERM( + (ev[0] * ev[0] - theta0) * a2xx, + + +(ev[1] * ev[1] - theta0) * a2yy + 2.0 * (ev[0] * ev[1] - 0) * a2xy, + + +(ev[2] * ev[2] - theta0) * a2zz + + 2.0 * (ev[0] * ev[2] - 0) * a2xz + + 2.0 * (ev[1] * ev[2] - 0) * a2yz)); + + f *= wt; +} + +AMREX_GPU_DEVICE AMREX_INLINE void set_population_zero(amrex::Real& eq) +{ + eq = 0.0; +} + +AMREX_GPU_DEVICE AMREX_INLINE amrex::Real get_energy( + const amrex::Real T, + const amrex::Real rho, + const amrex::Real ux, + const amrex::Real uy, + const amrex::Real uz, + const amrex::Real Cv) +{ + return rho * (2.0 * Cv * T + (ux * ux + uy * uy + uz * uz)); +} + +AMREX_GPU_DEVICE AMREX_INLINE amrex::Real get_energy( + const amrex::Real T, + const amrex::Real rho, + const amrex::RealVect& vel, + const amrex::Real Cv) +{ + return rho * + (2.0 * Cv * T + + AMREX_D_TERM(vel[0] * vel[0], +vel[1] * vel[1], +vel[2] * vel[2])); +} + +AMREX_GPU_DEVICE AMREX_INLINE amrex::Real get_temperature( + const amrex::Real two_rho_e, + const amrex::Real rho, + const amrex::Real ux, + const amrex::Real uy, + const amrex::Real uz, + const amrex::Real Cv) +{ + return (0.50 / Cv) * ((two_rho_e / rho) - (ux * ux + uy * uy + uz * uz)); +} + +AMREX_GPU_DEVICE AMREX_INLINE amrex::Real get_temperature( + const amrex::Real two_rho_e, + const amrex::Real rho, + const amrex::RealVect& vel, + const amrex::Real Cv) +{ + return (0.50 / Cv) * + ((two_rho_e / rho) - + AMREX_D_TERM(vel[0] * vel[0], +vel[1] * vel[1], +vel[2] * vel[2])); +} + +AMREX_GPU_DEVICE AMREX_INLINE void get_equilibrium_moments( + const amrex::Real rho, + const amrex::Real ux, + const amrex::Real uy, + const amrex::Real uz, + const amrex::Real total_energy, + const amrex::Real Cv, + const amrex::Real R, + amrex::Real& qxEq, + amrex::Real& qyEq, + amrex::Real& qzEq, + amrex::Real& RxxEq, + amrex::Real& RyyEq, + amrex::Real& RzzEq, + amrex::Real& RxyEq, + amrex::Real& RxzEq, + amrex::Real& RyzEq) +{ + + amrex::Real energy = total_energy / (2.0 * rho); + amrex::Real temperature = + get_temperature(total_energy, rho, ux, uy, uz, Cv); + amrex::Real p = rho * R * temperature; + amrex::Real h = energy + (p / rho); + + qxEq = 2.0 * rho * ux * h; + qyEq = 2.0 * rho * uy * h; + qzEq = 2.0 * rho * uz * h; + RxxEq = 2.0 * rho * ux * ux * (h + (p / rho)) + 2.0 * p * h; + RyyEq = 2.0 * rho * uy * uy * (h + (p / rho)) + 2.0 * p * h; + RzzEq = 2.0 * rho * uz * uz * (h + (p / rho)) + 2.0 * p * h; + RxyEq = 2.0 * rho * ux * uy * (h + (p / rho)) + 0; + RxzEq = 2.0 * rho * ux * uz * (h + (p / rho)) + 0; + RyzEq = 2.0 * rho * uy * uz * (h + (p / rho)) + 0; +} + +AMREX_GPU_DEVICE AMREX_INLINE void get_equilibrium_moments( + const amrex::Real rho, + const amrex::RealVect& vel, + const amrex::Real total_energy, + const amrex::Real Cv, + const amrex::Real R, + amrex::RealVect& qEq, + amrex::Real& RxxEq, + amrex::Real& RyyEq, + amrex::Real& RzzEq, + amrex::Real& RxyEq, + amrex::Real& RxzEq, + amrex::Real& RyzEq) +{ + + amrex::Real energy = total_energy / (2.0 * rho); + amrex::Real temperature = get_temperature(total_energy, rho, vel, Cv); + amrex::Real p = rho * R * temperature; + amrex::Real h = energy + (p / rho); + + qEq[0] = 2.0 * rho * vel[0] * h; + qEq[1] = 2.0 * rho * vel[1] * h; + if (AMREX_SPACEDIM == 3) { + qEq[2] = 2.0 * rho * vel[2] * h; + } + + RxxEq = 2.0 * rho * vel[0] * vel[0] * (h + (p / rho)) + 2.0 * p * h; + RyyEq = 2.0 * rho * vel[1] * vel[1] * (h + (p / rho)) + 2.0 * p * h; + if (AMREX_SPACEDIM == 3) { + RzzEq = 2.0 * rho * vel[2] * vel[2] * (h + (p / rho)) + 2.0 * p * h; + } + RxyEq = 2.0 * rho * vel[0] * vel[1] * (h + (p / rho)) + 0; + if (AMREX_SPACEDIM == 3) { + RxzEq = 2.0 * rho * vel[0] * vel[2] * (h + (p / rho)) + 0; + } + if (AMREX_SPACEDIM == 3) { + RyzEq = 2.0 * rho * vel[1] * vel[2] * (h + (p / rho)) + 0; + } } AMREX_GPU_DEVICE AMREX_INLINE amrex::Real gradient( diff --git a/Source/VelocityBC.H b/Source/VelocityBC.H index c6a8414..e16faac 100644 --- a/Source/VelocityBC.H +++ b/Source/VelocityBC.H @@ -6,6 +6,7 @@ #include #include #include +#include "Constants.H" namespace lbm::bc { @@ -13,6 +14,7 @@ struct NoOp { struct DeviceOp { + AMREX_GPU_DEVICE void operator()( const amrex::IntVect& /*iv*/, @@ -20,7 +22,10 @@ struct NoOp const int /*ndir*/, const amrex::Real /*time*/, amrex::GeometryData const& /*geom*/, - amrex::RealVect& /*vel*/) const + amrex::RealVect& /*vel*/, + amrex::Real& /*R*/, + amrex::Real& /*T*/, + amrex::Real& /*gamma*/) const {} }; @@ -40,6 +45,16 @@ struct Constant int dir{1}; amrex::Real u0{0.0}; + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + amrex::Real Mach_0{0.005}; + AMREX_GPU_DEVICE void operator()( const amrex::IntVect& /*iv*/, @@ -47,9 +62,15 @@ struct Constant const int /*ndir*/, const amrex::Real /*time*/, amrex::GeometryData const& /*geom*/, - amrex::RealVect& vel) const + amrex::RealVect& vel, + amrex::Real& R, + amrex::Real& T, + amrex::Real& gamma) const { vel[dir] = u0; + R = (R_u / m_bar); + T = initial_temperature; + gamma = adiabatic_exponent; } }; @@ -68,6 +89,16 @@ struct Channel { amrex::Real u_ref{1.0}; + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + amrex::Real Mach_ref{0.005}; + AMREX_GPU_DEVICE void operator()( const amrex::IntVect& iv, @@ -75,13 +106,19 @@ struct Channel const int /*ndir*/, const amrex::Real /*time*/, amrex::GeometryData const& geom, - amrex::RealVect& vel) const + amrex::RealVect& vel, + amrex::Real& R, + amrex::Real& T, + amrex::Real& gamma) const { const int* domhi = geom.Domain().hiVect(); const amrex::Real c1 = iv[1] * (domhi[1] - iv[1]); const amrex::Real c2 = AMREX_D_PICK(, c1, iv[2] * (domhi[2] - iv[2])); vel[0] = 16.0 * u_ref * c1 * c2 / std::pow((domhi[1] + 1), 4); + R = (R_u / m_bar); + T = initial_temperature; + gamma = adiabatic_exponent; } }; @@ -102,6 +139,17 @@ struct Parabolic int tangential_dir{1}; amrex::Real um{1.0}; + amrex::Real initial_temperature = 1.0 / 3.0; + amrex::Real adiabatic_exponent = 5.0 / 3.0; + + const amrex::Real R_u = constants::AIR_MOLAR_MASS; + amrex::Real m_bar = constants::AIR_MOLAR_MASS; + amrex::Real speed_of_sound_ref = + std::sqrt(adiabatic_exponent * (R_u / m_bar) * initial_temperature); + + int model_type = 1; + amrex::Real mach_m{0.05}; + AMREX_GPU_DEVICE void operator()( const amrex::IntVect& iv, @@ -109,7 +157,10 @@ struct Parabolic const int /*ndir*/, const amrex::Real /*time*/, amrex::GeometryData const& geom, - amrex::RealVect& vel) const + amrex::RealVect& vel, + amrex::Real& R, + amrex::Real& T, + amrex::Real& gamma) const { const amrex::Real* prob_lo = geom.ProbLo(); const amrex::Real* prob_hi = geom.ProbHi(); @@ -118,8 +169,13 @@ struct Parabolic prob_hi[normal_dir] - prob_lo[normal_dir]; const amrex::Real x = prob_lo[normal_dir] + (iv[normal_dir] + 0.5) * dx[normal_dir]; + vel[tangential_dir] = 4.0 * um * x * (height - x) / (height * height); + + R = (R_u / m_bar); + T = initial_temperature; + gamma = adiabatic_exponent; } }; diff --git a/Source/VelocityBC.cpp b/Source/VelocityBC.cpp index 0607618..0661bbd 100644 --- a/Source/VelocityBC.cpp +++ b/Source/VelocityBC.cpp @@ -8,12 +8,32 @@ Constant::Constant() amrex::ParmParse pp("velocity_bc_constant"); pp.query("dir", m_op.dir); pp.query("u0", m_op.u0); + + m_op.model_type = 1; + pp.query("Mach_0", m_op.Mach_0); + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + m_op.u0 = m_op.Mach_0 * m_op.speed_of_sound_ref; } Channel::Channel() { amrex::ParmParse pp("velocity_bc_channel"); pp.query("u_ref", m_op.u_ref); + + m_op.model_type = 1; + pp.query("Mach_ref", m_op.Mach_ref); + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + m_op.u_ref = m_op.Mach_ref * m_op.speed_of_sound_ref; } Parabolic::Parabolic() @@ -22,6 +42,16 @@ Parabolic::Parabolic() pp.query("normal_dir", m_op.normal_dir); pp.query("tangential_dir", m_op.tangential_dir); pp.query("um", m_op.um); + + m_op.model_type = 1; + pp.query("Mach_m", m_op.mach_m); + pp.query("initial_temperature", m_op.initial_temperature); + pp.query("adiabatic_exponent", m_op.adiabatic_exponent); + pp.query("mean_molecular_mass", m_op.m_bar); + m_op.speed_of_sound_ref = std::sqrt( + m_op.adiabatic_exponent * (m_op.R_u / m_op.m_bar) * + m_op.initial_temperature); + m_op.um = m_op.mach_m * m_op.speed_of_sound_ref; } } // namespace lbm::bc diff --git a/Tests/test_files/channel_regular/channel_regular.inp b/Tests/test_files/channel_regular/channel_regular.inp index 9fbaf5e..b7ae6d7 100644 --- a/Tests/test_files/channel_regular/channel_regular.inp +++ b/Tests/test_files/channel_regular/channel_regular.inp @@ -11,19 +11,19 @@ amr.plot_int = 10 amr.chk_int = 10 lbm.bc_lo = 2 1 1 -lbm.bc_hi = 3 1 1 +lbm.bc_hi = 5 1 1 lbm.dx_outer = 0.5 lbm.dt_outer = 0.5 #lbm.reynolds = 10.23 -lbm.nu = 0.01733333333333333 +lbm.nu = 0.20 lbm.save_streaming = 0 lbm.velocity_bc_type = "channel" -velocity_bc_channel.u_ref = 0.1 +velocity_bc_channel.Mach_ref = 0.001 lbm.ic_type = "constant" ic_constant.density = 1.0 -ic_constant.velocity = 0.0 0.0 0.0 +ic_constant.mach_components = 0.002 0.0 0.0 eb2.geom_type="all_regular" diff --git a/Tests/test_files/single_rotated_box/single_rotated_box.inp b/Tests/test_files/single_rotated_box/single_rotated_box.inp index 68c9c92..8b5dd23 100644 --- a/Tests/test_files/single_rotated_box/single_rotated_box.inp +++ b/Tests/test_files/single_rotated_box/single_rotated_box.inp @@ -14,15 +14,15 @@ amr.plot_int = 10 amr.chk_int = 10 amr.file_name_digits = 5 -lbm.bc_lo = 1 2 0 -lbm.bc_hi = 1 5 0 +lbm.bc_lo = 6 2 0 +lbm.bc_hi = 6 5 0 lbm.dx_outer = 1.0 lbm.dt_outer = 1.0 -lbm.nu = 0.006 +lbm.nu = 0.20 lbm.save_streaming = 0 lbm.velocity_bc_type = "parabolic" -velocity_bc_parabolic.um = 0.015 +velocity_bc_parabolic.Mach_m = 0.0025 velocity_bc_parabolic.normal_dir = 0 velocity_bc_parabolic.tangential_dir = 1 diff --git a/Tests/test_files/sod_test/sod.inp b/Tests/test_files/sod_test/sod.inp new file mode 100644 index 0000000..7643cd0 --- /dev/null +++ b/Tests/test_files/sod_test/sod.inp @@ -0,0 +1,56 @@ +# How to use this sod test tube case? +# set ic_sod_test.initial_temperature=lbm.initial_temperature to a value <= 0.3333 +# set lbm.nu to a value <= 0.0100 +# Further instructions in sod_tester.ipynb +# Note. Always: geometry.prob_hi[0]=amr.n_cell[0]=amr.max_grid_size=2.0*ic_sod_test.xDiscontinuity + +max_step = 1500 + +# geometry parameters +geometry.prob_lo = 0.0 -1.0 -1.0 +geometry.prob_hi = 3000.0 1.0 1.0 +geometry.is_periodic = 0 1 1 + +# timestepping +amr.n_cell = 3000 2 2 +amr.max_level = 0 +amr.max_grid_size = 3000 +amr.blocking_factor = 1 +amr.plot_int = 100 +amr.chk_int = 100 +amr.file_name_digits = 5 + +lbm.bc_lo = 5 0 0 +lbm.bc_hi = 5 0 0 +lbm.dx_outer = 1.0 +lbm.dt_outer = 1.0 +lbm.nu = 0.010 +lbm.alpha = 0.010 +lbm.save_streaming = 0 +lbm.compute_forces = 0 + +lbm.ic_type = "sod_test" +ic_sod_test.density = 0.50 +ic_sod_test.velocity = 0.0 0.0 0.0 +ic_sod_test.mach_components = 0.0 0.0 0.0 + +# Set ic_sod_test.xDiscontinuity equal to half length to place +# discontinuity in the middle +ic_sod_test.x_discontinuity = 1500.0 + +ic_sod_test.initial_temperature = 0.20 +ic_sod_test.adiabatic_exponent = 2.0 +ic_sod_test.mean_molecular_mass = 28.96 +ic_sod_test.density_ratio = 4.00 +ic_sod_test.temperature_ratio = 0.1250 +lbm.initial_temperature = 0.20 +lbm.adiabatic_exponent = 2.0 +lbm.mean_molecular_mass = 28.96 + +eb2.geom_type = "all_regular" + +amrex.fpe_trap_invalid = 1 +amrex.fpe_trap_zero = 1 +amrex.fpe_trap_overflow = 1 +amrex.the_arena_is_managed = 0 +amrex.abort_on_out_of_gpu_memory = 1 diff --git a/Tests/test_files/tg/tg.inp b/Tests/test_files/tg/tg.inp index b6df1cc..4e2cda3 100644 --- a/Tests/test_files/tg/tg.inp +++ b/Tests/test_files/tg/tg.inp @@ -17,7 +17,7 @@ lbm.bc_hi = 0 0 0 lbm.dx_outer = 0.5 lbm.dt_outer = 0.5 #lbm.reynolds = 10.23 -lbm.nu = 0.01733333333333333 +lbm.nu = 0.1733333333333333 lbm.save_streaming = 1 lbm.ic_type = "taylorgreen" diff --git a/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_air.inp b/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_air.inp new file mode 100644 index 0000000..4948fd5 --- /dev/null +++ b/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_air.inp @@ -0,0 +1,55 @@ +# How to use this thermal diffusivity tester? +# set ic_thermaldiffusivity_test.initial_temperature=lbm.initial_temperature to a value <= 0.3333 +# set lbm.nu to a value <= 0.0100 +# Further instructions in thermaldiffusivity_tester.ipynb +# Note. Always: geometry.prob_hi[1]=amr.n_cell[1]=amr.max_grid_size=ic_thermaldiffusivity_test.waveLength + +max_step = 50000 + +# geometry parameters +geometry.prob_lo = 0.0 0.0 -1.0 +geometry.prob_hi = 6.0 200.0 1.0 +geometry.is_periodic = 1 1 1 + +# timestepping +amr.n_cell = 6 200 2 +amr.max_level = 0 +amr.max_grid_size = 200 +amr.blocking_factor = 1 +amr.plot_int = 5000 +amr.chk_int = 5000 +amr.file_name_digits = 5 + +lbm.bc_lo = 0 0 0 +lbm.bc_hi = 0 0 0 +lbm.dx_outer = 1.0 +lbm.dt_outer = 1.0 +lbm.nu = 0.0071 +lbm.alpha = 0.010 +lbm.save_streaming = 0 +lbm.compute_forces = 1 + +# lbm.ic_type = "constant" +lbm.ic_type = "thermaldiffusivity_test" +ic_thermaldiffusivity_test.density = 1.0 +ic_thermaldiffusivity_test.velocity = 0.0 0.0 0.0 +ic_thermaldiffusivity_test.mach_components = 0.0 0.0 0.0 + +# Set ic_thermaldiffusivity_test.waveLength equal to geometry.prob_hi y for perfectly fitting +# one wave in the periodic domain +ic_thermaldiffusivity_test.waveLength = 200.0 + +ic_thermaldiffusivity_test.initial_temperature = 0.03333 +ic_thermaldiffusivity_test.adiabatic_exponent = 1.40 +ic_thermaldiffusivity_test.mean_molecular_mass = 28.96 +lbm.initial_temperature = 0.03333 +lbm.adiabatic_exponent = 1.40 +lbm.mean_molecular_mass = 28.96 + +eb2.geom_type = "all_regular" + +amrex.fpe_trap_invalid = 1 +amrex.fpe_trap_zero = 1 +amrex.fpe_trap_overflow = 1 +amrex.the_arena_is_managed = 0 +amrex.abort_on_out_of_gpu_memory = 1 diff --git a/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_ammonia.inp b/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_ammonia.inp new file mode 100644 index 0000000..1501e5b --- /dev/null +++ b/Tests/test_files/thermaldiffusivity_test/thermal_diffusivity_ammonia.inp @@ -0,0 +1,55 @@ +# How to use this thermal diffusivity tester? +# set ic_thermaldiffusivity_test.initial_temperature=lbm.initial_temperature to a value <= 0.3333 +# set lbm.nu to a value <= 0.0100 +# Further instructions in thermaldiffusivity_tester.ipynb +# Note. Always: geometry.prob_hi[1]=amr.n_cell[1]=amr.max_grid_size=ic_thermaldiffusivity_test.waveLength + +max_step = 50000 + +# geometry parameters +geometry.prob_lo = 0.0 0.0 -1.0 +geometry.prob_hi = 6.0 200.0 1.0 +geometry.is_periodic = 1 1 1 + +# timestepping +amr.n_cell = 6 200 2 +amr.max_level = 0 +amr.max_grid_size = 200 +amr.blocking_factor = 1 +amr.plot_int = 5000 +amr.chk_int = 5000 +amr.file_name_digits = 5 + +lbm.bc_lo = 0 0 0 +lbm.bc_hi = 0 0 0 +lbm.dx_outer = 1.0 +lbm.dt_outer = 1.0 +lbm.nu = 0.000008076 +lbm.alpha = 0.000010 +lbm.save_streaming = 0 +lbm.compute_forces = 1 + +# lbm.ic_type = "constant" +lbm.ic_type = "thermaldiffusivity_test" +ic_thermaldiffusivity_test.density = 1.0 +ic_thermaldiffusivity_test.velocity = 0.0 0.0 0.0 +ic_thermaldiffusivity_test.mach_components = 0.0 0.0 0.0 + +# Set ic_thermaldiffusivity_test.waveLength equal to geometry.prob_hi y for perfectly fitting +# one wave in the periodic domain +ic_thermaldiffusivity_test.waveLength = 200.0 + +ic_thermaldiffusivity_test.initial_temperature = 0.003333 +ic_thermaldiffusivity_test.adiabatic_exponent = 1.32 +ic_thermaldiffusivity_test.mean_molecular_mass = 17.031 +lbm.initial_temperature = 0.003333 +lbm.adiabatic_exponent = 1.32 +lbm.mean_molecular_mass = 17.031 + +eb2.geom_type = "all_regular" + +amrex.fpe_trap_invalid = 1 +amrex.fpe_trap_zero = 1 +amrex.fpe_trap_overflow = 1 +amrex.the_arena_is_managed = 0 +amrex.abort_on_out_of_gpu_memory = 1 diff --git a/Tests/test_files/viscosity_test/viscosity_test.inp b/Tests/test_files/viscosity_test/viscosity_test.inp new file mode 100644 index 0000000..0ae7042 --- /dev/null +++ b/Tests/test_files/viscosity_test/viscosity_test.inp @@ -0,0 +1,54 @@ +# How to use this visosity tester? +# set ic_viscosity_test.initial_temperature=lbm.initial_temperature to a value <= 0.3333 +# set lbm.nu to a value <= 0.0100 +# Further instructions in viscosity_tester.ipynb +# Note. Always: geometry.prob_hi[1]=amr.n_cell[1]=amr.max_grid_size=ic_viscosity_test.waveLength + +max_step = 50000 + +# geometry parameters +geometry.prob_lo = 0.0 0.0 -1.0 +geometry.prob_hi = 6.0 200.0 1.0 +geometry.is_periodic = 1 1 1 + +# timestepping +amr.n_cell = 6 200 2 +amr.max_level = 0 +amr.max_grid_size = 200 +amr.blocking_factor = 1 +amr.plot_int = 5000 +amr.chk_int = 5000 +amr.file_name_digits = 5 + +lbm.bc_lo = 0 0 0 +lbm.bc_hi = 0 0 0 +lbm.dx_outer = 1.0 +lbm.dt_outer = 1.0 +lbm.nu = 0.00010 +lbm.save_streaming = 0 +lbm.compute_forces = 1 + +# lbm.ic_type = "constant" +lbm.ic_type = "viscosity_test" +ic_viscosity_test.density = 1.0 +ic_viscosity_test.velocity = 0.0 0.0 0.0 +ic_viscosity_test.mach_components = 0.0 0.0 0.0 + +# Set ic_viscosity_test.waveLength equal to geometry.prob_hi y for perfectly fitting +# one wave in the periodic domain +ic_viscosity_test.waveLength = 200.0 + +ic_viscosity_test.initial_temperature = 0.3333 +ic_viscosity_test.adiabatic_exponent = 1.6667 +ic_viscosity_test.mean_molecular_mass = 28.96 +lbm.initial_temperature = 0.3333 +lbm.adiabatic_exponent = 1.6667 +lbm.mean_molecular_mass = 28.96 + +eb2.geom_type = "all_regular" + +amrex.fpe_trap_invalid = 1 +amrex.fpe_trap_zero = 1 +amrex.fpe_trap_overflow = 1 +amrex.the_arena_is_managed = 0 +amrex.abort_on_out_of_gpu_memory = 1 diff --git a/Tools/sod_test/sod_test.ipynb b/Tools/sod_test/sod_test.ipynb new file mode 100644 index 0000000..5dc64a7 --- /dev/null +++ b/Tools/sod_test/sod_test.ipynb @@ -0,0 +1,270 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "1a0d1aad-76b1-4de1-ba9f-660bc5e0bc78", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np,matplotlib.pyplot as plt,scipy as sp" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4dcc8464-537f-4c8a-b22b-af27988e8d71", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: sodshock in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (0.1.9)\n", + "Requirement already satisfied: numpy>=1.3.0 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from sodshock) (2.1.2)\n", + "Requirement already satisfied: matplotlib>=2.0.0 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from sodshock) (3.9.2)\n", + "Requirement already satisfied: scipy>=1.0.0 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from sodshock) (1.14.1)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (1.3.0)\n", + "Requirement already satisfied: cycler>=0.10 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (4.54.1)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (1.4.7)\n", + "Requirement already satisfied: packaging>=20.0 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (24.1)\n", + "Requirement already satisfied: pillow>=8 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (11.0.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (3.2.0)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from matplotlib>=2.0.0->sodshock) (2.9.0)\n", + "Requirement already satisfied: six>=1.5 in /Users/nsawant/miniforge3/envs/ct-env/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib>=2.0.0->sodshock) (1.16.0)\n" + ] + } + ], + "source": [ + "!pip install sodshock" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8084d833-98df-4c2a-bd9c-ee1e2dc9892f", + "metadata": {}, + "outputs": [], + "source": [ + "#plot over line in paraview, File > Save Data > csv > select rho, tempererature and vel_x\n", + "profilesLBM=np.loadtxt('profiles.csv',delimiter=\",\",skiprows=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1daf7b2d-7bc4-4582-84ca-ac30a7541aad", + "metadata": {}, + "outputs": [], + "source": [ + "rhoLBM=profilesLBM[:,0]\n", + "temperatureLBM=profilesLBM[:,1]\n", + "velocityLBM=profilesLBM[:,2]\n", + "xLBM=np.linspace(0.0,1.0,rhoLBM.size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f411d1d-5140-401c-9d27-f1bba13071da", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "10cf147e-2952-499e-8505-400373981a27", + "metadata": {}, + "outputs": [], + "source": [ + "#This cell needs user inputs\n", + "#Please match parameters with sod.inp file used in marbles\n", + "\n", + "maxTime=1500 #max_step from the sod.inp file of marbles\n", + "\n", + "nX=3000;nY=1;nZ=1;\n", + "dx=dy=dz=1.0\n", + "\n", + "gamma=2.0 #ic_sodTest.adiabaticExponent\n", + "\n", + "rho0=0.50 #ic_sodTest.density\n", + "ux0=0.00\n", + "uy0=0.00\n", + "uz0=0.00\n", + "T0=0.20 #ic_sodTest.initialTemperature\n", + "\n", + "densityRatio=4.0 #ic_sodTest.densityRatio\n", + "temperatureRatio=0.1250 #ic_sodTest.temperatureRatio\n", + "\n", + "cs=np.sqrt(gamma*T0)\n", + "\n", + "nu=0.010\n", + "Prandtl=1.0\n", + "alpha=nu/Prandtl\n", + "\n", + "dt=1.0\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "28a3ea97-11bd-4df6-8561-792c68cbafb5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Positions:\n", + "Head of Rarefaction : 0.18377223398316206\n", + "Foot of Rarefaction : 0.22841878108735808\n", + "Contact Discontinuity : 0.5297643647361306\n", + "Shock : 0.6363334859985355\n", + "Regions:\n", + "Region 1 : (0.1, 0.5, 0.0)\n", + "Region 2 : RAREFACTION\n", + "Region 3 : (np.float64(0.08246303682406858), np.float64(0.454045803923097), np.float64(0.05952872947226134))\n", + "Region 4 : (np.float64(0.08246303682406858), np.float64(2.558592665183791), np.float64(0.05952872947226134))\n", + "Region 5 : (0.05, 2.0, 0.0)\n" + ] + }, + { + "data": { + "image/png": "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N954o0cDBAAAAFC6XKok1K9fX//5z38Ktc+cOdPtgAAAgPuoJABwh0uVhN27d2vfvn327ffff18DBgzQk08+qezsbI8FBwAAXEOSAMAdLiUJo0aN0g8//CBJ+umnnzR06FBVqlRJ7777riZMmODRAAEAAACULpeShB9++EGtW7eWJL377rvq1q2b3n77bS1dulSrVq3yZHwAAMAFVBIAuMOlJMEwDNlsNkl5t0DNfzZCVFSUTp486bnoAAAAAJQ6l5KEdu3a6fnnn9e//vUvbd68WTfddJOkvIesRUREeDRAAADgPCoJANzhUpIwa9Ys7d69W4888ogmTZqkhg0bSpLee+89derUyaMBAgAA55EkAHCHS7dAbdmypenuRvlefvllWa1Wt4MCAAAA4DsuVRIk6cyZM1q8eLHi4+N1+vRpSdL+/ft1/PhxjwUHAABcQyUBgDtcqiR88803uu6663TppZcqKSlJ999/vy677DKtWbNGR44c0bJlyzwdJwAAcEJ+kgAArnCpkhAXF6d7771XBw8eVGhoqL29T58++uKLLzwWHAAAcA+VBACucClJ+PrrrzVq1KhC7fXq1VN6errbQQEAAPcw3QiAO1xKEkJDQ5WZmVmo/cCBA6pZs6bbQQEAAADwHZeShP79++u5557T+fPnJeV9W5GcnKyJEydq0KBBHg0QAAA4j0oCAHe4lCRMnz5dJ06cUK1atfTHH3+oe/fuatiwoapWraqpU6d6OkYAAOAkFi4DcIdLdzcKCwvT1q1b9fnnn2v37t2y2Wxq27atrr/+ek/HBwAA3EAlAYArnE4ScnJyFBoaqj179qhnz57q2bOnN+ICAABuYLoRAHc4Pd0oMDBQ0dHRys3N9UY8AADAA5huBMAdLq1JmDx5sulJywAAwD9RSQDgCpfWJMyZM0eHDh1S3bp1FR0drcqVK5ve3717t0eCAwAArmG6EQB3uJQkDBgwQBaLhV88AAAAQDnkVJLw+++/6/HHH9e///1vnT9/Xtddd51effVV1ahRw1vxAQAAF1BJAOAOp9YkTJkyRUuXLtVNN92k22+/XZ9++qkefPBBb8UGAABcxMJlAO5wqpKwevVqLVmyREOHDpUk3XnnnercubNyc3NltVq9EiAAAHAdlQQArnCqkpCSkqKuXbvat6+55hoFBgbq2LFjHg8MAAC4julGANzh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DuMVVBIAoOz57rvv1KxZM1122WU6deqUr8MBAL/k80rC3r171aZNG/39739X7dq1NWrUKH311VfeOhwAAAAAD/FaktCiRQvNmDFDqampeuONN5Senq4uXbqoefPmmjFjhk6cOOGtQwMAKiBugQoAnuP1W6AGBgZq4MCB+r//+z/985//1I8//qjHHntMkZGRuvvuu5WWlubtEAAAAAA4wetJws6dO/XQQw+pTp06mjFjhh577DH9+OOP+vzzz5Wamqr+/ft7OwQAQAVCJQEA3BforYFnzJihN954QwcOHFDfvn21bNky9e3bVwF/PvkxJiZGCxcuVJMmTbwVAgCgAvHjO3oDQJnjtSRh/vz5uu+++3Tvvfeqdu3aRfapX7++lixZ4q0QAAAAALjAa0nChg0bVL9+fXvlIJ9hGEpJSVH9+vUVHBys4cOHeysEAEAFwsJlAPAcr61JuOKKK3Ty5MlC7adPn1ZMTIy3DgsAAADATV5LEoqbG/rrr7+WqQerAQDKFioJAOA+j083iouLk5T3S/rpp59WpUqV7O/l5uZqx44dat26tacPCwCo4Fi4DACe4/EkITExUVLeL+t9+/YpODjY/l5wcLBatWqlxx57zNOHBQAAAOAhHk8SNm7cKEm69957NXv2bIWFhXn6EAAAFMLCZQDwHK/d3eiNN97w1tAAAAAAvMijScItt9yipUuXKiwsTLfcckuJfVevXu3JQwMAKjgqCQDgOR5NEsLDw+2/nMPDwz05NAAAAIBS4tEk4cIpRkw3AgAAAMomrz0n4Y8//tDvv/9u3z5y5IhmzZql9evXe+uQAIAKjOlGAOA5XksS+vfvr2XLlkmSzpw5o2uuuUavvPKK+vfvr/nz53vrsAAAAADc5LUkYffu3eratask6b333lPt2rV15MgRLVu2THPmzPHWYQEAFRSVBADwHK8lCb///ruqVq0qSVq/fr1uueUWBQQEqEOHDjpy5Ii3DgsAAADATV5LEho2bKh///vfSklJ0bp169SrVy9J0vHjx516wNoXX3yhfv36qW7durJYLPr3v/9dYv9NmzbJYrEUen3//ffunA4AoIygkgAA7vNakvD000/rscceU4MGDdS+fXt17NhRUl5VoU2bNg6P89tvv6lVq1Z67bXXnDr+gQMHlJaWZn81atTIqf0BAGVL/nQjAID7vPbE5Vtv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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import sodshock\n", + "\n", + "\n", + "def sodAnalytical(maxTime):\n", + " dustFrac = 0.0\n", + " npts = nX\n", + " t = maxTime/nX\n", + " rho_L=rho0\n", + " rho_R=densityRatio*rho_L\n", + " T_L=T0\n", + " T_R=temperatureRatio*T_L\n", + " left_state = (rho_L*T_L,rho_L,ux0) #P,rho,u\n", + " right_state = (rho_R*T_R,rho_R,ux0)\n", + " positions, regions, values = sodshock.solve(left_state=left_state, \\\n", + " right_state=right_state, geometry=(0., 1., 0.5), t=t,\n", + " gamma=gamma, npts=npts, dustFrac=dustFrac)\n", + " # left_state and right_state set pressure, density and u (velocity)\n", + " # geometry sets left boundary on 0., right boundary on 1 and initial\n", + " # position of the shock xi on 0.5\n", + " # t is the time evolution for which positions and states in tube should be\n", + " # calculated\n", + " # gamma denotes specific heat\n", + " # note that gamma and npts are default parameters (1.4 and 500) in solve\n", + " # function\n", + " positions, regions, values = sodshock.solve(left_state=left_state, \\\n", + " right_state=right_state, geometry=(0., 1., 0.5), t=t,\n", + " gamma=gamma, npts=npts, dustFrac=dustFrac)\n", + " # Printing positions\n", + " print('Positions:')\n", + " for desc, vals in positions.items():\n", + " print('{0:10} : {1}'.format(desc, vals))\n", + "\n", + " # Printing p, rho and u for regions\n", + " print('Regions:')\n", + " for region, vals in sorted(regions.items()):\n", + " print('{0:10} : {1}'.format(region, vals))\n", + "\n", + "\n", + " # Finally, let's plot the solutions\n", + " f, axarr = plt.subplots(4, sharex=True,figsize=(9, 9))\n", + " #f.figure(figsize=(20, 6), dpi=500)\n", + "\n", + " markEveryNumber=20\n", + "\n", + " axarr[0].plot(values['x'], values['p'], linewidth=1.5, color='k')\n", + " axarr[0].plot(xLBM,rhoLBM*temperatureLBM,'.',label='P',color='r',markevery=markEveryNumber)\n", + " axarr[0].set_ylabel('Pressure')\n", + "\n", + " axarr[1].plot(values['x'], values['rho'], linewidth=1.5, color='k')\n", + " axarr[1].plot(xLBM,rhoLBM,'.',label='rho',color='r',markevery=markEveryNumber)\n", + " axarr[1].set_ylabel('Density')\n", + "\n", + " axarr[2].plot(values['x'], values['u'], linewidth=1.5, color='k')\n", + " axarr[2].plot(xLBM,velocityLBM,'.',label='ux',color='r',markevery=markEveryNumber)\n", + " axarr[2].set_ylabel('Velocity')\n", + "\n", + " axarr[3].plot(values['x'], values['p']/values['rho'], linewidth=1.5, color='k')\n", + " axarr[3].plot(xLBM,temperatureLBM,'.',label='T',color='r',markevery=markEveryNumber)\n", + " axarr[3].set_ylabel('Temperature')\n", + "\n", + " plt.xlabel(\"x\")\n", + " #plt.legend(loc='best')\n", + "\n", + " #plt.suptitle('Shocktube results at t={0}\\ndust fraction = {1}, gamma={2}'\\\n", + " # .format(t, dustFrac, gamma))\n", + " plt.suptitle('Shocktube results at t='+str(t)+r', $\\gamma$'+'='+str(gamma))\n", + " plt.show()\n", + "\n", + "sodAnalytical(maxTime)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dbacb786-c960-4193-b2ed-07c36f0bb0c5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45a288d8-0528-41db-b237-4f4652d78d00", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7dc2f2df-3705-4fd1-9ee6-507c8d0fdfde", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe8ffe49-0fc0-4645-9bfe-ba0f70dc8e37", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/thermaldiffusivity_test/thermaldiffusivity_tester.ipynb b/Tools/thermaldiffusivity_test/thermaldiffusivity_tester.ipynb new file mode 100644 index 0000000..348122d --- /dev/null +++ b/Tools/thermaldiffusivity_test/thermaldiffusivity_tester.ipynb @@ -0,0 +1,246 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "1a0d1aad-76b1-4de1-ba9f-660bc5e0bc78", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np,matplotlib.pyplot as plt,scipy as sp" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "33f6c4d3-c699-4550-80c4-814253739e43", + "metadata": {}, + "outputs": [], + "source": [ + "#This cell needs user input\n", + "#set ic_thermalDiffusivityTest.initialTemperature=lbm.initialTemperature to a value <= 0.03333\n", + "#set lbm.nu and lbm.alpha to a value <= 0.0100 to set the desired Prandtl number = nu/alpha\n", + "#set ic_thermalDiffusivityTest.meanMolecularMass = lbm.meanMolecularMass = 17.031 [kg/kmol] (e.g. molecular weight of ammonia, 28.96 for air)\n", + "#set ic_thermalDiffusivityTest.adiabaticExponent = lbm.adiabaticExponent = 1.32 (e.g. adiabatic exponent of ammonia, 1.4 for air)\n", + "#Please refer to the plot at the end of the notebook for a reasoanble range to play with\n", + "#Run the marbles code\n", + "\n", + "#Enter the maximum temperature in the domain at each time step in a list called \"temperatureMaxList\"\n", + "\n", + "meanInitialTemperature=0.003333 #T_0\n", + "\n", + "#nu=0.00000876\n", + "#alpha=0.000010\n", + "temperatureMaxList=[0.0033330111089260287,0.003333011108338176,0.003333011107781597,0.0033330111072346004,0.0033330111066846944,0.003333011106120858,0.0033330111055466377,0.0033330111049846086,0.0033330111044451555,0.0033330111039127325,0.00333301110337527]\n", + "\n", + "#nu=0.0000876\n", + "#alpha=0.00010\n", + "#temperatureMaxList=[0.0033330111089260287,0.0033330111033038714,0.0033330110978033434,0.0033330110924156917,0.0033330110870387793,0.0033330110815657367,0.0033330110759895912,0.003333011070392199,0.0033330110648796627,0.003333011059492473,0.003333011054139599]\n", + "\n", + "#nu=0.000876\n", + "#alpha=0.0010\n", + "#temperatureMaxList=[0.0033330111089260287,0.0033330110527316566,0.0033330109977224424,0.003333010943989307,0.0033330108907816953, 0.0033330108371347118,0.0033330107827006144,0.0033330107280385014,0.0033330106741257482,0.0033330106215165604,0.003333010569870143]\n", + "\n", + "#nu=0.00876\n", + "#alpha=0.010\n", + "#temperatureMaxList=[0.0033330111089260287,0.0033330105519450933,0.0033330100276789763,0.003333009536056499,0.003333009072522581,0.003333008630668897,0.0033330082055979177,0.0033330077960986204,0.003333007404394945,0.003333007033836297,0.003333006686130709]\n", + "\n", + "#meanInitialTemperature=0.03333\n", + "\n", + "#nu=0.0071\n", + "#alpha=0.010\n", + "#temperatureMaxList=[0.03340215329014551,0.03339851356944971,0.0333951476904181,0.03339188963009732,0.03338874961475574,0.0333858520511657,0.03338308525571377,0.03338038707464298,0.03337788233695801,0.0333755290937577,0.0333732222571624] \n", + "\n", + "#nu=0.00071\n", + "#alpha=0.0010\n", + "#temperatureMaxList=[0.03340215329014551,0.03340179248093723,0.03340144310994365,0.03340108129426548,0.03340073396884571,0.03340038325337785,0.033400029435033916,0.033399689770114024,0.033399337832998297,0.03339899646682287,0.033398657317939374] \n", + "\n", + "#nu=0.000071\n", + "#alpha=0.00010\n", + "#temperatureMaxList=[0.03340215329014551,0.03340211693829567,0.03340208164841688,0.03340204518170678,0.033402010440168814,0.03340197416190645,0.033401938698434726,0.03340190352715983,0.033401867134232564,0.03340183247380818,0.033401796309968014] \n", + "\n", + "#nu=0.0000071\n", + "#alpha=0.000010\n", + "#temperatureMaxList=[0.03340215329014551,0.03340214928783017,0.03340214552387792,0.033402141875260756,0.03340213863515059,0.03340213461244372,0.033402131449524766,0.03340212768242821,0.03340212403454414,0.03340212079532666,0.033402116773623786] \n", + " \n", + "#nu=0.000010\n", + "#alpha=0.000010\n", + "#temperatureMaxList=[0.03340874201013944,0.03340873717067321,0.033408733547318936,0.033408729930235956,0.03340872619828263,0.033408722282763176,0.033408718193215704,0.03340871401269121,0.03340870986614099,0.03340870586786155,0.03340870206676039]\n", + "\n", + "#nu=0.00010\n", + "#alpha=0.00010\n", + "#temperatureMaxList=[0.03340874201013944,0.033408702517069545,0.033408664080927346,0.03340862539812661,0.03340858637224108,0.03340854706797808,0.033408507677263936,0.03340846843598876,0.033408429525490474,0.03340839099314283,0.03340835272588857]\n", + "\n", + "#nu=0.0010\n", + "#alpha=0.0010\n", + "#temperatureMaxList=[0.03340874201013944,0.033408356815923565,0.033407972788316816,0.03340758769829346,0.03340720172925465,0.03340681627400937,0.03340643330379178,0.03340605451267123,0.033405680580878075,0.03340531086409777,0.03340494366894785]\n", + "\n", + "#nu=0.010\n", + "#alpha=0.010\n", + "#temperatureMaxList=[0.03340874201013944,0.03340498275468927,0.033401386210898464,0.03339793634852444,0.03339463084356549,0.03339147646793545,0.03338848203037338,0.03338565127375332,0.033382978639401754,0.03338044951061152,0.03337804449187678]\n", + "\n", + "samplingInterval=5000 #The interval between consecutive readings. \"max_step\" value in the marbles input file\n", + "\n", + "nY=200.0 #wavelength on the sine wave. \"ic_viscosityTest.waveLength\" in the marbles input file" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "37248e4c-4730-453e-9fd3-d78531254fa7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n", + "alpha recovered is 1.0202174236998391e-05\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmEAAAHACAYAAADqXb+dAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABavElEQVR4nO3de1xUZf4H8M8MlwERJxFhuClWhhleABXFELVQVHJdc71GVqZZYVFWm5bh1qaumq67WJqZXTd+ltjaliiUGiYqt0kEpTSNiyBeYAAFBmae3x/o5CgiIwxnBj7v1+u8bJ7znDnfObWezz7nnOfIhBACRERERNSm5FIXQERERNQRMYQRERERSYAhjIiIiEgCDGFEREREEmAIIyIiIpIAQxgRERGRBBjCiIiIiCTAEEZEREQkAYYwIiIiIgkwhBERERFJgCGsnXn//fcxcuRIdOnSBTKZDOXl5VKXRERERI1gCLNCI0eOxEcffdTousuXLyMiIgKLFy9u26KIiIjIJLZSF0CtKyYmBgCwd+9eSesgIiKipnEkjIiIiEgCDGFEREREEmAIswLLli1D586dDUtKSgrmz59/QxsRERFZD94TZgXmz5+PqVOnGj7PmjULDz/8MCZPnmxo8/LykqI0IiIiuk0MYVbAxcUFLi4uhs+Ojo5wc3PD3XffLWFVRERE1BIMYe1MSUkJSkpKcOLECQBAdnY2nJ2d0aNHD6MgR0RERNLiPWHtzIYNGxAQEIC5c+cCAEaMGIGAgADs2LFD4sqIiIjoWjIhhJC6CCIiIqKOhiNhRERERBJgCCMiIiKSAG/Mt1B6vR5nzpyBs7MzZDKZ1OUQERFRMwghUFlZCU9PT8jlTY91MYRZqDNnzsDHx0fqMoiIiOg2FBQUwNvbu8k+DGEWytnZGUDDv8QuXbpIXA0RERE1R0VFBXx8fAzn8aYwhFmoq5cgu3TpwhBGRERkZZpzKxFvzCciIiKSAEMYERERkQQYwoiIiIgkwBBGREREJAGGMCIiIiIJMIQRERERSYAhjIiIiEgCDGFEREREEmAIIyIiIpKAVYewd999F7169YKDgwOCgoKQkpLSZP99+/YhKCgIDg4OuPPOO7Fhw4Yb+mzbtg19+/aFQqFA3759sX37dpP3K4TA0qVL4enpCUdHR4wcORI5OTkt+7GtRacD9u4Fvvii4U+dTuqKiIiIOiSrDWH/93//h5iYGLz22mvIyspCaGgoxo0bh/z8/Eb7nzp1CuPHj0doaCiysrKwePFiPPfcc9i2bZuhT2pqKqZNm4aoqCj8/PPPiIqKwtSpU3Ho0CGT9rty5UqsWbMGcXFxSEtLg0qlQnh4OCorK813QJojIQHw9UXyqFHoO3MmkkeNAnx9G9qJiIiobQkrNWTIEDF//nyjtj59+ohXX3210f6vvPKK6NOnj1HbU089JYYOHWr4PHXqVBEREWHUZ+zYsWL69OnN3q9erxcqlUqsWLHCsL6mpkYolUqxYcOGZv8+jUYjAAiNRtPsbZq0bZsQMpnQA2IwIHDlTz0ghEzWsJ6IiIhaxJTzt1WOhGm1WmRkZGDMmDFG7WPGjMGBAwca3SY1NfWG/mPHjkV6ejrq6uqa7HP1O5uz31OnTqGkpMSoj0KhQFhY2E1rMzudDnj+eUAI7AaQdqU5DcDuq31iYnhpkoiIqA1ZZQg7f/48dDod3N3djdrd3d1RUlLS6DYlJSWN9q+vr8f58+eb7HP1O5uz36t/mlIbANTW1qKiosJoaTUpKUBhIQSAJfjjX7rNlc9CCKCgoKEfERERtQmrDGFXyWQyo89CiBvabtX/+vbmfGdr9bnW8uXLoVQqDYuPj89N+5qsuBgADKNg+ivNOlw3GnalHxEREZmfVYYwV1dX2NjY3DCyVFpaesMI1FUqlarR/ra2tujWrVuTfa5+Z3P2q1KpAMCk2gBg0aJF0Gg0hqWgoOCmfU3m4WEYBbNpZPUcNAQyeHi03j6JiIioSVYZwuzt7REUFISkpCSj9qSkJISEhDS6zbBhw27ov3v3bgwaNAh2dnZN9rn6nc3Zb69evaBSqYz6aLVa7Nu376a1AQ33jXXp0sVoaTWhodjt6oo0XAlb1ykCEGxnh1I/v9bbJxERETXNrI8ImFF8fLyws7MTmzdvFrm5uSImJkY4OTmJ06dPCyGEePXVV0VUVJSh/2+//SY6deokXnjhBZGbmys2b94s7OzsxFdffWXo89NPPwkbGxuxYsUKcezYMbFixQpha2srDh482Oz9CiHEihUrhFKpFAkJCSI7O1vMmDFDeHh4iIqKimb/vtZ8OlKv14vBd90l5FeeirzZolKpxN69e1u8PyIioo7KlPO31YYwIYRYv3696Nmzp7C3txeBgYFi3759hnWzZ88WYWFhRv337t0rAgIChL29vfD19RXvvffeDd/55ZdfCj8/P2FnZyf69OkjtjUydUNT+xWiIfTExsYKlUolFAqFGDFihMjOzjbpt7VmCKupqRHu7u5NBjAbGxsBQMjlcvG3v/1N1NfXt3i/REREHY0p52+ZEFfuTieLUlFRAaVSCY1G0yqXJgsKCnDu3LmGaSiysoDz5wFXVyAgALCxQefOnbF8+XJ89NFHAIAHHngAn332meEeNyIiIro1U87fDGEWqrVDWHN98sknePrpp3H58mW4u7vj888/xwMPPNBm+yciIrJmppy/rfLGfDKfRx99FOnp6fD398fZs2cbfXcmERERtZyt1AWQ5bn33ntx+PBhrF69Gi+//LLU5RAREbVLHAmjRjk6OmLJkiVwcHAAAOh0OkydOhW7du2SuDIiIqL2gSGMmmXDhg348ssvMXXqVFy8eFHqcoiIiKweL0dSs8yZMwe5ubkYPnw4XFxcpC6HiIjI6jGEUbM4ODhg/fr1Rm379u1DVVUVJkyYIFFVRERE1ouXI+m2nDt3DjNmzEBkZCRefvll1NXVSV0SERGRVWEIo9vSpUsXTJ06FQCwevVqjBgxAr///rvEVREREVkPhjC6LQqFAv/85z+xfft23HHHHTh48CAGDhyI//73v1KXRkREZBUYwqhFJk2ahKysLAQHB6O8vByTJk1CTEwMtFqt1KURERFZNIYwajFfX1/8+OOPWLhwIQBg3bp1GD58OH777TeJKyMiIrJcDGHUKuzt7bF69Wp88803cHFxQXp6OgICAvDVV19JXRoREZFFYgijVhUZGQm1Wo3hw4ejoqICf/nLX/Dss8+ipqZG6tKIiIgsCkMYtTofHx/s2bMHr776KgDg3XffxdatWyWuioiIyLJwslYyCzs7OyxfvhxhYWHYtm0boqKipC6JiIjIonAkjMwqIiICmzZtgkwmAwBUVFTg9ddfR3V1tcSVERERSYshjNrUM888g7fffht/+ctfpC6FiIhIUgxh1KYee+wxeHl5YfHixVKXQkREJCmGMGpTDz74IE6ePImQkBBD248//ohLly5JWBUREVHbYwijNqdQKAz/fPToUURERGDIkCHIycmRsCoiIqK2xRBGkqqoqMAdd9yB3NxcDB48GB9++CGEEFKXRUREZHYMYSSpkJAQqNVqjBkzBtXV1ZgzZw6i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JrISkt2YX1paahghCw0NxUsvvdRaX93hMIQRdVx1dXV47bXXsGrVKgBAYGAg/u///g933323xJUR0a20SQirq6tDSUkJLl++jO7du8PFxeW2iqXGMYQR0bfffovZs2fjwoULcHZ2xqZNmzBt2jSpyyKiJpjt6ciqqips3LgRI0eOhFKphK+vL+699150794dPXv2xNy5c5GWlnbrLyIioluaMGEC1Go17r//flRWVmL69OmYP38+qqurpS6NiFpBs0PY2rVr4evri02bNmH06NFISEiAWq3GL7/8gtTUVMTGxqK+vh7h4eGIiIjAr7/+as66iYg6BG9vb+zZswevvfYaZDIZNm7ciLCwMOh0ultvTEQWrdmXI//yl7/gjTfeQL9+/ZrsV1tbi82bN8Pe3h5PPvlkqxTZEfFyJBFdLykpCY888ggWL16M559/XupyiKgRnDG/HWAII6LGnD9/Ht26dYNMJgMAnDx5Eh4eHujUqZPElRERYMZ7woiISFqurq6GAFZZWYmIiAgMGTIEJ0+elLgyIjKVbUu/oLy8HLt27UJRURFkMhk8PDwwduxYdO3atTXqIyKim/jtt99QVVWF2tpa/p1LZIVaNBK2efNmDBkyBAcPHoRer4dOp8PBgwcxdOhQbN68ubVqJCKiRgwYMABqtRo7duwwTBMkhEBNTY3ElRFRc7TonjA/Pz9kZGSgc+fORu2VlZUICgrCL7/80uICOyreE0ZEt+PDDz/EqlWrsHXr1ls+SEVEra/N7gmTyWSoqqq6ob2qqspwzwIREbWNuro6rFixAsePH8eQIUOwadMm8NkrIsvVonvCVq9ejbCwMPj7+xveE1lYWIicnBy88847rVIgERE1j52dHX766SfMnj0bO3fuxLx587Bnzx5s3LgRzs7OUpdHRNcx6XLkrl27EB4eDrn8jwE0nU6Hw4cP48yZMxBCwMvLC0OGDIGNjY1ZCu4oeDmSiG6XXq/H6tWrsXjxYuh0Otx9993YunUrAgICpC6NqN0z2zxhNjY2KC4uhpubW4uLpKYxhBFRSx04cADTp09HQUEB7O3tsXbtWjz99NO8XYTIjMx2TxjvLSAish4hISFQq9WYOHEitFotnn32WUydOhUajUbq0ogInKyViKhdc3Fxwddff401a9bAzs4OX331FQICApCWliZ1aUQdnskhLC4uDrt2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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Execute this cell as is. Prints the recovered thermal diffusivity. Visually check the curve fit \n", + "\n", + "# viscosity test\n", + "from scipy.optimize import curve_fit\n", + "\n", + "temperatureMaxArray=np.asarray(temperatureMaxList)-meanInitialTemperature\n", + "temperatureMaxArray[:]=temperatureMaxArray[:]/temperatureMaxArray[0]\n", + "tArray=np.arange(len(temperatureMaxList))[:]*samplingInterval\n", + "\n", + "print(type(temperatureMaxArray),type(tArray))\n", + "\n", + "def fit(t_,a_):\n", + " return np.exp(-a_*t_)\n", + "\n", + "popt,pcov=curve_fit(fit,tArray,temperatureMaxArray,p0=0.00000010)\n", + "\n", + "plt.plot(tArray,temperatureMaxArray,'ro')\n", + "plt.plot(tArray,fit(tArray,popt[0]),'k-.^')\n", + "alphaRecovered=popt[0]/pow((2.0*np.pi/nY),2)\n", + "plt.ylabel(r'$(T-T_0)/(T_{in}-T_0)$')\n", + "plt.xlabel('time')\n", + "print('alpha recovered is',alphaRecovered)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "997c9627-391e-41e7-a11a-eedfa2da5080", + "metadata": {}, + "outputs": [], + "source": [ + "#Some readings taken at various temperatures\n", + "\n", + "#Prandtl 1, gamma=5.0/3.0\n", + "alphaInputPr1=[0.000010,0.00010,0.0010,0.010]\n", + "alphaRevoveredPr1=[1.0300319369885965e-05,0.00010056444942059138,0.0010031605945491945,0.010024704606597004]\n", + "\n", + "#Prandtl 0.71, gamma=1.4\n", + "alphaInputPr0p71=[0.000010,0.00010,0.0010,0.010]\n", + "alphaRevoveredPr0p71=[1.0271302677162716e-05,0.00010052321584375431,0.001007166936195215,0.01038101554946801]\n", + "\n", + "#Prandtl 0.876, gamma=1.32\n", + "alphaInputPr0p876=[0.010,0.0010,0.00010,0.000010]\n", + "alphaRevoveredPr0p876=[0.010271861539354417,0.0010089582673687711,0.00010036837884700615,1.0202174236998391e-05]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ceb71352-26d6-4a77-9e16-2a1f57dcc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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O3fu4OHDh5LY1atXoVAo4OHhUWIZX3/9NYYMGYLt27cjMzMT//vf/7Bjxw68//77aNWqFd566y2No2a6qEi/5ufn46uvvsJnn31WYj7eSy+9hL1792LmzJkVap+uWrduDXNzc5w9e1b9j6i8vDxcvHhR7+s+paam4tq1a9i6dSv69esHADqNSNZERldEERmjglEoExMTjT+cJiYmWLJkCYYMGaLXhNOydOnSBQqFAgEBARg/fjz8/Pzg6uqKa9eu4c6dO3B1dcWtW7fg5OQEU9PCP+lbt26hffv2OHfuHABg+fLl2LBhAzZu3AhTU1OkpqZi/vz5eP3119GhQwekpaWhTp06MDU1RVpaGszNzTF58mQAgKWlJfz8/GBjYwMLC4sy/yERHByMhQsX4s8//9T4esGkck9PT42vR0VFwcTERDLKpom+h7S0mRKwadMmBAcH4+TJkwBU/7r++OOP4eLigg4dOiAiIgJr167FG2+8IVm2UqnEzp074evrK+kLbbVt2xZ3797FwYMHER0dXWqevtte3nQJoOS2L1q0CMOHD4ezszOePHmCffv24dSpU/j555/Vy5kxYwa++eYb/N///R/q1q2rHumztbUt9dBxgYL+LnrYKDIyEvXr15cczo2KikLLli01nk6/aNEiyefdqVMnLFiwwGCfSXn9WvwzK+7HH3/Eo0ePMGXKlBJ/O+PGjcP27durvIiysbHB22+/jXnz5qm3NSAgAFlZWRoPIWujQYMGaNiwIYKCguDg4ICEhASt+6GmMrrDeUTGKDc3FwkJCaUOYyuVSty9e7dShqxbt26NFStWYMOGDejatSscHBwQEhICZ2dn9VyK6OhodOjQQfK+6OhouLm5qZ937NgRf//9NwCgbt26uHLlCjw8PDBu3Dj8+OOPkmVER0dLDl1fuXJFfWjlypUrZc5tSEtLK/NCiwVnAdWvX1/j61FRUWjXrl2F56+URpspASkpKbh586b6+caNGzFu3Di88847aN++PebOnYu33nqrxEUGT5w4gYSEhBLFVYHyzlwsGEmcOXOmxlG6iipvugRQctv//vtvTJo0CW5ubvjXv/6F8+fP4+eff8bgwYPVOVu2bEFaWhoGDBgABwcH9WP//v3qnNK2vaC/ixZbERERJUacoqKiNB7KA6BXwVpAm8+kvH4t/pkVt337dgwaNEjjPz5eeuklREZG4tKlS3pvg74++eQTvPTSS5g0aRK6deuGGzdu4NixY2jQoIFeyzMxMcG+ffsQHh6Ojh074t1335XM5ayNZKKyJnLUMoGBgQgMDIRCoUBcXBzS0tJ44c0aJjs7G/Hx8eorVevq7t27ePDgQamvN27cWKd5IIb08ccfAwAWL14siclkMixatAj5+fl45ZVXMGjQILz11luSw3Zvvvkmhg4dipSUFDx8+BALFy7E1q1bkZKSgsWLF0MIgVatWuHWrVsAgKVLl6JVq1YaJ1RT2ZYtW4ZTp07h1KlTGl9/+PAhGjZsiKioqBITemu68radyBDK2s8XTMcx5O83D+dpiXOiyNnZ2WjvnXj16lWEhIRg27ZtAICePXvCxMQEZ8+exYEDByCTyTBy5Ej1PKaVK1fi/PnzsLa2Rr9+/TBmzBjMmTNHPbpw9epV9SjX7du3JYdVoqOjMXr06Crdvtri2LFjGidkF4iKioK5uTnat29fha2qGuVtO1FNxJEoHVVGJUtVo6IjUUSVbf369di9ezciIiKquylENVJVj0RxThQRkZGYM2cOCyiiGoRFFBEREZEeWERpiRfbJCIioqJYRGlpxowZiImJ0XixRSIiInr2sIgiIiIi0gOLKCIiIiI9sIgiIiIi0gOLKCIiIiI9sIjSEs/OIyIioqJYRGmJZ+cRERFRUSyiiIiIiPTAIoqIiIzKqlWrUKdOHfVj1apV1d2kKjFgwADMmTOnuptBOmARRaSlhIQEXLp0qdRHQkJCdTexRnnuuecgk8kgk8lgZmYGNzc3fPPNN1Wy7s2bN6tvUOrp6YkzZ86Umtu8eXN1O4s+ZsyYoc759ddfMWrUKDg6OkImk+HIkSNVsBW6qWgbV69eDZlMpvFHXpfPUxvTp09HZGSk+jF9+vQKLa80q1evhre3N+rWrYvGjRtj9OjRiI2NleTk5+fjgw8+QIsWLWBlZYWWLVtixYoVUCqVOq/v999/h1wux7BhwzS+fvjwYaxcuVKvbaFqIkgnaWlpAoBIS0ur7qaQjp4+fSpiYmLE06dPdX7vnTt3hKWlpQBQ6sPS0lLcuXOnElpe+yiVSlG3bl2xevVqkZSUJG7duiXeeOMNYWpqKm7duqXxPXl5eQZZ9759+4SZmZnYtm2biImJEX5+fsLGxqbUvktOThZJSUnqx/HjxwUAERoaqs45evSoWLx4sTh06JAAIIKDgw3SVkOqSBsvXLggmjdvLjp37iz8/Pwkr+n6eRqToUOHip07d4ro6GgRGRkpRo4cKVxcXERGRoY656OPPhINGzYUP/74o4iPjxcHDhwQderUEevXr9d5fVOmTKnQ55OTk6Pze541Ze3nK+P3m0WUjlhE1VwVKaLCw8PLLKAKHuHh4ZXQcpXz58+L/v37C0tLS+Hm5iYuXLggtm7dKkaNGlVp66wssbGxAoA4c+aMOnbjxg0BQBw5ckTEx8cLAOLAgQOiX79+wtzcXHz33XcGWXf37t3F9OnTJbF27dqJBQsWaPV+Pz8/0apVK6FUKjW+rk8R1aZNG9GzZ0+RlZWljimVStGjRw8xb948nZalDV3a+OTJE9GmTRtx/Phx0b9//xJFVEU/z4K+PnTokOjXr5+wtLQU3bp1E/Hx8SI0NFR4e3sLKysrMWDAAJGamqrVMosrra+KS05OFgDE6dOn1bGRI0eKN954Q5I3duxY8eqrr+rUhoyMDFG3bl3x559/igkTJojly5eXyCn++fbv31/MmDFDvPvuu6Jhw4biueee02mdz6KqLqJ4OE9LvMQBVadz586hf//+GDZsGC5fvgx3d3csW7YMa9aswfLly6u7eRK7du2CTCYrMyc8PBwymQydO3dWxxITEwEATZo0QWRkJADg008/xZIlS3D16lUMGTJEsozi82Y0PYofVsrNzUV4eHiJZQ0ZMgS///57uduWm5uLPXv24I033ih3G3Wxf/9+RERE4LffflPH9u7di/j4eHzwwQeSXH22uyJmzJiBkSNHYtCgQSVeq+jnCUDd15s3b8aqVavwxx9/IDU1FZMmTcKnn36KwMBAnDp1CleuXMH27dtLvP/JkydYvHgxPD094ebmhmnTpuGXX35BZmYmYmJiMG3aNMTExGjVlrS0NACAnZ2dOta3b1+cPHkScXFxAICoqCicPXsWI0aM0GqZBfbv3w83Nze4ubnh1Vdfxc6dOyGEKPd9u3fvhqmpKX777Tds3bpVp3VS5TOt7gbUFDNmzMCMGTOQnp4OW1vb6m4OPWP8/f3x0ksvYcGCBQCAl19+Ga+88gp8fHzQtWtXAMBnn32G9PR0SVH12WefYd26dbC3t0daWhpefPFFbNiwodT1nDhxAleuXMG7776rd1ttbW3h5uZWZs6lS5fQokUL1KtXDwAQGxuLuXPnokuXLujevTtWrlwJGxsbHDhwAM2bN9e4jOnTp+Pf//53metp1qyZ5HlKSgoUCgWaNGkiiTdp0gT3798vZ8uAI0eO4PHjx5g8eXK5ubro2rUrPDw88Oeff2LQoEHIysrCwoULsXLlSvVnVECf7dbXvn37cOnSpVIv7VLRzxNQFSUNGjTAvn37YG9vDwAYOHAgfvnlF8TExMDGxgYA4O3trXGZn3zyCR48eIA1a9YgKysLP/74I8aPH4+HDx+iXr16mDZtGlq1alVuO4QQ8Pf3R9++fdGxY0d1fP78+UhLS0O7du0gl8uhUCjw8ccf45VXXtFq+wps374dr776KgBg2LBhyMjIwMmTJzUWp0W1bt0aAQEBOq2Lqg6LKCIjl5iYiD/++ANr1qxRx8zNzSGEkBRM0dHRGD58uOS90dHRCAwMhI+PDzIzM2Fvb49PPvkEVlZWGtc1aNCgcnfq5RkzZgzGjBlTZk54eDhu376NOnXqID8/HzKZDBMmTMCnn34KExMTREZG4sUXXyy1gAJUowVFRwx0UXwUSQih1cjS9u3bMXz4cDg6Ouq13rK0bdtWPak5ICAAdnZ2mDJlSom8imy3Lu7evQs/Pz+EhITA0tKyzFx9P08A6r4uKKAA1Ukcr7zyirqAKoiNHDmyxPvnzZuH+vXrIzExEUqlEi+88AI2b96MlJQUNGrUCDk5OcjLyyt3G2bOnInLly/j7Nmzkvj+/fuxZ88efPPNN+jQoQMiIyMxZ84cODo6wtfXV6ttjI2NxYULF3D48GEAgKmpKSZMmIAdO3aU+/fm5eWl1TqoevBwHpGRu3btGgDpzjQ2Nhbdu3dHp06d1LHo6GjJv6ALYl26dAEAREREoF27duoCauvWrejWrRs6duyIiRMnAgCGDx+uXt/w4cPh7++Pnj17ol27dggLC8OLL74IV1dXBAUFVWibIiIiMG/ePERGRuLWrVvIysrCrl271CMaUVFRGDBgQJnL0Oewlr29PeRyeYkRjeTk5BKjKcXduXMHJ06cwNSpU3XfYC24ubkhNjYWiYmJWLNmDdatWwe5XF4ir6oO54WHhyM5ORmenp4wNTWFqakpTp8+jc8//xympqZQKBQV+jwLREVFoWfPnpJYZGQkevTooX6enZ2NuLg49Xe5qEePHmHgwIFwdnaGq6srOnXqhM2bN+PBgwc4duwYevXqhTt37pTZhlmzZuH7779HaGgonJycJK/NmzcPCxYswMsvv4xOnTph0qRJePfdd7F69Wqttg9QFd/5+flo1qyZ+rPcsmULDh8+jEePHpX53qKFJBkfjkQRGbm0tDTJj+nDhw8REBAgKZiEELh58ybatm0ricXFxcHHxwdZWVlIS0tTz7l59OgRgoKCEBYWBrlcjsePHwMArl+/jjZt2gBQFWATJkzA2rVr8dprr2H+/Pn44YcfcP36dbz99tt488039dqeW7du4fHjxxg8eDBat25d4vX09HTcvn1bfZiyNPoc1jI3N4enpyeOHz8uGS07fvw4fHx8ylzWzp070bhxY42jIYbQtm1bbNu2DQsWLMDgwYPx/PPPa8yrqsN5//rXv3DlyhVJ7PXXX0e7du0wf/58yOVyyOVyvT9PQHNf37lzBw8fPpTErl69CoVCAQ8PjxLL+PrrrzFkyBBs374dmZmZ+N///ocdO3bg/fffR6tWrfDWW2/B3d1d4/qFEJg1axaCg4Nx6tQptGjRokROVlYWTEyk4w1yuVzrSxzk5+fjq6++wmeffVZi7thLL72EvXv3YubMmVoti4yQwaaoPyN4dl7NVVPPzrt+/boAIFasWCGuXbsmhgwZIrp27SoaNWokbt++LYRQndnWqVMnyftu3LghevTooX6+bNkyMXPmTCGEEOnp6cLV1VW89957Ijo6WgghxOPHj4WHh4f6/1u2bKl+77Rp08SRI0eEEELExMSIoUOHltrew4cPCzc3t1Jf/+6774RMJhOPHj3S+Pqvv/4q5HK5Xv2kjYJT8rdv3y5iYmLEnDlzhI2NjfqzFEKIjRs3iueff179XKFQCBcXFzF//nyNy3zy5ImIiIgQERERAoBYu3atiIiI0Ok09oiICCGTyYSFhYW4fv26/htYCm3aWHy7i9N0dp42n2dpCvq66FmJR44cEfXr15fkbd++XbRq1UrjMipy6Yu3335b2NrailOnTkkuY1G0Pb6+vqJZs2bqSxwcPnxY2Nvbi/fff1+dU9bnFhwcLMzNzcXjx49LvLZo0SLRpUsX9XNNZ+cV/7ypbDw7j8gI2dvblzunwtLSUjKvw1Bat26NFStWYMOGDejatSscHBwQEhICZ2dn9XyK6OhodOjQQfK+6OhoyQTvjh074u+//wYA1K1bF1euXIGHhwfGjRuHH3/8UbKM6OhoyZmoV65cUR9euXLlSonDhkWlpaWVuGBhUZcuXULr1q1Rv359ja9HRUWhXbt25X7e+powYQLWr1+PFStWoEuXLvj1119x9OhRuLq6qnNSUlJw8+ZN9fMTJ04gISEBb7zxhsZlXrx4EV27dlWPnvj7+6Nr165YunSpOqe8sxYLRhFnzpypcYSuorRpY/Ht1oY2n2dp217Q10Xn6EVERJQYcYqKitJ4KA9QzS/S15YtW5CWloYBAwbAwcFB/di/f786Z+PGjRg3bhzeeecdtG/fHnPnzsVbb70luShmWZ/b9u3bMWjQII0nJL300kuIjIzEpUuX9N4Gql4yIbQ4x5LUCs7OS0tLK3HWDBm37OxsxMfHq6+srKuEhASkpKSU+rq9vT1cXFwq0kS9ffzxxwCAxYsXS2IymQyLFi1Cfn4+XnnlFQwaNAhvvfWW5LDdm2++iaFDhyIlJQUPHz7EwoULsXXrVqSkpGDx4sUQQqBVq1a4desWAGDp0qVo1aqV1pNqSWXZsmU4deoUTp06pfH1hw8fomHDhoiKipJc+qE2KG/biQylrP18Zfx+c06UlgIDAxEYGAiFQlHdTaFq4uLiUm1FUnmuXr2KkJAQbNu2DQDQs2dPmJiY4OzZszhw4ABkMhlGjhypnse0cuVKnD9/HtbW1ujXrx/GjBmDOXPmYPDgwerlFYxy3b59W3KWXHR0NEaPHl2l21cbHDt2rMzLS0RFRcHc3Bzt27evwlZVjfK2naim4kiUjjgSVXNVdCSKqDKtX78eu3fvRkRERHU3hajGquqRKM6JIiIyAnPmzGEBRVTDsIgiIiIi0gOLKCIiIiI9sIgiIiIi0gOLKHrm8FwKIqLaqar37yyi6JlRcOuU3Nzcam4JERFVhqysLACAmZlZlayP14miZ4apqSmsra3x4MEDmJmZlbgfFhER1UxCCGRlZSE5ORn169fXePPuylChIiovLw/3799HVlYWGjVqBDs7O0O1i8jgZDIZHBwcEB8fX+5d3YmIqOapX78+mjZtWmXr07mIysjIwN69e/Htt9/iwoULyMnJUb/m5OSEIUOG4M0335Tcd4vIWJibm6NNmzY8pEdEVMuYmZlV2QhUAZ2KqHXr1uHjjz9G8+bN8eKLL2LBggVo1qwZrKys8PDhQ0RHR+PMmTMYPHgwevbsiY0bN6rvz0VkLExMTHjFciIiqjCdbvsyfvx4LF26FJ06dSozLycnB9u3b4e5uTmmTp1a4UYaE972hYiIqOapjN9v3jtPS0VvQBwXF8ciioiIqAYxqnvnjR49GpcvXzZII2qCGTNmICYmBmFhYdXdFCIiIjICehdRI0aMwPjx4zF+/HjExMSo4wkJCXBzczNI44iIiIiMld6XOOjWrRvatGmD4OBgBAcHo3v37rCwsMC1a9fg5ORkyDYSERERGR29i6jXXnsN7u7u+Pbbb2Fubo4///wTa9asQfPmzRESEmLINhIREREZHb0nlltbW+PKlSto1aqVOvbw4UNMnDgRzZo1w/bt2w3WSGPCs/OIiIhqHqOaWN6jRw8cPnxYErOzs8OGDRuwb9++CjeMiIiIyJjpfTjv008/xYABAxAdHY23334bnp6eAICDBw/CxsbGYA0kIiIiMkZ6F1Hdu3fHL7/8gvfeew+9e/eGTCaDXC5Hfn4+Vq5cacg2EhERERmdCt2AuGfPnvjtt99w7949XLt2DWlpaejSpYtknhQRERFRbaRTEZWQkAAXF5cS8WbNmqFZs2Yl4vfu3dMYJyIiIqrpdJpY7u3tjWnTpuHChQul5qSlpWHbtm3o2LFjiYnnRERERLWFTiNR165dw6pVqzBs2DCYmZnBy8sLjo6OsLS0xKNHjxATE4OrV6/Cy8sLa9aswfDhwyur3URERETVSq/rRGVnZ+Po0aM4c+YMbt++jadPn8Le3h5du3bF0KFD0bFjx8poq1HgdaKIiIhqnsr4/db7YpvPKhZRRERENU9l/H5X6Ow8ImOVkJCAlJSUUl+3t7fXeJIEERGRtp65Iuru3buYNGkSkpOTYWpqiiVLlmD8+PHV3SwyoISEBLi5uSE7O7vUHEtLS8TGxrKQompx4sQJzJ49G59//jkGDRpU3c2hSqJQKHDmzBkkJSXBwcEB/fr1g1wur+5mkQHpfduXmsrU1BTr169HTEwMTpw4gXfffReZmZnV3SwyoJSUlDILKEA1r6+skSqiyiKEwKJFi3Dt2jUsWrQInFFROx0+fBjNmzfHwIEDMXHiRAwcOBDNmzfnWeu1zDNXRDk4OKBLly4AgMaNG8POzg4PHz6s3kYR0TMjJCQEYWFhAICwsDCEhIRUc4vI0A4fPoxx48YhMTFREr937x7GjRvHQqoWMboi6tdff8WoUaPg6OgImUyGI0eOlMjZvHkzWrRoAUtLS3h6euLMmTN6revixYtQKpVwdnbW/c2ZmUDRf0Hm5qpiOTkl8zIzAaWyMJaXp4oVHy3RJTcrSxVXKApj+fmq2NOn+uc+faqK5+cXxhQK3XOzsqS52dmqeF6efrlKZeHnU1ROjiqWmyvN1ZYQhcvV1J9Fl1terjZ9b4jviab+NMT3pKA/K/o9Kd6fFf2elNb3Ff2eFO1PXXJ16ftiuSIjA0sWL1Yf0pHL5ViyaBFERgb3EVW9jzBU3xfLVaSnw2/2bI0jjAWxOXPmQFGwbdxHVO0+wtCEnnx9fcXp06f1fXupjh49KhYvXiwOHTokAIjg4GDJ6/v27RNmZmZi27ZtIiYmRvj5+QkbGxtx584ddU63bt1Ehw4dSjzu3bunzklJSRHt27cXv/32W5ntyc7OFmlpaerH3bt3BQCRBgiRnFyY+NFHQgBCTJ0qXYC1tSoeH18YW7dOFZs4UZprb6+KR0cXxoKCVDEfH2muq6sqfuFCYWzPHlVs0CBprru7Kh4aWhgLDlbFeveW5np5qeI//lgYCwlRxTw8pLn9+6vi331XGDt7VhVr3VqaO2KEKr5zZ2EsIkIVc3SU5o4bp4pv2lQYi4tTxWxtpbm+vqp4QIA6FP7TTwJAuY/w8HAhHj1SvR8QIje3cLlz56pic+cWxnJzC3MfPSqMf/ihKvbOO9K2mZqq4omJhbGAAFXM11eaa2urisfFFcY2bVLFxo2T5jo6quIREYWxnTtVsREjpLmtW6viZ88Wxr77ThXr31+a6+GhioeEFMZ+/FEV8/KS5vburYoX/fsMDVXF3N2luYMGqeJ79hTGLlxQxVxdpbk+Pqp4UFBhLDpaFbO3l+ZOnKiKr1tXGIuPV8WsraW5U6eq4h99VBhLTi7sz6L8/FSxRYsKYxkZhbkZGYXxRYtUMT8/6TIKcovtI34u5bv4M/cRVbqPEImJqpipqTT3nXdU8Q8/LIzpuI8I1WLfA0CEhoZyH1GgivYRaWlpqt/vtDRhKHpPLH/y5AmGDBkCZ2dnvP766/D19TXILV6GDx9e5kU6165diylTpmDq1KkAgPXr1+PYsWPYsmULVq9eDQAIDw8vcx05OTkYM2YMFi5ciN69e5eZu3r1aixfvlzHrSAikhJCYAkAuUwGRZFRCjmAJQCGCAFZdTWODCZJ27wkbTPJmFXoOlGpqanYs2cPdu3ahejoaAwaNAhTpkyBj48PzMzMKt44mQzBwcEYPXo0ACA3NxfW1tY4cOAAxowZo87z8/NDZGQkTp8+Xe4yhRCYOHEi3NzcsGzZsnLzc3JykFNkWDU9PR3Ozs5I++sv1GvaFJD9s9vLzVUNGZqaAhYWhQsoGF60sgJM/jl6mpenypfLAUtL/XKzslT/NrK0VL0GqIZCc3JU77Wy0i/36VPV0KiFhWpbANWwana2brkyGWBtXZibna16zdwcKPhu6JKrVBYOF9vYFO0g1baYmanyAVy6eBGe3t4oT3h4OLp17Vo4XGxtXbI/iywXQpSdq03fG+J7oqk/DfE9KejPin5PivdnRb8npfV9Bb8nkv7UJVeXvi+Se+zHHzFs1CiU5uejRzG04B+Q3EfonqtL3+v7PdFiH3Hq558xcMQIlCc0NBQDCvZT3EdUyT6iUq7zaKghrUuXLomZM2cKS0tLYW9vL+bMmSPiig476gGQHs67d++eAFDiENzHH38s2rZtq9Uyz5w5I2QymfDw8FA/Ll++rHWbKmM4kAwrPDxc+8N5RFVAqVQKb29vYWJiovG7aGJiIry9vYVSqazuplIF5efnCycnJyGTyTT2tUwmE87OziI/P7+6m/rMqYzfb4NMLE9KSkJISAhCQkIgl8sxYsQIXL16Fe7u7li3bp0hViEhk0kHvYUQJWKl6du3L5RKJSIjI9WPTp06GbyNVH3s7e1hWfRfWhpYWlrC3t6+ilpEz7rc3FwkJCRAWcpJD0qlEnfv3kVu0UnKVCPJ5XJs2LABQMnfqoLn69ev5/Wiagm950Tl5eXh+++/x86dOxESEoLOnTvj3XffxX/+8x/UrVsXALBv3z68/fbbePfddw3SWHt7e8jlcty/f18ST05ORpMmTQyyjtIEBgYiMDBQdUYFGTUXFxfExsbyiuVkNCwsLBAWFoYHDx6UmtO4cWNYFD18QzXW2LFjcfDgQfj5+Ukuc+Dk5IT169dj7Nix1dg6MiS950TZ29tDqVTilVdewbRp09TXXirq0aNH6NatG+Lj4/VrXLE5UQDQo0cPeHp6YvPmzeqYu7s7fHx81BPLKxPvnUdERNrgFcuNi1HdO8/Pzw/vvfcerItO+ILq0Nrdu3fh4uKCBg0a6FxAZWRk4MaNG+rn8fHxiIyMhJ2dHVxcXODv749JkybBy8sLvXr1QlBQEBISEjB9+nR9N4WIiMjg5HI5BgwYUN3NoEqk90iUXC5HUlISGjduLImnpqaicePGeh/2OnXqFAYOHFgi7uvri127dgFQXWwzICAASUlJ6NixI9atW4fnnntOr/Vpq+jhvLi4OI5EERER1SCVMRKldxFlYmKC+/fvlyii7ty5A3d391p7PzoeziMiIqp5jOJwnr+/PwDVfKWlS5dKDucpFAqcP39e4/woIiIiotpE5yIqIiICgGru05UrV2BecJExAObm5vDw8MDcuXMN10IiIiIiI6RzERUaGgoAeP3117Fhw4Zn5pAWL3FARERERVXoti/PIs6JIiIiqnmqfU6Uv78/Vq5cCRsbG/XcqNKsXbu2Qg0jIiIiMmY6FVERERHIy8tT/39ptL0FCxEREVFNxcN5OuLhPCIiopqnMn6/9b4B8euvv46TJ0/iWanBAgMD4e7uDm9v7+puChERERkBvYuo1NRUjBw5Ek5OTnjvvfcQGRlpwGYZnxkzZiAmJgZhYWHV3RQiIiIyAnoXUd9//z3u37+PDz/8EOHh4fD09IS7uztWrVqF27dvG7CJRERERMbHYHOiEhMT8e2332LHjh24fv068vPzDbFYo8M5UURERDWPUc2JKiovLw8XL17E+fPncfv2bTRp0sQQiyUiIiIyWhUqokJDQzFt2jQ0adIEvr6+qFu3Ln744QfcvXvXUO0jIiIiMko63/algJOTE1JTUzF06FBs3boVo0aNgqWlpSHbZlR42xciIiIqSu85UUFBQRg/fjwaNGhg6DYZNc6JIiIiqnmq/bYvRb355psGaQARERFRTcR75xERERHpgffOIyIiItID752nI86JIiIiqnmM6jpRT58+RVZWlvr5nTt3sH79eoSEhBikYURERETGTO8iysfHB1999RUA4PHjx+jevTs+++wz+Pj4YMuWLQZroLHgDYiJiIioKL2LqEuXLqFfv34AgIMHD6Jp06a4c+cOvvrqK3z++ecGa6Cx4A2IiYiIqCi9i6isrCzUrVsXABASEoKxY8fCxMQEPXv2xJ07dwzWQCIiIiJjpHcR1bp1axw5cgR3797FsWPHMGTIEABAcnIyJ1wTERFRrad3EbV06VLMnTsXzZs3R48ePdCrVy8AqlGprl27GqyBRERERMaoQpc4uH//PpKSkuDh4QETE1U9duHCBdSrVw/t2rUzWCONCS9xQEREVPMY1W1fAKBp06Zo2rSpJNa9e/cKNYiIiIioJtC7iFqxYkWZry9dulTfRRMREREZPb2LqODgYMnzvLw8xMfHw9TUFK1atap1RVRgYCACAwOhUCiquylERERkBAx625f09HRMnjwZY8aMwaRJkwy1WKPCOVFEREQ1j1Hd9kWTevXqYcWKFViyZIkhF0tERERkdAxaRAGqW8CkpaUZerFERERERkXvOVHFb+0ihEBSUhK+/vprDBs2rMINIyIiIjJmehdR69atkzw3MTFBo0aN4Ovri4ULF1a4YURERETGTKci6vLly+jYsSNMTEwQHx9fWW0iIiIiMno6zYnq2rUrUlJSAAAtW7ZEampqpTSKiIiIyNjpVETVr19fPQJ1+/ZtKJXKSmkUERERkbHT6XDeSy+9hP79+8PBwQEymQxeXl6Qy+Uac2/dumWQBhIREREZI52KqKCgIIwdOxY3btzA7NmzMW3aNNStW7ey2kZERERktHSeWD5kyBAMGzYM4eHh8PPzYxFFREREzyS9J5afPn0aubm5ldIoIiIiImPHieVaCgwMhLu7O7y9vau7KURERGQEdLoB8ZtvvomvvvoKDg4OSEhIgJOT0zM3sZw3ICYiIqp5KuP3mxPLiYiIiPSg821fCu6Lx4nlRERE9CzT+955O3fuNGQ7iIiIiGoUnYoof39/rFy5EjY2NvD39y8zd+3atRVqGBEREZEx06mIioiIQF5envr/SyOTySrWKiIiIiIjp9PZecSz84iIiGqiyvj91uk6UURERESkovOcKG1xThQRERHVZjrPiSoqPDwcCoUCbm5uAIC4uDjI5XJ4enoaroVERERERkinIio0NFT9/2vXrkXdunWxe/duNGjQAADw6NEjvP766+jXr59hW0lERERkZPSeWN6sWTOEhISgQ4cOknh0dDSGDBmCv/76yyANNDacWE5ERFTzGNXE8vT0dPz9998l4snJyXjy5EmFGkVERERk7PQuosaMGYPXX38dBw8eRGJiIhITE3Hw4EFMmTIFY8eONWQbiYiIiIyO3rd9+eKLLzB37ly8+uqr6gtwmpqaYsqUKVizZo3BGkhERERkjCp8sc3MzEzcvHkTQgi0bt0aNjY2hmpbpXjy5Amef/555OXlQaFQYPbs2Zg2bZrW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du0KAIiOjpa8VhtvQExERERUlN5FVGhoqCHbQURERFSj6DUnKi8vDwMHDkRcXJyh20NERERUI+hVRJmZmSE6OpqH7YiIiOiZpffZea+99hq2b99uyLYQERER1Rh6z4nKzc3Fl19+iePHj8PLyws2NjaS12vb2XmBgYEIDAyEQqGo7qYQERGREdD7EgcDBw4sfaEyGX755Re9G2XMeIkDIiKimseoLnHAs/OIiIjoWVahe7acOXMGr776Knr37o179+4BAL7++mucPXvWII0jIiIiMlZ6F1GHDh3C0KFDYWVlhUuXLiEnJwcA8OTJE6xatcpgDSQiIiIyRnoXUR999BG++OILbNu2TXLLl969e+PSpUsGaRwRERGRsdK7iIqNjcVzzz1XIl6vXj08fvy4Im0iIiIiMnp6F1EODg64ceNGifjZs2fRsmXLCjWKiIiIyNjpXUS99dZb8PPzw/nz5yGTyfDXX39h7969mDt3Lt555x1DttEoBAYGwt3dHd7e3tXdFCIiIjICel8nCgAWL16MdevWITs7GwBgYWGBuXPnYuXKlQZroLHhdaKIiIhqnsr4/a5QEQUAWVlZiImJgVKphLu7O+rUqWOQhhkrFlFEREQ1j1FdbLOAtbU1vLy8DNEWIiIiohqjQkXUyZMncfLkSSQnJ0OpVEpe27FjR4UaRkRERGTM9C6ili9fjhUrVsDLywsODg6QyWSGbBcRERGRUdO7iPriiy+wa9cuTJo0yZDtISIiIqoR9L7EQW5uLnr37m3IthARERHVGHoXUVOnTsU333xjyLYQERER1Rg6Hc7z9/dX/79SqURQUBBOnDiBzp07S+6fBwBr1641TAuJiIiIjJBORVRERITkeZcuXQAA0dHRkjgnmRMREVFtp1MRFRoaijfeeAMbNmxA3bp1K6tNREREREZP5zlRu3fvxtOnTyujLUREREQ1hs5FVAXvElNj8QbEREREVJTO984zMTHB33//jUaNGlVWm4wa751HRERU8xjNvfPatm1b7uTxhw8f6tUgIiIioppAryJq+fLlsLW1NXRbiIiIiGoMvYqol19+GY0bNzZ0W4iIiIhqDJ0nlvMaUEREREQ8O4+IiIhILzofzlMqlZXRDiIiIqIaRe8bEBMRERE9y1hEEREREemBRRQRERGRHlhEEREREemBRRQRERGRHlhEEREREemB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+bswMzODk5MT5HI59u3bhxdeeKFEH1Hl6tWrV4m+CwkJgZeXF8zMzKqpVVQhek1Hr8X27dsnzMzMxPbt20VMTIyYM2eOsLGxUZ/htWDBAjFp0iR1/pMnT4STk5MYN26cuHr1qjh9+rRo06aNmDp1anVtQq2ha18UePXVV0WPHj2qurm1mq59sXPnTmFqaio2b94sbt68Kc6ePSu8vLxE9+7dq2sTag1d+yI2NlZ8/fXXIi4uTpw/f15MmDBB2NnZifj4+GragtrjyZMnIiIiQkRERAgAYu3atSIiIkLcuXNHCFGyL27duiWsra3Fu+++K2JiYsT27duFmZmZOHjwYHVtQq2ha18IIdT5np6eYuLEiSIiIkJcvXpVp/WyiNIgMDBQuLq6CnNzc9GtWzdx+vRp9Wu+vr6if//+kvxr166JQYMGCSsrK+Hk5CT8/f1FVlZWFbe6dtK1Lx4/fiysrKxEUFBQFbe09tO1Lz7//HPh7u4urKyshIODg/jPf/4jEhMTq7jVtZMufRETEyO6dOkirKysRL169YSPj4/4888/q6HVtU9oaKgAUOLh6+srhND8d3Hq1CnRtWtXYW5uLpo3by62bNlS9Q2vhfTpC035rq6uOq1X9s+CiIiIiEgHPCBOREREpAcWUURERER6YBFFREREpAcWUURERER6YBFFREREpAcWUURERER6YBFFREREpAcWUURERER6YBFFREREpAcWUURERER6YBFFREZnwIABmDNnToVzqlNVty81NRWNGzfG7du3K7yscePGYe3atRVvFFEtxyKKiDB58mTIZDLIZDKYmZmhZcuWmDt3LjIzM6u7aQCMv2AyBqtXr8aoUaPQvHlzdey5556T9Kubmxu++eabcpe1dOlSfPzxx0hPT6/EFhPVfCyiiAgAMGzYMCQlJeHWrVv46KOPsHnzZsydO1djbm5ubhW3joDSP/enT59i+/btmDp1qjomhEBkZCRWr16NpKQkxMXFoW/fvvD19UV8fHyp68jPz0fnzp3RvHlz7N271+DbQFSbsIgiIgCAhYUFmjZtCmdnZ0ycOBH/+c9/cOTIEQCqkaCZM2fC398f9vb2GDx4MADg559/Rt++fVG/fn00bNgQL7zwAm7evKle5oABAzB79my8//77sLOzQ9OmTbFs2TLJejMzM/Haa6+hTp06cHBwwGeffSZ5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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Plotting\n", + "\n", + "plt.axhline(y=0.000010,linestyle='dotted',color='red')\n", + "plt.axhline(y=0.000100,linestyle='dotted',color='red')\n", + "plt.axhline(y=0.001000,linestyle='dotted',color='red')\n", + "plt.axhline(y=0.010000,linestyle='dotted',color='red',label='Input '+r'$\\alpha$')\n", + "\n", + "\n", + "plt.semilogy(np.ones(4)*1.000,alphaRevoveredPr1,label=r'$\\alpha_{LB sim}$ : '+r'$Pr=1.00, \\gamma=1.67, \\bar{m} \\approx 28$'+'. Monoatomic',marker='o',color='k',linestyle='none')\n", + "plt.semilogy(np.ones(4)*0.876,alphaRevoveredPr0p876,label=r'$\\alpha_{LB sim}$ : '+r'$Pr=0.87, \\gamma=1.32, \\bar{m} \\approx 17$'+'. Ammonia',marker='^',color='k',linestyle='none')\n", + "plt.semilogy(np.ones(4)*0.710,alphaRevoveredPr0p71,label=r'$\\alpha_{LB sim}$ : '+r'$Pr=0.71, \\gamma=1.40, \\bar{m} \\approx 28$'+'. Air',marker='s',color='k',linestyle='none')\n", + "\n", + "\n", + "plt.xlabel('Prandtl number '+r'$(Pr)$')\n", + "plt.ylabel('Thermal diffusivity '+r'$(\\alpha)$')\n", + "plt.ylim(5e-6,8e-1)\n", + "plt.xlim(0.6,1.1)\n", + "plt.legend(loc='best')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7dc2f2df-3705-4fd1-9ee6-507c8d0fdfde", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe8ffe49-0fc0-4645-9bfe-ba0f70dc8e37", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/viscosity_test/viscosity_tester.ipynb b/Tools/viscosity_test/viscosity_tester.ipynb new file mode 100644 index 0000000..6dcba98 --- /dev/null +++ b/Tools/viscosity_test/viscosity_tester.ipynb @@ -0,0 +1,198 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "1a0d1aad-76b1-4de1-ba9f-660bc5e0bc78", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np,matplotlib.pyplot as plt,scipy as sp" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "33f6c4d3-c699-4550-80c4-814253739e43", + "metadata": {}, + "outputs": [], + "source": [ + "#This cell needs user input\n", + "#Set ic_viscosityTest.initialTemperature and lbm.initialTemperature to the same test temeprature, e.g. 0.03333\n", + "#Set lbm.nu to the desired viscosity, e.g. 0.0010\n", + "#Please refer to the plot at the end of the notebook for a reasoanble range to play with\n", + "#Run the marbles code\n", + "\n", + "#Enter the maximum velocity in the domain at each time step in a list called \"uxMaxList\"\n", + "\n", + "#nu=0.0001\n", + "#0.00003333\n", + "#uxMaxList=[0.00001000000000006551, 0.00000999511185454698,0.000009990223299412856,0.000009985337138478791,0.000009980453356023808,0.000009975571966461126]\n", + "\n", + "#0.000016665\n", + "#uxMaxList=[0.00005270199237228379,0.000052676907342226576,0.00005265180639660203,0.00005262671741089268,0.00005260164038126802,0.00005257657530033559,0.00005255152216327203]\n", + "\n", + "#0.0000083325\n", + "#uxMaxList=[0.00003726593618835758,0.0000372498650813973,0.000037233771950543785,0.00003721768577238218,0.00003720160654473058,0.00003718553426339558]\n", + "\n", + "#0.0003333\n", + "#uxMaxList=[0.00023569047498783746,0.00023557417377456587,0.0002354579423384744,0.00023534176824824244,0.00023522565148285937,0.00023510959200675718]\n", + "\n", + "#0.003333\n", + "#uxMaxList=[0.0007453187237684844,0.0007449503436417107,0.0007445827558146017,0.0007442153493769334,0.0007438481242158305,0.0007434810802453358]\n", + "\n", + "#0.03333\n", + "#uxMaxList=[0.0023569047498785975,0.0023557223936788965,0.0023545599964885284,0.002353398172856396,0.0023522369225078403,0.0023510762451703225]\n", + "\n", + "#0.3333\n", + "uxMaxList=[0.007453187237685739,0.007448895859827816,0.00744522187857788,0.007441548411450876,0.007437876758520972,0.007434206917180952]\n", + "\n", + "samplingInterval=5000 #The interval between consecutive readings. \"max_step\" value in the marbles input file\n", + "\n", + "nY=200.0 #wavelength on the sine wave. \"ic_viscosityTest.waveLength\" in the marbles input file" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "37248e4c-4730-453e-9fd3-d78531254fa7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n", + "nu recovered is 0.000104556395716762\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Execute this cell as is. Prints the recovered kinematic viscosity. Visually check the curve fit \n", + "\n", + "# viscosity test\n", + "from scipy.optimize import curve_fit\n", + "\n", + "uxMaxArray=np.asarray(uxMaxList)[:]/uxMaxList[0]\n", + "tArray=np.arange(len(uxMaxList))[:]*samplingInterval\n", + "\n", + "print(type(uxMaxArray),type(tArray))\n", + "\n", + "def fit(t_,a_):\n", + " return np.exp(-a_*t_)\n", + "\n", + "popt,pcov=curve_fit(fit,tArray,uxMaxArray,p0=0.00010)\n", + "\n", + "plt.plot(tArray,uxMaxArray,'ro')\n", + "plt.plot(tArray,fit(tArray,popt[0]),'k-.^')\n", + "nuRecovered=popt[0]/pow((2.0*np.pi/nY),2)\n", + "plt.ylabel(r'$u_x/u_{x,max}$')\n", + "plt.xlabel('time')\n", + "print('nu recovered is',nuRecovered)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "997c9627-391e-41e7-a11a-eedfa2da5080", + "metadata": {}, + "outputs": [], + "source": [ + "#Some readings taken at various temperatures\n", + "\n", + "PByRhoWithCorrection0p0001=[0.0000083325,0.000016665,0.00003333,0.0003333,0.003333,0.03333,0.3333]\n", + "nuRecoveredWithCorrection0p0001=[8.752389508818336e-05,9.655888575570699e-05,9.912005978686417e-05,0.00010001058594407982,0.00010006171279929167,0.00010047037490018057,0.000104556395716762]\n", + "\n", + "PByRhoWithCorrection0p001=[0.3333,0.03333,0.003333,0.0003333,0.00016665,0.000083325]\n", + "nuRecoveredWithCorrection0p001=[0.0010247274007715574,0.0010173939291227424,0.0010247274007715574,0.0009908869945360408,0.0009649512404285938,0.0008743684126622247]\n", + "\n", + "PByRhoWithCorrection0p01=[0.3333,0.03333,0.003333,0.0016665,0.00083325]\n", + "nuRecoveredWithCorrection0p01 =[0.010014845734417641,0.010001635237936712,0.009909324681269585,0.009650364044259478,0.008744969541304054]" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "ceb71352-26d6-4a77-9e16-2a1f57dcc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlMAAAG4CAYAAABhKmI0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABcOElEQVR4nO3dfVxTdf8/8NcYDAQFA7xBh2AiKN5g3lDeUGqmYplp9qvsMtT0yrTCyLypJALL0i5vSiq1UrshLcHqKkvNUJG+qSGUiqkpKCCGtyAgd+Pz+2MXG5MB287GNng9H489ivf57Jz3Pmeevfc5n50jE0IIEBEREZFJHKydABEREZE9YzFFREREJAGLKSIiIiIJWEwRERERScBiioiIiEgCFlNEREREErCYIiIiIpKAxRQRERGRBI7WTsDeVFdX48KFC2jTpg1kMpm10yEiIiIDCCFw48YNdOrUCQ4O5h1LYjFloPj4eMTHx6OiogJnzpyxdjpERERkgpycHCiVSrOuU8bbyRinsLAQbdu2RU5ODtzd3a2dDhERERmgqKgIvr6+uH79Ojw8PMy6bo5MGanm1J67uzuLKSIiIjtjiSk6nIBOREREJAGLKSIiIiIJeJqPqBlSqVSorKy0dhpERE3GyckJcrncKttmMUXUjAghcPHiRVy/ft3aqRARNbm2bduiY8eOTX7pIhZTRM1ITSHVvn17uLq68lpoRNQiCCFQWlqKgoICAICPj0+Tbp/FFFEzoVKpNIWUl5eXtdMhImpSrVq1AgAUFBSgffv2TXrKjxPQiZqJmjlSrq6uVs6EiMg6ao5/TT1nlMUUUTPDU3tE1FJZ6/jHYoqIiIhIAhZTRERERBKwmCIiIiKSgMUUERERkQQspojIJkybNg0PPfRQk293+PDhmDdvXpNvl4iaDxZTRERERBKwmCJqCUpK1A8htLGKCnWsvFx/2+pqbayyUh0rKzOsrRkMHz4czz//PBYsWABPT0907NgRMTExOsufffZZPPvss2jbti28vLzw6quvQtR6jf7+/li9erXOevv166dZz7Rp07Bv3z6sWbMGMpkMMpkM2dnZevMJDw9HRESE5u9ffvkFXl5eqKqqMsvrJSL7xWKKqCVo3Vr9uHxZG1uxQh179lndtu3bq+Pnz2tj8fHq2FNP6bb191fHT5zQxjZtMlvamzdvhpubGw4ePIjly5cjNjYWu3fv1lnu6OiIgwcP4t1338WqVavw0UcfGbz+NWvWYPDgwZg1axby8/ORn58PX19fvW07d+6MvLw8zd8jRoxAeXk5UlNTTX+BRNQs8HYyRGSz+vbti9deew0A0L17d6xduxZ79uzBfffdBwDw9fXFqlWrIJPJEBQUhKNHj2LVqlWYNWuWQev38PCAQqGAq6srOnbs2GDbzp0748CBA5q/ZTIZXFxccOnSJRNfHRE1FxyZImoJiovVD29vbeyll9SxtWt12xYUqONdumhjc+eqYx9/rNs2O1sd79lTG5s2zWxp9+3bV+dvHx8fzY1MAeCuu+7SueLx4MGDcfr0aahUKrPlUOPWkamMjAxcu3YNQ4YMMfu2iMi+cGSKqCVwc6sbUyjUD0PaOjmpH4a2NROnW9Ylk8lQXXt+ViMcHBx05lABpt+zq3PnziguLkZRURFat26NF154AU888QQ6depk0vqIqPlokSNTEydOxG233YbJkydbOxUikuC3336r83f37t01d4tv164d8vPzNcuLioqQlZWl8xyFQmHQSFbnzp0BALm5uVi4cCHy8/Ox9tZRPSJqkVpkMfX888/j008/tXYaRCRRTk4OoqKicPLkSXz55Zd47733EBkZqVk+cuRIfPbZZ0hJScGxY8cQERGhKbRq+Pv74+DBg8jOzsbly5frHfmqKaZefPFFJCYmYs+ePXB3d7fciyMiu9Eii6kRI0agTZs21k6DiCR68skncfPmTYSGhmLu3Ll47rnn8O9//1uzfPHixbj77rvxwAMPYNy4cXjooYfQrVs3nXXMnz8fcrkcwcHBaNeuHc7X/hVjLd7e3nB2dsa5c+ewf/9+TXFFRCQTt04osLL9+/djxYoVSEtLQ35+PrZv317nqsjvv/8+VqxYgfz8fPTq1QurV69GWFiYUdvZu3cv1q5di23bthn1vKKiInh4eKCwsJDfSsmmlJWVISsrC127doWLi4u107G44cOHo1+/fnWuI0VELVdDx0FLfn7b3AT0kpIShISEYPr06Xj44YfrLN+6dSvmzZuH999/H0OHDsW6desQHh6OzMxMdPnfr48GDBiA8lsvRAhg165dRk8WLS8v11lXUVGRka+IiIiImjObK6bCw8MRHh5e7/KVK1fiqaeewsyZMwEAq1evxs6dO/HBBx9g2bJlAIC0tDSz5bNs2TK8/vrrZlsfERERNS92NWeqoqICaWlpGD16tE589OjR+PXXXy2yzcWLF6OwsFDzyMnJsch2iMg4e/fu5Sk+IrIJNjcy1ZDLly9DpVKhQ4cOOvEOHTrg4sWLBq9nzJgxOHLkCEpKSqBUKrF9+3YMGjRIb1tnZ2c4OztLypuIiIiaL7sqpmrUvuIxAAgh6sQasnPnTnOnRERERC2UXZ3m8/b2hlwurzMKVVBQUGe0ioiIiKgp2FUxpVAoMGDAAJ27xgPA7t27LX5/rPj4eAQHB9d7OpCIiIhaJps7zVdcXIy///5b83dWVhYyMjLg6emJLl26ICoqClOnTsXAgQMxePBgrF+/HufPn8fs2bMtmtfcuXMxd+5czXUqiIiIiAAbLKZ+//13jBgxQvN3VFQUACAiIgKbNm3Co48+iitXriA2Nhb5+fno3bs3duzYAT8/P2ulTERERC2YzRVTw4cPr3OX91vNmTMHc+bMaaKMiIiIiOpnV3OmrIlzpoiIiEgfFlMGmjt3LjIzM3H48GFrp0JkVjExMYiLizPqOXFxcYiJibFMQkREdobFFFELJ5fLER0dbXBBFRcXh+joaMjlcgtnVtfw4cMxb948u9xWU+ZORE2LxRRRC7dkyRLExsYaVFDVFFKxsbFYsmSJ2XO5ePEinnvuOdx+++1wdnaGr68vxo8fjz179ph9W41JSkoyesROimnTpuGhhx5qcLlMJtM8vLy8MHbsWPz555962+n7hfOcOXMgk8kwbdo0yfnefffdmlycnJwQFBSEhISEOrksWrRI8raMsX//fowfPx6dOnWCTCbDN998U2/b2vl98MEH6Nu3L9zd3eHu7o7Bgwfjxx9/bKKsyd6xmCIigwoqSxdS2dnZGDBgAH755RcsX74cR48exU8//YQRI0Zg7ty5Zt9eYzw9PdGmTZsm325Dxo4di/z8fOTn52PPnj1wdHTEAw88UKedr68vtmzZgps3b2piZWVl+PLLL9GlSxfJeQghkJGRgWXLliE/Px+nTp3CsGHDEBERgaysLABAdXU1fvjhB0yYMEHy9oxRUlKCkJAQrF27tsF2t+anVCrx1ltv4ffff8fvv/+OkSNHYsKECTh+/HhTpE12jsUUEQFouKCydCEFaEdNDh06hMmTJyMwMBC9evVCVFQUfvvtN73P+emnnzBs2DC0bdsWXl5eeOCBB3DmzBmdNtu2bUOfPn3QqlUreHl5YdSoUSgpKWl02a2n5aqrq/H2228jICAAzs7O6NKlC9544w2jcpHK2dkZHTt2RMeOHdGvXz8sXLgQOTk5uHTpkk67/v37o0uXLkhKStLEkpKS4OvrizvuuENyHqdPn8aNGzcwbNgwdOzYEV27dsXLL7+MqqoqzUhZamoqHBwccOedd+o898CBAwgNDYWLiwu8vb2xatUqyfnUFh4ejqVLl2LSpEkNtrs1v/Hjx2PcuHEIDAxEYGAg3njjDbRu3bre9x5RbSymDMRf81FLoK+gaopC6urVq/jpp58wd+5cuLm51Vnetm1bvc8rKSlBVFQUDh8+jD179sDBwQETJ05EdXU1ACA/Px+PP/44ZsyYgRMnTmDv3r2YNGkShBANLtNn8eLFePvtt7FkyRJkZmYiISFB5zZWjeVibsXFxfjiiy8QEBAALy+vOsunT5+OjRs3av7+5JNPMGPGjEbXu2nTpkbvdZqWlgaZTIa+fftqYrm5uQCg6ZPvvvsO48ePh4OD9mNmx44dmDhxIubMmYM///wTTz/9NKKiovQWnW+++SZat27d4CMlJaXR11MfffnVUKlU2LJlC0pKSjB48GCTt0EtiCCjFBYWCgCisLDQ2qkQ6bh586bIzMwUN2/elLyu2NhYAUAoFAoBQMTGxpohw/odPHhQABBJSUkNtrvnnntEZGRkvcsLCgoEAHH06FEhhBBpaWkCgMjOzq7TtqFlt26rqKhIODs7iw0bNhj2gvTk0ljuERERYsKECQ0ul8vlws3NTbi5uQkAwsfHR6Slpeldz6VLl4Szs7PIysoS2dnZwsXFRVy6dElMmDBBRERE1LudpKQkERQU1OBrmz9/vrj99ts1f//1119i4MCBol+/fkKlUgkhhAgMDBTfffedps3NmzeFUqkUX3zxhSZWVVUl2rRpIz7++OM627hy5Yo4ffp0g4/S0tIG8wQgtm/frnfZrfkJIcSff/4p3NzchFwuFx4eHuKHH35ocP1kexo6Dlry85sjU0RUx5IlS6BQKFBRUQGFQmGxEaka4n+jQY2NiNzqzJkzmDJlCm6//Xa4u7uja9euAIDz588DAEJCQnDvvfeiT58+eOSRR7BhwwZcu3at0WW3OnHiBMrLy3HvvfeanIs5jBgxAhkZGcjIyMDBgwcxevRohIeH49y5c3Xaent74/7778fmzZuxceNG3H///fD29m50GxMnTsRff/3VYJu0tDRkZ2ejdevWcHFxQb9+/dCrVy/89NNPcHBwwIkTJ5Cbm4tRo0ZpnvPLL7/g5s2bePTRRzUxuVwOR0dHODs719mGp6cnAgICGny0atWq0dejj778ACAoKAgZGRn47bff8MwzzyAiIgKZmZkmbYNaFhZTRFRHXFycppCqqKiw+K/aunfvDplMhhMnThj1vPHjx+PKlSvYsGEDDh48iIMHDwIAKioqAKg/rHfv3o0ff/wRwcHBeO+99xAUFISsrKwGl93KkA/txnIxBzc3N00hERoaio8//hglJSXYsGGD3vYzZszApk2bsHnzZoNO8RkqPT0dL730EjIyMnD27FmUlpZi06ZNOqf47rvvPp1+S05ORkhIiM4lNbKysnDt2jX079+/zjYseZpPX34AoFAoEBAQgIEDB2LZsmUICQnBmjVrTNoGtSwspohIR+05UuXl5QZfNkEKT09PjBkzBvHx8ZoJ4LVdv369TuzKlSs4ceIEXn31Vdx7773o2bOn3pElmUyGoUOH4vXXX0d6ejoUCgW2b9/e6LLaunfvjlatWtV7iQZDczE3mUwGBwcHnV/t1TZ27FhUVFSgoqICY8aMMcs2z549i+vXr+O+++5DQECA5hIEtX377bd48MEHdWLp6el1Csv33nsP/fv3R8+ePetsZ/bs2ZpRuPoeAwcONOk16MtPHyEEysvLTdoGtSw2d28+IrIefZPNa/4bHR2t87e5vf/++xgyZAhCQ0MRGxuLvn37oqqqCrt378YHH3xQZ9Tqtttug5eXF9avXw8fHx+cP3++zjWNDh48iD179mD06NFo3749Dh48iEuXLqFnz54NLruVi4sLFi5ciAULFkChUGDo0KG4dOkSjh8/jqeeesqgXAxRWFiIjIwMnZinp6fmcgbl5eW4ePEiAODatWtYu3YtiouLMX78eL3rk8vlmn4z9CKr27dvx+LFi+s91Vcz+XzAgAF6lxcUFODw4cN1ru+UkZGB6upqbN68GYMHD8ZXX32FDz74AKmpqXrX4+npCU9PT4Nyrq24uBh///235u+srCxkZGRo+rG+/F5++WWEh4fD19cXN27cwJYtW7B371789NNPRudALZDZZ2E1U2vXrhU9e/YUgYGBnIBONknqBPSaSef1TTZvbLk5XLhwQcydO1f4+fkJhUIhOnfuLB588EGRnJwshKg7iXv37t2iZ8+ewtnZWfTt21fs3btXZ9JxZmamGDNmjGjXrp1wdnYWgYGB4r333mt0mb5tqVQqsXTpUuHn5yecnJxEly5dxJtvvmlwLoZMQAdQ51EzWfzW5W3atBGDBg0S27Ztq7OehiayNzYBfePGjaKhj4ZFixaJ7t2717v8o48+EkOHDtWJnTt3TgAQP/zwg+jdu7dQKBRi4MCBYu/evfWux1TJyckN9qO+/IQQYsaMGZr3Xbt27cS9994rdu3aZfb8yLKsNQGdxZSR+Gs+slVSiilDC6WmKKjIvo0fP168/fbbOrFvv/1WeHp6WikjXfryo+bDWsUUT/MRtXDGXEeqqU75kf0aNmwYHn/8cZ1Yeno6+vTpY6WMdOnLj0gqFlNELZxKpTLqgpw17VQqlSXTIju1YMGCOrH09HSdC3xak778iKSSCVHP5X5Jr6KiInh4eKCwsBDu7u7WTodIo6ysDFlZWejatStcXFysnQ4RUZNr6Dhoyc9vXhqBiIiISAIWU0REREQSsJgyEG90TERERPqwmDLQ3LlzkZmZicOHD1s7FSIiIrIhLKaIiIiIJGAxRURERCQBiykiIiIiCVhMEREREUnAYoqIiIhIAhZTRERERBKwmCIiIiKbMHz4cMybN8/aaRiNxZSBeNFOaklUKhX27t2LL7/8Env37uVNjY109913QyaTQSaTwcnJCUFBQUhISGiSbe/fvx/jx49Hp06dIJPJ8M033xj0vPfff19zP7MBAwYgJSXFpDbWZOprz8vLw7/+9S94eXnB1dUV/fr1Q1pamma5v7+/Zn/WfsydO9eo/KZNmwaZTIbZs2fXWTZnzhzIZDJMmzbNqHU2haYscJKSkhAXF9ck2zInFlMG4kU7qaVISkqCv78/RowYgSlTpmDEiBHw9/dHUlKStVOzC0IIZGRkYNmyZcjPz8epU6cwbNgwREREICsrq97nVVVVmWX7JSUlCAkJwdq1aw1+ztatWzFv3jy88sorSE9PR1hYGMLDw3H+/Hmj2libKa/92rVrGDp0KJycnPDjjz8iMzMT//nPf9C2bVtNm8OHDyM/P1/z2L17NwDgkUceMTpHX19fbNmyBTdv3tTEysrK8OWXX6JLly5Gr6+58fT0RJs2baydhvEEGaWwsFAAEIWFhdZOhUjHzZs3RWZmprh586bJ60hMTBQymUwA0HnIZDIhk8lEYmKiGTPWNXbsWPHkk09q/t6zZ4/w9PQUlZWVFtumJZw8eVIAECkpKZrY33//LQCIb775RgghRFZWlgAgvv76axEWFiYUCoX46quvzJ4LALF9+/ZG24WGhorZs2frxHr06CEWLVpkVJuGdO/eXdx1112itLRUE6uurhZ33nmneOmllwxahzEMfe0LFy4Uw4YNM2rdkZGRolu3bqK6utqo50VERIgJEyaIPn36iM8//1wT/+KLL0SfPn3EhAkTREREhCZeVlYmnnvuOdGuXTvh7Owshg4dKg4dOqRZfs8994jnnntOvPTSS+K2224THTp0EK+99prONhtbx48//iiGDh0qPDw8hKenp7j//vvF33//rZPzrceDrKysRtdbk9+zzz4rIiMjRdu2bUX79u3FunXrRHFxsZg2bZpo3bq1uP3228WOHTt0nhMZGan5W6VSibfeekt069ZNKBQK4evrK5YuXVpvHzd0HLTk5zdHpogIgPrUXmRkJIQQdZbVxObNm2exU36dO3dGXl6e5u8RI0agvLwcqampFtmeKTZt2gSZTNZgm7S0NMhkMvTt21cTy83NBQB06NABAJCRkQEAePvtt7FkyRIcP34co0eP1rR/88030bp16wYf5jrFVlFRgbS0NJ3tA8Do0aPx66+/GtymMVu3bkV6errO/vziiy+QlZWFV199VadtU77+7777DgMHDsQjjzyC9u3b44477sCGDRvqbV9RUYHPP/8cM2bMaPS9UJ/p06dj48aNmr8/+eQTzJgxo067BQsWIDExEZs3b8aRI0cQEBCAMWPG4OrVq5o2mzdvhpubGw4ePIjly5cjNjZWM3JmyDpKSkoQFRWFw4cPY8+ePXBwcMDEiRNRXV0NAFizZg0GDx6MWbNmaUbmfH19DcqtJj9vb28cOnQIzz33HJ555hk88sgjGDJkCI4cOYIxY8Zg6tSpKC0t1dtXixcv1vw7yczMREJCgubfkU0xe3nWzHFkimyV1JGp5OTkOt9A9T2Sk5PNm/j/REdHi6CgIJ2Yl5eX+Prrr8U777wjoqOj6zznnXfeEZ07dxYhISHC399fPP/88/Wuf/fu3WLlypWSckxKSqqT463mz58vbr/9ds3ff/31lxg4cKDo16+fUKlU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FlNEREREErCYIiIiIpKAxRQRERGRBCymiIiIiCRgMWUgXhqBiIiI9OGlEYzESyMQERHZH14agYiIiMhGsZgiIiIikoDFFBEREZEELKaIiIiIJGAxRURERCQBiykiIiIiCVhMEREREUnAYspAvGgnERER6cOLdhqJF+0kIiKyP7xoJxEREZGNYjFFREREJAGLKSIiIiIJWEwRERERScBiioiIiEgCFlNEREREErCYIiIiIpKAxRQRERGRBCymiIiIiCRgMUVEREQkAYspA/HefERERKQP781nJN6bj4iIyP7w3nxERERENorFFBEREZEELKaIiIiIJGAxRURERCQBiykiIiIiCVhMEREREUnAYoqIiIhIAhZTRERERBKwmCIiIiKSgMUUERERkQQspoiIiIgkYDFFREREJAGLKSIiIiIJHK2dgL0RQgBQ332aiIiI7EPN53bN57g5sZgyUHx8POLj41FRUQEA8PX1tXJGREREZKwrV67Aw8PDrOuUCUuUaM1YdXU1AgMDkZaWBplMZvTzBw0ahMOHD5ulbUPL61umL95YrKioCL6+vsjJyYG7u7tBuZvKmP6R8lz2reWey7613HMNaWtMH9YXZ98a14Z9K71tU/RtYWEhunTpgmvXrqFt27YG5W4ojkwZycHBAQqFwuSqVi6XG/wPpLG2DS2vb5m+uKExd3d3i//jNqZ/pDyXfWu557JvLfdcQ9oa04f1xdm3xrVh30pv25R96+Bg/uninIBugrlz5zbJcxtr29Dy+pbpixsaawrsW8th31qOrfRtQ23Yt9Lbsm9Ne25L6Fue5qNGFRUVwcPDA4WFhRb/ptTSsG8th31rOexby2HfWo4l+5YjU9QoZ2dnvPbaa3B2drZ2Ks0O+9Zy2LeWw761HPat5ViybzkyRURERCQBR6aIiIiIJGAxRURERCQBiykiIiIiCVhMEREREUnAYoqIiIhIAhZTZFaOjo7o168f+vXrh5kzZ1o7nWantLQUfn5+mD9/vrVTaTZu3LiBQYMGoV+/fujTpw82bNhg7ZSajZycHAwfPhzBwcHo27cvvv76a2un1KxMnDgRt912GyZPnmztVOze999/j6CgIHTv3h0fffSR0c/npRHIrLy9vXH58mVrp9FsvfLKKzh9+jS6dOmCd955x9rpNAsqlQrl5eVwdXVFaWkpevfujcOHD8PL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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Plotting\n", + "plt.axhline(y=0.0001,linestyle='dotted',color='red')\n", + "plt.axhline(y=0.001,linestyle='dotted',color='red')\n", + "plt.axhline(y=0.01,linestyle='dotted',color='red',label='Input '+r'$\\nu$')\n", + "\n", + "plt.loglog(np.ones(3)/3.0,np.array([0.01,0.001,0.0001]),label='Classical LBM : '+r'${P}/{\\rho}=1/3$',marker='x',markersize=10,color='k',linestyle='none')\n", + "plt.loglog(PByRhoWithCorrection0p0001,nuRecoveredWithCorrection0p0001,label=r'$\\nu_{LB sim}$ : '+r'$Pr=1.00, \\gamma=1.67$'+'. Monoatomic',marker='o',color='k',linestyle='none')\n", + "plt.loglog(PByRhoWithCorrection0p001,nuRecoveredWithCorrection0p001,marker='o',color='k',linestyle='none')\n", + "plt.loglog(PByRhoWithCorrection0p01,nuRecoveredWithCorrection0p01,marker='o',color='k',linestyle='none')\n", + "\n", + "plt.xlabel(r'${P}/{\\rho}$')\n", + "plt.ylabel('Kinematic viscosity '+r'$(\\nu)$')\n", + "plt.ylim(2e-5,2e-1)\n", + "plt.xlim(2e-6,1.0)\n", + "plt.legend(loc='best')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7dc2f2df-3705-4fd1-9ee6-507c8d0fdfde", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}