diff --git a/docs/sphinx/references/references.bib b/docs/sphinx/references/references.bib index 1ed40a513..c6d35a544 100644 --- a/docs/sphinx/references/references.bib +++ b/docs/sphinx/references/references.bib @@ -412,4 +412,11 @@ @book{wilcox1998turbulence volume={2}, year={1998}, publisher={DCW industries La Canada, CA} -} \ No newline at end of file +} + +@article{Menter:2015, + Author = {Menter, F. R. and Smirnov, P. E., and Liu, T and Avancha, R.}, + Journal = {Flow Turbulence Combust}, + Title = {A One-Equation Local Correlation-Based Transition Model}, + Year = {2015} +} diff --git a/docs/sphinx/source/theory/supportedEquationSet.rst b/docs/sphinx/source/theory/supportedEquationSet.rst index b634d559b..d35141824 100644 --- a/docs/sphinx/source/theory/supportedEquationSet.rst +++ b/docs/sphinx/source/theory/supportedEquationSet.rst @@ -855,6 +855,41 @@ where :math:`\Omega` is the earth's angular velocity and :math:`\lambda` is the .. _eqn_sst_des: +Laminar-Turbulent Transition Model Formulation +++++++++++++++++++++++++++++++++++++++++++++++ +To account for the effects of the laminar-turbulent boundary layer transition, +Menter's one-equation :math:`\gamma` transition model :cite:`Menter:2015` is coupled with the SST model. +The model consists of single transport equation for intermittency + +.. math:: + \frac{D(\rho \gamma)}{Dt}=P_{\gamma}-D_{\gamma}+\frac{\partial }{\partial x_j}\left[ (\mu + \frac{\mu_t}{\sigma_{\gamma}} )\frac{\partial \gamma}{\partial x_j} \right] + +The production term, :math:`P_{\gamma}`, and destruction term, :math:`D_{\gamma}`, are as: + +.. math:: + P_{\gamma}=F_{length} \rho S \gamma (1-\gamma) F_{onset}, \quad D_{\gamma}=C_{a2} \rho \Omega \gamma F_{turb} (C_{e2}\gamma-1) + +The model constants are: + +.. math:: + F_{length}=100, \quad c_{e2}=50, \quad c_{a2}=0.06, \quad \sigma_{\gamma}=1.0 + +The transition onset criteria of the model are defined as: + +.. math:: + F_{onset1}=\frac{Re_{v}}{2.2Re_{\theta c}}, \quad F_{onset2}=(F_{onset1},2.0 ) + +.. math:: + F_{onset3}=\max \left(1- \left (\frac{R_{T}}{3.5}\right)^3,0 \right ), \quad F_{onset}=\max(F_{onset2}-F_{onset3},0) + +.. math:: + F_{turb}=e^{-\left ( \frac{R_{T}}{2} \right )^{4}}, \quad R_T=\frac{\rho k}{\mu \omega}, \quad Re_v=\frac{\rho d_{w}^2S}{\mu} + +The transition onset occurs once the scaled vorticity Reynolds number, :math:`Re_{v}/2.2`, exceeds the critical momentum thickness Reynolds number, :math:`Re_{\theta c}`, from the empirical correlations. + +The output intermittency from the transition model is applied to both the production and destruction terms of the turbulent kinetic energy +transport equation. + Detached Eddy Simulation (DES) Formulation ++++++++++++++++++++++++++++++++++++++++++ diff --git a/include/Enums.h b/include/Enums.h index b12022330..eeff62168 100644 --- a/include/Enums.h +++ b/include/Enums.h @@ -245,12 +245,8 @@ enum TurbulenceModelConstant { TM_sdrAmb = 63, TM_avgTimeCoeff = 64, TM_alphaInf = 65, - TM_caOne = 66, - TM_caTwo = 67, - TM_ceOne = 68, - TM_ceTwo = 69, - TM_c0t = 70, - TM_END = 71 + TM_fsti = 66, + TM_END = 67 }; static const std::string TurbulenceModelConstantNames[] = { @@ -320,11 +316,7 @@ static const std::string TurbulenceModelConstantNames[] = { "sdr_amb", "avgTimeCoeff", "alphaInf", - "caOne", - "caTwo", - "ceOne", - "ceTwo", - "c0t", + "fsti", "END"}; enum ActuatorType { diff --git a/include/GammaEquationSystem.h b/include/GammaEquationSystem.h index 396479c4d..aad8f01f1 100644 --- a/include/GammaEquationSystem.h +++ b/include/GammaEquationSystem.h @@ -73,10 +73,15 @@ class GammaEquationSystem : public EquationSystem VectorFieldType* dgamdx_; ScalarFieldType* gamTmp_; ScalarFieldType* minDistanceToWall_; + VectorFieldType* dwalldistdx_; + ScalarFieldType* nDotV_; + VectorFieldType* dnDotVdx_; ScalarFieldType* visc_; ScalarFieldType* tvisc_; ScalarFieldType* evisc_; ScalarNodalGradAlgDriver nodalGradAlgDriver_; + ScalarNodalGradAlgDriver wallDistGradAlgDriver_; + ScalarNodalGradAlgDriver nDotVGradAlgDriver_; std::unique_ptr effDiffFluxAlg_; }; diff --git a/include/NaluParsedTypes.h b/include/NaluParsedTypes.h index 852fca2d2..00f3c2020 100644 --- a/include/NaluParsedTypes.h +++ b/include/NaluParsedTypes.h @@ -63,12 +63,6 @@ struct GammaInf GammaInf() : gamma_(1.0) {} }; -struct GammaOpen -{ - double gamma_; - GammaOpen() : gamma_(1.0) {} -}; - struct Temperature { double temperature_; diff --git a/include/NaluParsing.h b/include/NaluParsing.h index e6d46577b..c6fdb7558 100644 --- a/include/NaluParsing.h +++ b/include/NaluParsing.h @@ -137,7 +137,7 @@ struct OpenUserData : public UserData MixtureFraction mixFrac_; VolumeOfFluid volumeOfFluid_; MassFraction massFraction_; - GammaOpen gamma_; + GammaInf gamma_; bool uSpec_; bool pSpec_; diff --git a/include/ShearStressTransportEquationSystem.h b/include/ShearStressTransportEquationSystem.h index 6e646fe96..0bbeb3d13 100644 --- a/include/ShearStressTransportEquationSystem.h +++ b/include/ShearStressTransportEquationSystem.h @@ -92,7 +92,7 @@ class ShearStressTransportEquationSystem : public EquationSystem const double tkeMinValue_{1.0e-8}; const double sdrMinValue_{1.0e-8}; - const double gammaMinValue_{0.0}; + const double gammaMinValue_{0.02}; const double gammaMaxValue_{1.0}; }; diff --git a/include/node_kernels/BLTGammaM2015NodeKernel.h b/include/node_kernels/BLTGammaM2015NodeKernel.h index be7042e6d..88bdd2de2 100644 --- a/include/node_kernels/BLTGammaM2015NodeKernel.h +++ b/include/node_kernels/BLTGammaM2015NodeKernel.h @@ -57,6 +57,8 @@ class BLTGammaM2015NodeKernel : public NGPNodeKernel stk::mesh::NgpField visc_; stk::mesh::NgpField dudx_; stk::mesh::NgpField minD_; + stk::mesh::NgpField dwalldistdx_; + stk::mesh::NgpField dnDotVdx_; stk::mesh::NgpField dualNodalVolume_; stk::mesh::NgpField coordinates_; stk::mesh::NgpField velocityNp1_; @@ -68,16 +70,12 @@ class BLTGammaM2015NodeKernel : public NGPNodeKernel unsigned viscID_{stk::mesh::InvalidOrdinal}; unsigned dudxID_{stk::mesh::InvalidOrdinal}; unsigned minDID_{stk::mesh::InvalidOrdinal}; + unsigned dwalldistdxID_{stk::mesh::InvalidOrdinal}; + unsigned dnDotVdxID_{stk::mesh::InvalidOrdinal}; unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; unsigned gamintID_{stk::mesh::InvalidOrdinal}; - NodeKernelTraits::DblType caOne_; - NodeKernelTraits::DblType caTwo_; - NodeKernelTraits::DblType ceOne_; - NodeKernelTraits::DblType ceTwo_; - - int timeStepCount; - int maxStepCount; + NodeKernelTraits::DblType fsti_; const int nDim_; }; diff --git a/include/node_kernels/SDRSSTBLTM2015NodeKernel.h b/include/node_kernels/SDRSSTBLTM2015NodeKernel.h new file mode 100644 index 000000000..060a262a7 --- /dev/null +++ b/include/node_kernels/SDRSSTBLTM2015NodeKernel.h @@ -0,0 +1,84 @@ +// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS), National Renewable Energy Laboratory, University of Texas Austin, +// Northwest Research Associates. Under the terms of Contract DE-NA0003525 +// with NTESS, the U.S. Government retains certain rights in this software. +// +// This software is released under the BSD 3-clause license. See LICENSE file +// for more details. +// + +#ifndef SDRSSTBLTM2015NODEKERNEL_H +#define SDRSSTBLTM2015NODEKERNEL_H + +#include "node_kernels/NodeKernel.h" +#include "FieldTypeDef.h" + +#include "stk_mesh/base/BulkData.hpp" +#include "stk_mesh/base/Ngp.hpp" +#include "stk_mesh/base/NgpField.hpp" +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class SDRSSTBLTM2015NodeKernel : public NGPNodeKernel +{ +public: + SDRSSTBLTM2015NodeKernel(const stk::mesh::MetaData&); + + SDRSSTBLTM2015NodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~SDRSSTBLTM2015NodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField tke_; + stk::mesh::NgpField sdr_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField dkdx_; + stk::mesh::NgpField dwdx_; + stk::mesh::NgpField dualNodalVolume_; + stk::mesh::NgpField fOneBlend_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned dkdxID_{stk::mesh::InvalidOrdinal}; + unsigned dwdxID_{stk::mesh::InvalidOrdinal}; + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned fOneBlendID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType sigmaWTwo_; + NodeKernelTraits::DblType betaOne_; + NodeKernelTraits::DblType betaTwo_; + NodeKernelTraits::DblType gammaOne_; + NodeKernelTraits::DblType gammaTwo_; + NodeKernelTraits::DblType sdrAmb_; + + const int nDim_; + + bool lengthScaleLimiter_; + NodeKernelTraits::DblType corfac_; + NodeKernelTraits::DblType referenceVelocity_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* SDRSSTBLTM2015NODEKERNEL_H */ diff --git a/include/node_kernels/TKESSTBLTM2015NodeKernel.h b/include/node_kernels/TKESSTBLTM2015NodeKernel.h new file mode 100644 index 000000000..dabb1aa96 --- /dev/null +++ b/include/node_kernels/TKESSTBLTM2015NodeKernel.h @@ -0,0 +1,75 @@ +// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS), National Renewable Energy Laboratory, University of Texas Austin, +// Northwest Research Associates. Under the terms of Contract DE-NA0003525 +// with NTESS, the U.S. Government retains certain rights in this software. +// +// This software is released under the BSD 3-clause license. See LICENSE file +// for more details. +// + +#ifndef TKESSTBLTM2015NODEKERNEL_H +#define TKESSTBLTM2015NODEKERNEL_H + +#include "node_kernels/NodeKernel.h" +#include "FieldTypeDef.h" +#include "stk_mesh/base/BulkData.hpp" +#include "stk_mesh/base/Ngp.hpp" +#include "stk_mesh/base/NgpField.hpp" +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class TKESSTBLTM2015NodeKernel : public NGPNodeKernel +{ +public: + TKESSTBLTM2015NodeKernel(const stk::mesh::MetaData&); + + TKESSTBLTM2015NodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~TKESSTBLTM2015NodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField tke_; + stk::mesh::NgpField sdr_; + stk::mesh::NgpField gamint_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField visc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField wallDist_; + stk::mesh::NgpField dualNodalVolume_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned gamintID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned wallDistID_{stk::mesh::InvalidOrdinal}; + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType tkeAmb_; + NodeKernelTraits::DblType sdrAmb_; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* TKESSTBLTM2015NODEKERNEL_H */ diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index 94c823ff4..f2722b754 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -207,6 +207,7 @@ if(NOT ENABLE_CUDA AND NOT ENABLE_ROCM) add_test_r(airfoilRANSEdgeNGPHypre.rst 2) add_test_r(fsiTurbineSurrogate 4) add_test_r(VOFZalDisk 4) + add_test_r(airfoilSST_Gamma_Trans 4) if (ENABLE_TRILINOS_SOLVERS) add_test_r(aslNeutralEdgeSST 4) @@ -302,6 +303,7 @@ else() add_test_r(ablNeutralNGPHypreSegregated 2) add_test_r(multiElemCylinder 2) add_test_r(VOFZalDisk 2) + add_test_r(airfoilSST_Gamma_Trans 4) endif() if (ENABLE_TIOGA AND ENABLE_TRILINOS_SOLVERS) diff --git a/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.norm.gold b/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.norm.gold new file mode 100644 index 000000000..4ff1c609e --- /dev/null +++ b/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.norm.gold @@ -0,0 +1,5 @@ +9886408.858641421 1 0.0146628 +3938.732212071351 2 0.0293255 +43.78119071175424 3 0.0439883 +26.35564999333952 4 0.058651 +18.24183547843733 5 0.0733138 diff --git a/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.yaml b/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.yaml new file mode 100644 index 000000000..737cfbaeb --- /dev/null +++ b/reg_tests/test_files/airfoilSST_Gamma_Trans/airfoilSST_Gamma_Trans.yaml @@ -0,0 +1,316 @@ + +Simulations: +- name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +# Hypre memory and other configurations +hypre_config: + memory_pool_mbs: 3000 + use_vendor_sgemm: no + +linear_solvers: + # solver for the momentum + - name: solve_mom + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 100 + kspace: 20 + segregated_solver: yes + write_matrix_files: no + #write_preassembly_matrix_files: yes + recompute_preconditioner_frequency: 1 + reuse_linear_system: yes + simple_hypre_matrix_assemble: yes + dump_hypre_matrix_stats: no + + bamg_max_levels: 1 + bamg_relax_type: 12 + bamg_num_sweeps: 2 + bamg_cycle_type: 1 + bamg_relax_order: 0 + + bamg_output_level: 0 + bamg_debug: 0 + output_level: 0 + + # solver for the scalars TKE, SDR + - name: solve_scalar + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 100 + kspace: 20 + write_matrix_files: no + #write_preassembly_matrix_files: yes + recompute_preconditioner_frequency: 1 + reuse_linear_system: yes + simple_hypre_matrix_assemble: yes + dump_hypre_matrix_stats: no + + bamg_max_levels: 1 + bamg_relax_type: 12 + bamg_num_sweeps: 2 + bamg_cycle_type: 1 + bamg_relax_order: 0 + + bamg_output_level: 0 + bamg_debug: 0 + output_level: 0 + + # solver for the pressure + - name: solve_elliptic + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 100 + kspace: 40 + write_matrix_files: no + #write_preassembly_matrix_files: yes + recompute_preconditioner_frequency: 1 + reuse_linear_system: yes + simple_hypre_matrix_assemble: yes + dump_hypre_matrix_stats: no + + #bamg_max_levels: 7 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_relax_type: 11 + bamg_cycle_type: 1 + bamg_relax_order: 0 + bamg_keep_transpose: 1 + + bamg_num_sweeps: 2 + #bamg_num_down_sweeps: 2 + #bamg_num_up_sweeps: 2 + #bamg_num_coarse_sweeps: 1 + + bamg_strong_threshold: 0.3243198904981685 + bamg_trunc_factor: 0.4227143073461007 + bamg_pmax_elmts: 3 + + bamg_agg_num_levels: 1 + bamg_agg_interp_type: 7 + bamg_agg_pmax_elmts: 3 + + bamg_output_level: 0 + bamg_debug: 0 + output_level: 0 + + # solver for the wall + - name: solve_wall + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 100 + kspace: 40 + write_matrix_files: no + #write_preassembly_matrix_files: yes + recompute_preconditioner_frequency: 1 + reuse_linear_system: yes + simple_hypre_matrix_assemble: yes + dump_hypre_matrix_stats: no + + bamg_max_levels: 7 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_relax_type: 11 + bamg_num_sweeps: 2 + bamg_cycle_type: 1 + bamg_relax_order: 0 + bamg_trunc_factor: 0.1 + bamg_agg_num_levels: 2 + bamg_agg_interp_type: 5 + bamg_agg_pmax_elmts: 3 + bamg_pmax_elmts: 3 + bamg_strong_threshold: 0.25 + + bamg_output_level: 0 + bamg_debug: 0 + output_level: 0 + +realms: + + - name: realm_1 + mesh: ../../mesh/du91w2_airfoil.exo + automatic_decomposition_type: rcb + use_edges: yes + + time_step_control: + target_courant: 1000.0 + time_step_change_factor: 1.05 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_mom + turbulent_ke: solve_scalar + specific_dissipation_rate: solve_scalar + pressure: solve_elliptic + ndtw: solve_wall + gamma_transition: solve_scalar + + systems: + + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1e-8 + + - LowMachEOM: + name: myLowMach + max_iterations: 1 + convergence_tolerance: 1e-8 + + - ShearStressTransport: + name: mySST + max_iterations: 1 + convergence_tolerance: 1e-8 + + initial_conditions: + - constant: ic_1 + target_name: [Flow-QUAD] + value: + pressure: 0 + velocity: [34.1, 0.0] + turbulent_ke: 0.00392448375 + specific_dissipation_rate: 460.34999999999997 + gamma_transition: 1.0 + + material_properties: + target_name: [Flow-QUAD] + specifications: + - name: density + type: constant + value: 1.225 + - name: viscosity + type: constant + value: 1.0443125000000002e-05 + + boundary_conditions: + + - wall_boundary_condition: bc_wall + target_name: airfoil + wall_user_data: + velocity: [0,0] + use_wall_function: no + turbulent_ke: 0.0 + + + - inflow_boundary_condition: bc_inflow + target_name: inlet + inflow_user_data: + velocity: [34.1, 0.0] + turbulent_ke: 0.00392448375 + specific_dissipation_rate: 460.34999999999997 + + - open_boundary_condition: bc_open + target_name: outlet + open_user_data: + velocity: [0,0] + pressure: 0.0 + turbulent_ke: 0.00392448375 + specific_dissipation_rate: 460.34999999999997 + + solution_options: + name: myOptions + turbulence_model: sst + transition_model: true + projected_timescale_type: momentum_diag_inv #### Use 1/diagA formulation + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + gamma_transition: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + specific_dissipation_rate: 0.0 + gamma_transition: 0.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + gamma_transition: 1.0 + + - noc_correction: + pressure: yes + + - limiter: + pressure: no + velocity: yes + turbulent_ke: yes + specific_dissipation_rate: yes + + - projected_nodal_gradient: + velocity: element + pressure: element + turbulent_ke: element + specific_dissipation_rate: element + gamma_transition: element + + - relaxation_factor: + velocity: 0.7 + pressure: 0.3 + turbulent_ke: 0.7 + specific_dissipation_rate: 0.7 + gamma_transition: 0.7 + + - turbulence_model_constants: + fsti: 0.15 + + #Use this to set the mean angle of attack + mesh_transformation: + - name: interior + mesh_parts: [ Flow-QUAD ] + motion: + - type: rotation + angle: 0.0 + axis: [0.0, 0.0, -1.0] + centroid: [0.25, 0.0, 0.0] + + + post_processing: + - type: surface + physics: surface_force_and_moment + output_file_name: results/forces.dat + frequency: 1 + parameters: [0.25, 0] + target_name: airfoil + + output: + output_data_base_name: results/du91w2.e + output_frequency: 5000 + output_node_set: no + output_variables: + - velocity + - pressure + - turbulent_ke + - specific_dissipation_rate + - turbulent_viscosity + - minimum_distance_to_wall + - gamma_transition + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 0.014662756598240468 + termination_step_count: 5 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/src/GammaEquationSystem.C b/src/GammaEquationSystem.C index b6a198a37..b73eb84b3 100644 --- a/src/GammaEquationSystem.C +++ b/src/GammaEquationSystem.C @@ -98,10 +98,15 @@ GammaEquationSystem::GammaEquationSystem(EquationSystems& eqSystems) dgamdx_(NULL), gamTmp_(NULL), minDistanceToWall_(NULL), + dwalldistdx_(NULL), + nDotV_(NULL), + dnDotVdx_(NULL), visc_(NULL), tvisc_(NULL), evisc_(NULL), - nodalGradAlgDriver_(realm_, "gamma_transition", "dgamdx") + nodalGradAlgDriver_(realm_, "gamma_transition", "dgamdx"), + wallDistGradAlgDriver_(realm_, "minimum_distance_to_wall", "dwalldistdx"), + nDotVGradAlgDriver_(realm_, "nDotV", "dnDotVdx") { dofName_ = "gamma_transition"; @@ -162,6 +167,25 @@ GammaEquationSystem::register_nodal_fields( &(meta_data.declare_field(stk::topology::NODE_RANK, "gamTmp")); stk::mesh::put_field_on_mesh(*gamTmp_, selector, nullptr); + minDistanceToWall_ = meta_data.get_field( + stk::topology::NODE_RANK, "minimum_distance_to_wall"); + + dwalldistdx_ = + &(meta_data.declare_field(stk::topology::NODE_RANK, "dwalldistdx")); + stk::mesh::put_field_on_mesh(*dwalldistdx_, selector, nDim, nullptr); + stk::io::set_field_output_type( + *dwalldistdx_, stk::io::FieldOutputType::VECTOR_3D); + + nDotV_ = + &(meta_data.declare_field(stk::topology::NODE_RANK, "nDotV")); + stk::mesh::put_field_on_mesh(*nDotV_, selector, nullptr); + + dnDotVdx_ = + &(meta_data.declare_field(stk::topology::NODE_RANK, "dnDotVdx")); + stk::mesh::put_field_on_mesh(*dnDotVdx_, selector, nDim, nullptr); + stk::io::set_field_output_type( + *dnDotVdx_, stk::io::FieldOutputType::VECTOR_3D); + visc_ = &(meta_data.declare_field(stk::topology::NODE_RANK, "viscosity")); stk::mesh::put_field_on_mesh(*visc_, selector, nullptr); @@ -200,14 +224,28 @@ GammaEquationSystem::register_interior_algorithm(stk::mesh::Part* part) ScalarFieldType& gammaNp1 = gamma_->field_of_state(stk::mesh::StateNP1); VectorFieldType& dgamdxNone = dgamdx_->field_of_state(stk::mesh::StateNone); - if (edgeNodalGradient_ && realm_.realmUsesEdges_) + if (edgeNodalGradient_ && realm_.realmUsesEdges_) { nodalGradAlgDriver_.register_edge_algorithm( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone); - else + + wallDistGradAlgDriver_.register_edge_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_); + + nDotVGradAlgDriver_.register_edge_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_); + + } else { nodalGradAlgDriver_.register_elem_algorithm( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone, edgeNodalGradient_); + wallDistGradAlgDriver_.register_elem_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_, + edgeNodalGradient_); + + nDotVGradAlgDriver_.register_elem_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_, edgeNodalGradient_); + } // solver; interior contribution (advection + diffusion) if (!realm_.solutionOptions_->useConsolidatedSolverAlg_) { @@ -242,7 +280,6 @@ GammaEquationSystem::register_interior_algorithm(stk::mesh::Part* part) // Check if the user has requested CMM or LMM algorithms; if so, do not // include Nodal Mass algorithms - // NaluEnv::self().naluOutputP0() << "register gamma interior: " << std::endl; std::vector checkAlgNames = { @@ -340,6 +377,15 @@ GammaEquationSystem::register_inflow_bc( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone, edgeNodalGradient_); + // non-solver; dwalldistdx; allow for element-based shifted + wallDistGradAlgDriver_.register_face_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_, + edgeNodalGradient_); + + // non-solver; dnDotVdx; allow for element-based shifted + nDotVGradAlgDriver_.register_face_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_, edgeNodalGradient_); + // Dirichlet bc std::map::iterator itd = solverAlgDriver_->solverDirichAlgMap_.find(algType); @@ -358,8 +404,8 @@ GammaEquationSystem::register_inflow_bc( void GammaEquationSystem::register_open_bc( stk::mesh::Part* part, - const stk::topology& /* partTopo */, - const OpenBoundaryConditionData& /* openBCData */) + const stk::topology& partTopo, + const OpenBoundaryConditionData& openBCData) { // algorithm type @@ -368,10 +414,60 @@ GammaEquationSystem::register_open_bc( ScalarFieldType& gammaNp1 = gamma_->field_of_state(stk::mesh::StateNP1); VectorFieldType& dgamdxNone = dgamdx_->field_of_state(stk::mesh::StateNone); + stk::mesh::MetaData& meta_data = realm_.meta_data(); + + // register boundary data; gamma_bc + ScalarFieldType* theBcField = &( + meta_data.declare_field(stk::topology::NODE_RANK, "open_gamma_bc")); + stk::mesh::put_field_on_mesh(*theBcField, *part, nullptr); + + // extract the value for user specified tke and save off the AuxFunction + OpenUserData userData = openBCData.userData_; + GammaInf gamma = userData.gamma_; + std::vector userSpec(1); + userSpec[0] = gamma.gamma_; + + // new it + ConstantAuxFunction* theAuxFunc = new ConstantAuxFunction(0, 1, userSpec); + + // bc data alg + AuxFunctionAlgorithm* auxAlg = new AuxFunctionAlgorithm( + realm_, part, theBcField, theAuxFunc, stk::topology::NODE_RANK); + bcDataAlg_.push_back(auxAlg); + // non-solver; dgamdx; allow for element-based shifted nodalGradAlgDriver_.register_face_algorithm( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone, edgeNodalGradient_); + + // non-solver; dwalldistdx; allow for element-based shifted + wallDistGradAlgDriver_.register_face_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_, + edgeNodalGradient_); + + // non-solver; dnDotVdx; allow for element-based shifted + nDotVGradAlgDriver_.register_face_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_, edgeNodalGradient_); + + if (realm_.realmUsesEdges_) { + auto& solverAlgMap = solverAlgDriver_->solverAlgorithmMap_; + AssembleElemSolverAlgorithm* elemSolverAlg = nullptr; + bool solverAlgWasBuilt = false; + + std::tie(elemSolverAlg, solverAlgWasBuilt) = + build_or_add_part_to_face_bc_solver_alg( + *this, *part, solverAlgMap, "open"); + + auto& dataPreReqs = elemSolverAlg->dataNeededByKernels_; + auto& activeKernels = elemSolverAlg->activeKernels_; + + build_face_topo_kernel_automatic( + partTopo, *this, activeKernels, "Gamma_open", realm_.meta_data(), + *realm_.solutionOptions_, gamma_, theBcField, dataPreReqs); + } else { + throw std::runtime_error( + "GAMMAEQS: Attempt to use non-NGP element open algorithm"); + } } //-------------------------------------------------------------------------- @@ -395,6 +491,15 @@ GammaEquationSystem::register_wall_bc( nodalGradAlgDriver_.register_face_algorithm( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone, edgeNodalGradient_); + + // non-solver; dwalldistdx; allow for element-based shifted + wallDistGradAlgDriver_.register_face_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_, + edgeNodalGradient_); + + // non-solver; dnDotVdx; allow for element-based shifted + nDotVGradAlgDriver_.register_face_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_, edgeNodalGradient_); } //-------------------------------------------------------------------------- @@ -418,6 +523,15 @@ GammaEquationSystem::register_symmetry_bc( nodalGradAlgDriver_.register_face_algorithm( algType, part, "gamma_nodal_grad", &gammaNp1, &dgamdxNone, edgeNodalGradient_); + + // non-solver; dwalldistdx; allow for element-based shifted + wallDistGradAlgDriver_.register_face_algorithm( + algType, part, "wall_dist_nodal_grad", minDistanceToWall_, dwalldistdx_, + edgeNodalGradient_); + + // non-solver; dnDotVdx; allow for element-based shifted + nDotVGradAlgDriver_.register_face_algorithm( + algType, part, "ndotv_nodal_grad", nDotV_, dnDotVdx_, edgeNodalGradient_); } //-------------------------------------------------------------------------- @@ -473,9 +587,68 @@ GammaEquationSystem::reinitialize_linear_system() void GammaEquationSystem::assemble_nodal_gradient() { + + using MeshIndex = nalu_ngp::NGPMeshTraits<>::MeshIndex; + + const auto& meta = realm_.meta_data(); + const auto& ngpMesh = realm_.ngp_mesh(); + const auto& fieldMgr = realm_.ngp_field_manager(); + const int ndim = meta.spatial_dimension(); + const double timeA = -NaluEnv::self().nalu_time(); nodalGradAlgDriver_.execute(); timerMisc_ += (NaluEnv::self().nalu_time() + timeA); + + // Computation of dV/dy in Eq. 11: gard(n dot V) dot n + // where the V is the velocity vector and n is the wall normal vector + // Step 1 - Calculate the gradient of the wall distance + wallDistGradAlgDriver_.execute(); + + auto& dwalldistdx = + fieldMgr.get_field(dwalldistdx_->mesh_meta_data_ordinal()); + auto& nDotV = fieldMgr.get_field(nDotV_->mesh_meta_data_ordinal()); + const std::string velName = + realm_.does_mesh_move() ? "velocity_rtm" : "velocity"; + auto& vel = fieldMgr.get_field(get_field_ordinal(meta, velName)); + + const stk::mesh::Selector sel = + (meta.locally_owned_part() | meta.globally_shared_part()) & + (stk::mesh::selectField(*dwalldistdx_)); + + dwalldistdx.sync_to_device(); + nDotV.sync_to_device(); + vel.sync_to_device(); + + nalu_ngp::run_entity_algorithm( + "GammaTransition::compute_nDotV", ngpMesh, stk::topology::NODE_RANK, sel, + KOKKOS_LAMBDA(const MeshIndex& mi) { + // Step 2 - Normalize the wall distance gradient + // Calculate a magnitude of the wall distance gradient + double mag_wdg = 0.0; + for (int d = 0; d < ndim; ++d) + mag_wdg += dwalldistdx.get(mi, d) * dwalldistdx.get(mi, d); + mag_wdg = stk::math::sqrt(mag_wdg); + + // Normalize the wall distance gradient vector: computation of n is done + for (int d = 0; d < ndim; ++d) + dwalldistdx.get(mi, d) /= mag_wdg; + + // Step 3 - Calculate the dot product of the wall normal vector and the + // velocity vector + double nDotV_tmp = 0.0; + for (int d = 0; d < ndim; ++d) + nDotV_tmp += dwalldistdx.get(mi, d) * vel.get(mi, d); + nDotV.get(mi, 0) = nDotV_tmp; + }); + + dwalldistdx.modify_on_device(); + nDotV.modify_on_device(); + + // Step 4 - Calculate the gradient of n Dot V + nDotVGradAlgDriver_.execute(); + + // Step 5 - Calculate the dot product of d(n Dot V)dx and n -This will be + // performed inside BLTGammaM2015NodeKernel } //-------------------------------------------------------------------------- diff --git a/src/ShearStressTransportEquationSystem.C b/src/ShearStressTransportEquationSystem.C index c3bef8992..11880d1d9 100644 --- a/src/ShearStressTransportEquationSystem.C +++ b/src/ShearStressTransportEquationSystem.C @@ -573,6 +573,7 @@ ShearStressTransportEquationSystem::compute_f_one_blending() const double betaStar = realm_.get_turb_model_constant(TM_betaStar); const double sigmaWTwo = realm_.get_turb_model_constant(TM_sigmaWTwo); const double CDkwClip = 1.0e-10; // 2003 SST + const auto gammaEqActive = realm_.solutionOptions_->gammaEqActive_; const auto& tkeNp1 = fieldMgr.get_field(tke_->mesh_meta_data_ordinal()); @@ -621,6 +622,16 @@ ShearStressTransportEquationSystem::compute_f_one_blending() fOneBlend.get(mi, 0) = stk::math::tanh(fArgOne * fArgOne * fArgOne * fArgOne); + + // Modifications of f1 blending function for the transition model + if (gammaEqActive) { + const double f1Orig = fOneBlend.get(mi, 0); + const double ry = rho * minD * stk::math::sqrt(tke) / mu; + const double arg = ry / 120.0; + const double f3 = + stk::math::exp(-arg * arg * arg * arg * arg * arg * arg * arg); + fOneBlend.get(mi, 0) = stk::math::max(f1Orig, f3); + } }); fOneBlend.modify_on_device(); diff --git a/src/SolutionOptions.C b/src/SolutionOptions.C index 151389487..5fbb06078 100644 --- a/src/SolutionOptions.C +++ b/src/SolutionOptions.C @@ -586,8 +586,14 @@ SolutionOptions::load(const YAML::Node& y_node) << TurbulenceModelNames[static_cast(turbulenceModel_)] << " " << isTurbulent_ << std::endl; if (gammaEqActive_ == true) { - NaluEnv::self().naluOutputP0() - << "Transition Model is: One Equation Gamma" << std::endl; + if (turbModelConstantMap_[TM_fsti] > 0) { + NaluEnv::self().naluOutputP0() + << "Transition Model is: One Equation Gamma w/ constant Tu" + << std::endl; + } else { + NaluEnv::self().naluOutputP0() + << "Transition Model is: One Equation Gamma w/ local Tu" << std::endl; + } } else { NaluEnv::self().naluOutputP0() << "No Transition Model" << std::endl; } @@ -711,11 +717,7 @@ SolutionOptions::initialize_turbulence_constants() turbModelConstantMap_[TM_sdrAmb] = 0.0; turbModelConstantMap_[TM_avgTimeCoeff] = 1.0; turbModelConstantMap_[TM_alphaInf] = 0.52; - turbModelConstantMap_[TM_caOne] = 2.0; - turbModelConstantMap_[TM_caTwo] = 0.06; - turbModelConstantMap_[TM_ceOne] = 1.0; - turbModelConstantMap_[TM_ceTwo] = 50.0; - turbModelConstantMap_[TM_c0t] = 0.03; + turbModelConstantMap_[TM_fsti] = -1; } double diff --git a/src/SpecificDissipationRateEquationSystem.C b/src/SpecificDissipationRateEquationSystem.C index edf466847..64b14daa6 100644 --- a/src/SpecificDissipationRateEquationSystem.C +++ b/src/SpecificDissipationRateEquationSystem.C @@ -53,6 +53,8 @@ #include #include +#include + // ngp #include "ngp_utils/NgpFieldBLAS.h" #include "ngp_algorithms/NodalGradEdgeAlg.h" @@ -265,37 +267,53 @@ SpecificDissipationRateEquationSystem::register_interior_algorithm( auto& solverAlgMap = solverAlgDriver_->solverAlgMap_; process_ngp_node_kernels( solverAlgMap, realm_, part, this, + [&](AssembleNGPNodeSolverAlgorithm& nodeAlg) { if (!elementMassAlg) nodeAlg.add_kernel(realm_.bulk_data(), sdr_); - - if (TurbulenceModel::SST == realm_.solutionOptions_->turbulenceModel_) { - nodeAlg.add_kernel(realm_.meta_data()); - } else if ( - TurbulenceModel::SSTLR == realm_.solutionOptions_->turbulenceModel_) { - nodeAlg.add_kernel(realm_.meta_data()); - } else if ( - (TurbulenceModel::SST_DES == - realm_.solutionOptions_->turbulenceModel_) || - (TurbulenceModel::SST_IDDES == - realm_.solutionOptions_->turbulenceModel_)) { - nodeAlg.add_kernel(realm_.meta_data()); - } else if ( - TurbulenceModel::SST_AMS == - realm_.solutionOptions_->turbulenceModel_) { - nodeAlg.add_kernel( - realm_.meta_data(), - realm_.solutionOptions_->get_coordinates_name()); - } else if ( - TurbulenceModel::KO == realm_.solutionOptions_->turbulenceModel_) { - nodeAlg.add_kernel(realm_.meta_data()); + if (realm_.solutionOptions_->gammaEqActive_) { + if ( + TurbulenceModel::SST == realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel(realm_.meta_data()); + } else { + throw std::runtime_error( + "Invalid turbulene model: Currently the transition model only " + "works with SST " + + TurbulenceModelNames[static_cast( + realm_.solutionOptions_->turbulenceModel_)]); + } } else { - throw std::runtime_error( - "Invalid turbulence model in SDR equation system: " + - TurbulenceModelNames[static_cast( - realm_.solutionOptions_->turbulenceModel_)]); + if ( + TurbulenceModel::SST == realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel(realm_.meta_data()); + } else if ( + TurbulenceModel::SSTLR == + realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel(realm_.meta_data()); + } else if ( + (TurbulenceModel::SST_DES == + realm_.solutionOptions_->turbulenceModel_) || + (TurbulenceModel::SST_IDDES == + realm_.solutionOptions_->turbulenceModel_)) { + nodeAlg.add_kernel(realm_.meta_data()); + } else if ( + TurbulenceModel::SST_AMS == + realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel( + realm_.meta_data(), + realm_.solutionOptions_->get_coordinates_name()); + } else if ( + TurbulenceModel::KO == realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel(realm_.meta_data()); + } else { + throw std::runtime_error( + "Invalid turbulence model in SDR equation system: " + + TurbulenceModelNames[static_cast( + realm_.solutionOptions_->turbulenceModel_)]); + } } }, + [&](AssembleNGPNodeSolverAlgorithm& nodeAlg, std::string& srcName) { if (srcName == "gcl") { nodeAlg.add_kernel(realm_.bulk_data(), sdr_); diff --git a/src/TurbKineticEnergyEquationSystem.C b/src/TurbKineticEnergyEquationSystem.C index 1075c3242..4389d2d60 100644 --- a/src/TurbKineticEnergyEquationSystem.C +++ b/src/TurbKineticEnergyEquationSystem.C @@ -62,6 +62,8 @@ #include #include +#include + // ngp #include #include @@ -303,7 +305,11 @@ TurbKineticEnergyEquationSystem::register_interior_algorithm( nodeAlg.add_kernel(realm_.meta_data()); break; case TurbulenceModel::SST: - nodeAlg.add_kernel(realm_.meta_data()); + if (!realm_.solutionOptions_->gammaEqActive_) { + nodeAlg.add_kernel(realm_.meta_data()); + } else { + nodeAlg.add_kernel(realm_.meta_data()); + } break; case TurbulenceModel::SSTLR: nodeAlg.add_kernel(realm_.meta_data()); diff --git a/src/node_kernels/BLTGammaM2015NodeKernel.C b/src/node_kernels/BLTGammaM2015NodeKernel.C index 075e2d370..76606b777 100644 --- a/src/node_kernels/BLTGammaM2015NodeKernel.C +++ b/src/node_kernels/BLTGammaM2015NodeKernel.C @@ -27,6 +27,8 @@ BLTGammaM2015NodeKernel::BLTGammaM2015NodeKernel( viscID_(get_field_ordinal(meta, "viscosity")), dudxID_(get_field_ordinal(meta, "dudx")), minDID_(get_field_ordinal(meta, "minimum_distance_to_wall")), + dwalldistdxID_(get_field_ordinal(meta, "dwalldistdx")), + dnDotVdxID_(get_field_ordinal(meta, "dnDotVdx")), dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), gamintID_(get_field_ordinal(meta, "gamma_transition")), nDim_(meta.spatial_dimension()) @@ -44,16 +46,12 @@ BLTGammaM2015NodeKernel::setup(Realm& realm) visc_ = fieldMgr.get_field(viscID_); dudx_ = fieldMgr.get_field(dudxID_); minD_ = fieldMgr.get_field(minDID_); + dwalldistdx_ = fieldMgr.get_field(dwalldistdxID_); + dnDotVdx_ = fieldMgr.get_field(dnDotVdxID_); dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); gamint_ = fieldMgr.get_field(gamintID_); - // Update transition model constants - caOne_ = realm.get_turb_model_constant(TM_caOne); - caTwo_ = realm.get_turb_model_constant(TM_caTwo); - ceOne_ = realm.get_turb_model_constant(TM_ceOne); - ceTwo_ = realm.get_turb_model_constant(TM_ceTwo); - timeStepCount = realm.get_time_step_count(); - maxStepCount = realm.get_max_time_step_count(); + fsti_ = realm.get_turb_model_constant(TM_fsti); } KOKKOS_FUNCTION @@ -101,30 +99,25 @@ BLTGammaM2015NodeKernel::execute( const DblType minD = minD_.get(node, 0); const DblType dVol = dualNodalVolume_.get(node, 0); - // define the wall normal vector (for now, hardwire to NASA TM case: z = wall - // norm direction) - DblType Re0c = 0.0; - DblType flength = 100.0; - DblType Rev = 0.0; - DblType rt = 0.0; DblType dvnn = 0.0; DblType TuL = 0.0; DblType lamda0L = 0.0; - DblType fonset = 0.0; - DblType fonset1 = 0.0; - DblType fonset2 = 0.0; - DblType fonset3 = 0.0; - DblType fturb = 0.0; - DblType sijMag = 0.0; DblType vortMag = 0.0; - DblType Ctu1 = 100.; - DblType Ctu2 = 1000.; - DblType Ctu3 = 1.0; + // constants for the source terms + const DblType flength = 100.0; + const DblType caTwo = 0.06; + const DblType ceTwo = 50.0; + + // constants for the local-correlations + const DblType Ctu1 = 100.; + const DblType Ctu2 = 1000.; + const DblType Ctu3 = 1.0; for (int i = 0; i < nDim_; ++i) { + dvnn += dwalldistdx_.get(node, i) * dnDotVdx_.get(node, i); for (int j = 0; j < nDim_; ++j) { const double duidxj = dudx_.get(node, nDim_ * i + j); const double dujdxi = dudx_.get(node, nDim_ * j + i); @@ -139,31 +132,56 @@ BLTGammaM2015NodeKernel::execute( sijMag = stk::math::sqrt(2.0 * sijMag); vortMag = stk::math::sqrt(2.0 * vortMag); - TuL = stk::math::min( - 81.6496580927726 * stk::math::sqrt(tke) / sdr / (minD + 1.0e-10), 100.0); + if (fsti_ > 0.0) { + TuL = fsti_; // const. Tu from yaml + } else { + TuL = stk::math::min( + 100.0 * stk::math::sqrt(2.0 / 3.0 * tke) / sdr / (minD + 1.0e-10), + 100.0); // local Tu + } + lamda0L = -7.57e-3 * dvnn * minD * minD * density / visc + 0.0128; lamda0L = stk::math::min(stk::math::max(lamda0L, -1.0), 1.0); - Re0c = Ctu1 + Ctu2 * stk::math::exp(-Ctu3 * TuL * FPG(lamda0L)); - Rev = density * minD * minD * sijMag / visc; - fonset1 = Rev / 2.2 / Re0c; - fonset2 = stk::math::min(fonset1, 2.0); - rt = density * tke / sdr / visc; - fonset3 = stk::math::max(1.0 - 0.0233236151603499 * rt * rt * rt, 0.0); - fonset = stk::math::max(fonset2 - fonset3, 0.0); - fturb = stk::math::exp(-rt * rt * rt * rt / 16.0); - - DblType Pgamma = - flength * density * sijMag * fonset * gamint * (1.0 - gamint); - DblType Dgamma = - -caTwo_ * density * vortMag * fturb * gamint * (ceTwo_ * gamint - 1.0); - DblType PgammaDir = - flength * density * sijMag * fonset * (1.0 - 2.0 * gamint); - DblType DgammaDir = - -caTwo_ * density * vortMag * fturb * (2.0 * ceTwo_ * gamint - 1.0); - - rhs(0) += (Pgamma + Dgamma) * dVol; - lhs(0, 0) -= (PgammaDir + DgammaDir) * dVol; + const DblType Re0c = Ctu1 + Ctu2 * stk::math::exp(-Ctu3 * TuL * FPG(lamda0L)); + const DblType Rev = density * minD * minD * sijMag / visc; + const DblType fonset1 = Rev / 2.2 / Re0c; + const DblType fonset2 = stk::math::min(fonset1, 2.0); + const DblType rt = density * tke / sdr / visc; + const DblType fonset3 = + stk::math::max(1.0 - stk::math::pow(rt / 3.5, 3), 0.0); + const DblType fonset = stk::math::max(fonset2 - fonset3, 0.0); + const DblType fturb = stk::math::exp(-rt * rt * rt * rt / 16.0); + + const DblType Pgamma = + flength * density * sijMag * fonset * gamint * (1.0 - gamint); + const DblType Dgamma = + caTwo * density * vortMag * fturb * gamint * (ceTwo * gamint - 1.0); + + // Exact Jacobian + // const DblType PgammaDir = + // flength * density * sijMag * fonset * (1.0 - 2.0 * gamint); + // const DblType DgammaDir = + // caTwo * density * vortMag * fturb * (2.0 * ceTwo * gamint - 1.0); + // + // rhs(0) += (Pgamma - Dgamma) * dVol; + // lhs(0, 0) += (DgammaDir - PgammaDir) * dVol; + + // Jacobian with the Positivity in the implicit operator + const DblType PgammaDir = + flength * density * sijMag * fonset * (1.0 - gamint); + const DblType PgammaDirP = -flength * density * sijMag * fonset; + + const DblType DgammaDir = + caTwo * density * vortMag * fturb * (ceTwo * gamint - 1.0); + const DblType DgammaDirP = caTwo * density * vortMag * fturb * ceTwo; + + const DblType gamma_pos1 = stk::math::max(DgammaDir - PgammaDir, 0.0); + const DblType gamma_pos2 = stk::math::max(DgammaDirP - PgammaDirP, 0.0); + + rhs(0) += (Pgamma - Dgamma) * dVol; + lhs(0, 0) += (gamma_pos1 + gamma_pos2 * gamint) * dVol; + // } } // namespace nalu diff --git a/src/node_kernels/CMakeLists.txt b/src/node_kernels/CMakeLists.txt index 822a003df..0436e7e4a 100644 --- a/src/node_kernels/CMakeLists.txt +++ b/src/node_kernels/CMakeLists.txt @@ -31,6 +31,8 @@ target_sources(nalu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/SDRSSTDESNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/WallDistNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/BLTGammaM2015NodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/TKESSTBLTM2015NodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/SDRSSTBLTM2015NodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/VOFGclNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/VOFMassBDFNodeKernel.C ) diff --git a/src/node_kernels/SDRSSTBLTM2015NodeKernel.C b/src/node_kernels/SDRSSTBLTM2015NodeKernel.C new file mode 100644 index 000000000..b2ce0c3bd --- /dev/null +++ b/src/node_kernels/SDRSSTBLTM2015NodeKernel.C @@ -0,0 +1,166 @@ +// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS), National Renewable Energy Laboratory, University of Texas Austin, +// Northwest Research Associates. Under the terms of Contract DE-NA0003525 +// with NTESS, the U.S. Government retains certain rights in this software. +// +// This software is released under the BSD 3-clause license. See LICENSE file +// for more details. +// + +#include "node_kernels/SDRSSTBLTM2015NodeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "SimdInterface.h" +#include "utils/StkHelpers.h" + +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +SDRSSTBLTM2015NodeKernel::SDRSSTBLTM2015NodeKernel( + const stk::mesh::MetaData& meta) + : NGPNodeKernel(), + tkeID_(get_field_ordinal(meta, "turbulent_ke")), + sdrID_(get_field_ordinal(meta, "specific_dissipation_rate")), + densityID_(get_field_ordinal(meta, "density")), + tviscID_(get_field_ordinal(meta, "turbulent_viscosity")), + dudxID_(get_field_ordinal(meta, "dudx")), + dkdxID_(get_field_ordinal(meta, "dkdx")), + dwdxID_(get_field_ordinal(meta, "dwdx")), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + fOneBlendID_(get_field_ordinal(meta, "sst_f_one_blending")), + nDim_(meta.spatial_dimension()) +{ +} + +void +SDRSSTBLTM2015NodeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + + tke_ = fieldMgr.get_field(tkeID_); + sdr_ = fieldMgr.get_field(sdrID_); + density_ = fieldMgr.get_field(densityID_); + tvisc_ = fieldMgr.get_field(tviscID_); + dudx_ = fieldMgr.get_field(dudxID_); + dkdx_ = fieldMgr.get_field(dkdxID_); + dwdx_ = fieldMgr.get_field(dwdxID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + fOneBlend_ = fieldMgr.get_field(fOneBlendID_); + + // Update turbulence model constants + betaStar_ = realm.get_turb_model_constant(TM_betaStar); + tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); + sigmaWTwo_ = realm.get_turb_model_constant(TM_sigmaWTwo); + betaOne_ = realm.get_turb_model_constant(TM_betaOne); + betaTwo_ = realm.get_turb_model_constant(TM_betaTwo); + gammaOne_ = realm.get_turb_model_constant(TM_gammaOne); + gammaTwo_ = realm.get_turb_model_constant(TM_gammaTwo); + sdrAmb_ = realm.get_turb_model_constant(TM_sdrAmb); + + lengthScaleLimiter_ = realm.solutionOptions_->lengthScaleLimiter_; + if (lengthScaleLimiter_) { + const NodeKernelTraits::DblType earthAngularVelocity = + realm.solutionOptions_->earthAngularVelocity_; + const NodeKernelTraits::DblType pi = std::acos(-1.0); + const NodeKernelTraits::DblType latitude = + realm.solutionOptions_->latitude_ * pi / 180.0; + corfac_ = 2.0 * earthAngularVelocity * std::sin(latitude); + referenceVelocity_ = realm.solutionOptions_->referenceVelocity_; + } +} + +KOKKOS_FUNCTION +void +SDRSSTBLTM2015NodeKernel::execute( + NodeKernelTraits::LhsType& lhs, + NodeKernelTraits::RhsType& rhs, + const stk::mesh::FastMeshIndex& node) +{ + using DblType = NodeKernelTraits::DblType; + + const DblType tke = tke_.get(node, 0); + const DblType sdr = sdr_.get(node, 0); + const DblType density = density_.get(node, 0); + const DblType tvisc = tvisc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + const DblType fOneBlend = fOneBlend_.get(node, 0); + + DblType crossDiff = 0.0; + + DblType sijMag = 0.0; + DblType vortMag = 0.0; + + for (int i = 0; i < nDim_; ++i) { + crossDiff += dkdx_.get(node, i) * dwdx_.get(node, i); + const int offset = nDim_ * i; + for (int j = 0; j < nDim_; ++j) { + const double duidxj = dudx_.get(node, nDim_ * i + j); + const double dujdxi = dudx_.get(node, nDim_ * j + i); + + const double rateOfStrain = 0.5 * (duidxj + dujdxi); + const double vortTensor = 0.5 * (duidxj - dujdxi); + sijMag += rateOfStrain * rateOfStrain; + vortMag += vortTensor * vortTensor; + } + } + sijMag = stk::math::sqrt(2.0 * sijMag); + vortMag = stk::math::sqrt(2.0 * vortMag); + + // Pk based on Kato-Launder formulation + const DblType Pk = tvisc * sijMag * vortMag; + + // Blend constants for SDR + const DblType omf1 = (1.0 - fOneBlend); + const DblType beta = fOneBlend * betaOne_ + omf1 * betaTwo_; + const DblType gamma = fOneBlend * gammaOne_ + omf1 * gammaTwo_; + const DblType sigmaD = 2.0 * omf1 * sigmaWTwo_; + + DblType gammaOne_apply; + DblType gammaTwo_apply; + // apply limiter to gamma + if (lengthScaleLimiter_) { + // calculate mixing length + const DblType l_t = + stk::math::sqrt(tke) / (stk::math::pow(betaStar_, .25) * sdr); + + // calculate maximum mixing length + // the proportionality constant (.00027) was found by fitting to + // measurements of atmospheric conditions as described in ref. Kob13 + const DblType l_e = .00027 * referenceVelocity_ / corfac_; + + // apply limiter to cEpsOne -> calculate gammaOne + const DblType cEpsOne_one = gammaOne_ + 1.; + const DblType cEpsTwo_one = betaOne_ / betaStar_ + 1.; + const DblType cEpsOneStar_one = + cEpsOne_one + (cEpsTwo_one - cEpsOne_one) * (l_t / l_e); + gammaOne_apply = cEpsOneStar_one - 1.; + + // apply limiter to cEpsTwo -> calculate gammaTwo + const DblType cEpsOne_two = gammaTwo_ + 1.; + const DblType cEpsTwo_two = betaTwo_ / betaStar_ + 1.; + const DblType cEpsOneStar_two = + cEpsOne_two + (cEpsTwo_two - cEpsOne_two) * (l_t / l_e); + gammaTwo_apply = cEpsOneStar_two - 1.; + } else { + gammaOne_apply = gammaOne_; + gammaTwo_apply = gammaTwo_; + } + + // Production term with appropriate clipping of tvisc + const DblType Pw = gamma * density * Pk / stk::math::max(tvisc, 1.0e-16); + const DblType Dw = beta * density * sdr * sdr; + const DblType Sw = sigmaD * density * crossDiff / sdr; + + // SUST source term + const DblType Dwamb = beta * density * sdrAmb_ * sdrAmb_; + + rhs(0) += (Pw - Dw + Dwamb + Sw) * dVol; + lhs(0, 0) += + (2.0 * beta * density * sdr + stk::math::max(Sw / sdr, 0.0)) * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/TKESSTBLTM2015NodeKernel.C b/src/node_kernels/TKESSTBLTM2015NodeKernel.C new file mode 100644 index 000000000..11a0756ce --- /dev/null +++ b/src/node_kernels/TKESSTBLTM2015NodeKernel.C @@ -0,0 +1,124 @@ +// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS), National Renewable Energy Laboratory, University of Texas Austin, +// Northwest Research Associates. Under the terms of Contract DE-NA0003525 +// with NTESS, the U.S. Government retains certain rights in this software. +// +// This software is released under the BSD 3-clause license. See LICENSE file +// for more details. +// + +#include "node_kernels/TKESSTBLTM2015NodeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "SimdInterface.h" +#include "utils/StkHelpers.h" + +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +TKESSTBLTM2015NodeKernel::TKESSTBLTM2015NodeKernel( + const stk::mesh::MetaData& meta) + : NGPNodeKernel(), + tkeID_(get_field_ordinal(meta, "turbulent_ke")), + sdrID_(get_field_ordinal(meta, "specific_dissipation_rate")), + densityID_(get_field_ordinal(meta, "density")), + tviscID_(get_field_ordinal(meta, "turbulent_viscosity")), + dudxID_(get_field_ordinal(meta, "dudx")), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + gamintID_(get_field_ordinal(meta, "gamma_transition")), + viscID_(get_field_ordinal(meta, "viscosity")), + wallDistID_(get_field_ordinal(meta, "minimum_distance_to_wall")), + nDim_(meta.spatial_dimension()) +{ +} + +void +TKESSTBLTM2015NodeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + + tke_ = fieldMgr.get_field(tkeID_); + sdr_ = fieldMgr.get_field(sdrID_); + density_ = fieldMgr.get_field(densityID_); + tvisc_ = fieldMgr.get_field(tviscID_); + dudx_ = fieldMgr.get_field(dudxID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + gamint_ = fieldMgr.get_field(gamintID_); + visc_ = fieldMgr.get_field(viscID_); + wallDist_ = fieldMgr.get_field(wallDistID_); + + // Update turbulence model constants + betaStar_ = realm.get_turb_model_constant(TM_betaStar); + tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); + tkeAmb_ = realm.get_turb_model_constant(TM_tkeAmb); + sdrAmb_ = realm.get_turb_model_constant(TM_sdrAmb); +} + +KOKKOS_FUNCTION +void +TKESSTBLTM2015NodeKernel::execute( + NodeKernelTraits::LhsType& lhs, + NodeKernelTraits::RhsType& rhs, + const stk::mesh::FastMeshIndex& node) +{ + using DblType = NodeKernelTraits::DblType; + + // See https://turbmodels.larc.nasa.gov/sst.html for details + + const DblType tke = tke_.get(node, 0); + const DblType sdr = sdr_.get(node, 0); + const DblType density = density_.get(node, 0); + const DblType tvisc = tvisc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + + const DblType gamint = gamint_.get(node, 0); + const DblType visc = visc_.get(node, 0); + const DblType dw = wallDist_.get(node, 0); + + const DblType Ck_BLT = 1.0; + const DblType CSEP = 1.0; + const DblType Retclim = 1100.0; + + DblType sijMag = 1.0e-16; + DblType vortMag = 1.0e-16; + + for (int i = 0; i < nDim_; ++i) { + for (int j = 0; j < nDim_; ++j) { + const double duidxj = dudx_.get(node, nDim_ * i + j); + const double dujdxi = dudx_.get(node, nDim_ * j + i); + + const double rateOfStrain = 0.5 * (duidxj + dujdxi); + const double vortTensor = 0.5 * (duidxj - dujdxi); + + sijMag += rateOfStrain * rateOfStrain; + vortMag += vortTensor * vortTensor; + } + } + + sijMag = stk::math::sqrt(2.0 * sijMag); + vortMag = stk::math::sqrt(2.0 * vortMag); + + const DblType Rev = density * dw * dw * sijMag / visc; + const DblType Fonlim = + stk::math::min(stk::math::max(Rev / 2.2 / Retclim - 1.0, 0.0), 3.0); + + // Pk based on Kato-Launder formulation + const DblType Pk = gamint * tvisc * sijMag * vortMag; + const DblType Pklim = + 5.0 * Ck_BLT * stk::math::max(gamint - 0.2, 0.0) * (1.0 - gamint) * Fonlim * + stk::math::max(3.0 * CSEP * visc - tvisc, 0.0) * sijMag * vortMag; + const DblType Dk = + betaStar_ * density * sdr * tke * stk::math::max(gamint, 0.1); + + // SUST source term + const DblType Dkamb = betaStar_ * density * sdrAmb_ * tkeAmb_; + + rhs(0) += (Pk + Pklim - Dk + Dkamb) * dVol; + lhs(0, 0) += betaStar_ * density * sdr * stk::math::max(gamint, 0.1) * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/unit_tests/kernels/UnitTestKernelUtils.C b/unit_tests/kernels/UnitTestKernelUtils.C index 1dbc8c54a..bdb7c564b 100644 --- a/unit_tests/kernels/UnitTestKernelUtils.C +++ b/unit_tests/kernels/UnitTestKernelUtils.C @@ -158,6 +158,57 @@ struct TrigFieldFunction std::sin(a * pi * z)); } + void gamma_intermittency(const double* coords, double* qField) const + { + double x = coords[0]; + double y = coords[1]; + double z = coords[2]; + + // Range should be from 0.02 to 1.0 + qField[0] = + gamma_intermittencynot + + abs(std::cos(a * pi * x) * std::sin(a * pi * y) * std::sin(a * pi * z)) / + (1.0 - gamma_intermittencynot); + } + + void dwalldistdx(const double* coords, double* qField) const + { + const double x = coords[0]; + const double y = coords[1]; + const double z = coords[2]; + + const double a_pi = a * pi; + const double cosx = std::cos(a_pi * x); + const double sinx = std::sin(a_pi * x); + const double cosy = std::cos(a_pi * y); + const double siny = std::sin(a_pi * y); + const double cosz = std::cos(a_pi * z); + const double sinz = std::sin(a_pi * z); + + qField[0] = -dwalldistdxnot * a_pi * sinx * siny * cosz; + qField[1] = dwalldistdxnot * a_pi * cosx * cosy * cosz; + qField[2] = -dwalldistdxnot * a_pi * cosx * siny * sinz; + } + + void dnDotVdx(const double* coords, double* qField) const + { + const double x = coords[0]; + const double y = coords[1]; + const double z = coords[2]; + + const double a_pi = a * pi; + const double cosx = std::cos(a_pi * x); + const double sinx = std::sin(a_pi * x); + const double cosy = std::cos(a_pi * y); + const double siny = std::sin(a_pi * y); + const double cosz = std::cos(a_pi * z); + const double sinz = std::sin(a_pi * z); + + qField[0] = -dnDotVdxnot * a_pi * sinx * siny * cosz; + qField[1] = dnDotVdxnot * a_pi * cosx * cosy * cosz; + qField[2] = -dnDotVdxnot * a_pi * cosx * siny * sinz; + } + void tdr(const double* coords, double* qField) const { double x = coords[0]; @@ -290,6 +341,15 @@ private: /// Factor for sdr field static constexpr double sdrnot{1.0}; + /// Factor for gamma_intermittency field + static constexpr double gamma_intermittencynot{0.02}; + + /// Factor for dwalldistdx field + static constexpr double dwalldistdxnot{1.0}; + + /// Factor for dnDotVdx field + static constexpr double dnDotVdxnot{1.0}; + /// Factor for tdr field static constexpr double tdrnot{1.0}; @@ -343,6 +403,12 @@ init_trigonometric_field( funcPtr = &TrigFieldFunction::dkdx; else if (fieldName == "specific_dissipation_rate") funcPtr = &TrigFieldFunction::sdr; + else if (fieldName == "gamma_transition") + funcPtr = &TrigFieldFunction::gamma_intermittency; + else if (fieldName == "dwalldistdx") + funcPtr = &TrigFieldFunction::dwalldistdx; + else if (fieldName == "dnDotVdx") + funcPtr = &TrigFieldFunction::dnDotVdx; else if (fieldName == "total_dissipation_rate") funcPtr = &TrigFieldFunction::tdr; else if (fieldName == "dwdx") @@ -498,6 +564,33 @@ sdr_test_function( init_trigonometric_field(bulk, coordinates, sdr); } +void +gamma_intermittency_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::ScalarFieldType& gamma_intermittency) +{ + init_trigonometric_field(bulk, coordinates, gamma_intermittency); +} + +void +dwalldistdx_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::VectorFieldType& dwalldistdx) +{ + init_trigonometric_field(bulk, coordinates, dwalldistdx); +} + +void +dnDotVdx_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::VectorFieldType& dnDotVdx) +{ + init_trigonometric_field(bulk, coordinates, dnDotVdx); +} + void tdr_test_function( const stk::mesh::BulkData& bulk, diff --git a/unit_tests/kernels/UnitTestKernelUtils.h b/unit_tests/kernels/UnitTestKernelUtils.h index 1919ea237..6eeaa4caa 100644 --- a/unit_tests/kernels/UnitTestKernelUtils.h +++ b/unit_tests/kernels/UnitTestKernelUtils.h @@ -83,6 +83,21 @@ void sdr_test_function( const sierra::nalu::VectorFieldType& coordinates, sierra::nalu::ScalarFieldType& sdr); +void gamma_intermittency_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::ScalarFieldType& gamma_intermittency); + +void dwalldistdx_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::VectorFieldType& dwalldistdx); + +void dnDotVdx_test_function( + const stk::mesh::BulkData& bulk, + const sierra::nalu::VectorFieldType& coordinates, + sierra::nalu::VectorFieldType& dnDotVdx); + void tdr_test_function( const stk::mesh::BulkData& bulk, const sierra::nalu::VectorFieldType& coordinates, @@ -731,6 +746,12 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh &meta_->declare_field(stk::topology::NODE_RANK, "viscosity")), tvisc_(&meta_->declare_field( stk::topology::NODE_RANK, "turbulent_viscosity")), + gamma_intermittency_(&meta_->declare_field( + stk::topology::NODE_RANK, "gamma_transition")), + dwalldistdx_( + &meta_->declare_field(stk::topology::NODE_RANK, "dwalldistdx")), + dnDotVdx_( + &meta_->declare_field(stk::topology::NODE_RANK, "dnDotVdx")), maxLengthScale_(&meta_->declare_field( stk::topology::NODE_RANK, "sst_max_length_scale")), minDistance_(&meta_->declare_field( @@ -759,6 +780,8 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh stk::mesh::put_field_on_mesh(*sdrbc_, meta_->universal_part(), nullptr); stk::mesh::put_field_on_mesh(*visc_, meta_->universal_part(), nullptr); stk::mesh::put_field_on_mesh(*tvisc_, meta_->universal_part(), nullptr); + stk::mesh::put_field_on_mesh( + *gamma_intermittency_, meta_->universal_part(), nullptr); stk::mesh::put_field_on_mesh( *maxLengthScale_, meta_->universal_part(), nullptr); stk::mesh::put_field_on_mesh( @@ -776,6 +799,14 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh stk::mesh::put_field_on_mesh( *dwdx_, meta_->universal_part(), spatialDim_, nullptr); stk::io::set_field_output_type(*dwdx_, stk::io::FieldOutputType::VECTOR_3D); + stk::mesh::put_field_on_mesh( + *dwalldistdx_, meta_->universal_part(), spatialDim_, nullptr); + stk::io::set_field_output_type( + *dwalldistdx_, stk::io::FieldOutputType::VECTOR_3D); + stk::mesh::put_field_on_mesh( + *dnDotVdx_, meta_->universal_part(), spatialDim_, nullptr); + stk::io::set_field_output_type( + *dnDotVdx_, stk::io::FieldOutputType::VECTOR_3D); double initOpenMassFlowRate[sierra::nalu::AlgTraitsQuad4::numScsIp_]; for (int i = 0; i < sierra::nalu::AlgTraitsQuad4::numScsIp_; ++i) { initOpenMassFlowRate[i] = 10.0; @@ -807,6 +838,8 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh *bulk_, *coordinates_, *density_); unit_test_kernel_utils::tke_test_function(*bulk_, *coordinates_, *tke_); unit_test_kernel_utils::sdr_test_function(*bulk_, *coordinates_, *sdr_); + unit_test_kernel_utils::gamma_intermittency_test_function( + *bulk_, *coordinates_, *gamma_intermittency_); unit_test_kernel_utils::minimum_distance_to_wall_test_function( *bulk_, *coordinates_, *minDistance_); unit_test_kernel_utils::sst_f_one_blending_test_function( @@ -817,6 +850,8 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh stk::mesh::field_fill(0.0, *dkdx_); stk::mesh::field_fill(0.0, *dwdx_); stk::mesh::field_fill(0.0, *pecletFactor_); + stk::mesh::field_fill(0.0, *dwalldistdx_); + stk::mesh::field_fill(0.0, *dnDotVdx_); } sierra::nalu::ScalarFieldType* tke_{nullptr}; @@ -825,6 +860,7 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh sierra::nalu::ScalarFieldType* sdrbc_{nullptr}; sierra::nalu::ScalarFieldType* visc_{nullptr}; sierra::nalu::ScalarFieldType* tvisc_{nullptr}; + sierra::nalu::ScalarFieldType* gamma_intermittency_{nullptr}; sierra::nalu::ScalarFieldType* maxLengthScale_{nullptr}; sierra::nalu::ScalarFieldType* minDistance_{nullptr}; sierra::nalu::ScalarFieldType* fOneBlend_{nullptr}; @@ -838,6 +874,8 @@ class SSTKernelHex8Mesh : public LowMachKernelHex8Mesh sierra::nalu::ScalarFieldType* sdrWallArea_{nullptr}; sierra::nalu::GenericFieldType* wallFricVel_{nullptr}; sierra::nalu::ScalarFieldType* pecletFactor_{nullptr}; + sierra::nalu::VectorFieldType* dwalldistdx_{nullptr}; + sierra::nalu::VectorFieldType* dnDotVdx_{nullptr}; }; /** Test Fixture for the KE Kernels diff --git a/unit_tests/node_kernels/CMakeLists.txt b/unit_tests/node_kernels/CMakeLists.txt index fc7537960..41f9f5f77 100644 --- a/unit_tests/node_kernels/CMakeLists.txt +++ b/unit_tests/node_kernels/CMakeLists.txt @@ -19,4 +19,5 @@ target_sources(${utest_ex_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/UnitTestKONodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/UnitTestKsgsNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/UnitTestWallDistNode.C + ${CMAKE_CURRENT_SOURCE_DIR}/UnitTestBLTGammaM2015NodeKernel.C ) diff --git a/unit_tests/node_kernels/UnitTestBLTGammaM2015NodeKernel.C b/unit_tests/node_kernels/UnitTestBLTGammaM2015NodeKernel.C new file mode 100644 index 000000000..c7ae735cc --- /dev/null +++ b/unit_tests/node_kernels/UnitTestBLTGammaM2015NodeKernel.C @@ -0,0 +1,143 @@ +// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS), National Renewable Energy Laboratory, University of Texas Austin, +// Northwest Research Associates. Under the terms of Contract DE-NA0003525 +// with NTESS, the U.S. Government retains certain rights in this software. +// +// This software is released under the BSD 3-clause license. See LICENSE file +// for more details. +// + +#include "kernels/UnitTestKernelUtils.h" +#include "UnitTestUtils.h" +#include "UnitTestHelperObjects.h" + +#include "node_kernels/BLTGammaM2015NodeKernel.h" + +namespace { +namespace hex8_golds { +namespace blt_gamma { +static constexpr double rhs[8] = { + 0, 0, 0, 0.12823826807242, 0, 0, -0.043287170452808, 0.43035793150449, +}; + +static constexpr double lhs[8][8] = { + { + 1.5336779974765e-19, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 4.6113433001562e-05, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 6.4413186123242e-11, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.13131235277404, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 7.8452858117332e-05, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.001645541661088, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.12774384574574, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.7648927575084, + }, +}; +} // namespace blt_gamma + +} // namespace hex8_golds +} // namespace + +TEST_F(SSTKernelHex8Mesh, NGP_blt_gamma_node) +{ + // Only execute for 1 processor runs + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + // Setup solution options + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::NodeHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 1, partVec_[0]); + + helperObjs.nodeAlg->add_kernel(*meta_); + + helperObjs.execute(); + + Kokkos::deep_copy( + helperObjs.linsys->hostNumSumIntoCalls_, + helperObjs.linsys->numSumIntoCalls_); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->hostNumSumIntoCalls_(0), 8u); + + namespace hex8_golds = hex8_golds::blt_gamma; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<8>( + helperObjs.linsys->lhs_, hex8_golds::lhs, 1.0e-12); +} diff --git a/unit_tests/node_kernels/UnitTestSSTNodeKernel.C b/unit_tests/node_kernels/UnitTestSSTNodeKernel.C index 823f5272a..e548d9381 100644 --- a/unit_tests/node_kernels/UnitTestSSTNodeKernel.C +++ b/unit_tests/node_kernels/UnitTestSSTNodeKernel.C @@ -15,9 +15,11 @@ #include "node_kernels/TKESSTLRNodeKernel.h" #include "node_kernels/TKESSTDESNodeKernel.h" #include "node_kernels/TKESSTIDDESNodeKernel.h" +#include "node_kernels/TKESSTBLTM2015NodeKernel.h" #include "node_kernels/SDRSSTNodeKernel.h" #include "node_kernels/SDRSSTLRNodeKernel.h" #include "node_kernels/SDRSSTDESNodeKernel.h" +#include "node_kernels/SDRSSTBLTM2015NodeKernel.h" namespace { namespace hex8_golds { @@ -408,6 +410,97 @@ static constexpr double rhs[8] = { }; } // namespace tke_sst_des_sust +namespace tke_sst_trans { +static constexpr double rhs[8] = { + -0.004499999980007, -0.0026450336235646, -0.0037149722043966, + -0.0013217844303503, -0.0026450336153232, -0.0015547117509048, + -0.017568942314324, 0.0073065228754648, +}; + +static constexpr double lhs[8][8] = { + { + 0.00225, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.0013225168176581, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.0013225168176581, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.00077735588132818, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.0013225168176581, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.00077735588132818, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.0070970479374154, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0022476729243034, + }, +}; +} // namespace tke_sst_trans + namespace sdr_sst { static constexpr double rhs[8] = { -0.0414, @@ -717,6 +810,102 @@ static constexpr double rhs[8] = { }; } // namespace sdr_sst_des_sust +namespace sdr_sst_trans { +static constexpr double rhs[8] = { + -0.0414, + -0.024334309444908, + -0.024334309444908, + 0.00096369609149651, + -0.024334309444908, + -0.013421452431681, + -0.025196833148802, + -0.0016391627843042, +}; + +static constexpr double lhs[8][8] = { + { + 0.0414, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.024334309444908, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.024334309444908, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.014303348216439, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.024334309444908, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.013421452431681, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.018984179689384, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.0096611889086056, + }, +}; +} // namespace sdr_sst_trans + } // namespace hex8_golds } // namespace @@ -936,6 +1125,42 @@ TEST_F(SSTKernelHex8Mesh, NGP_tke_sst_des_sust_node) helperObjs.linsys->lhs_, hex8_golds::tke_sst_des::lhs, 1.0e-12); } +TEST_F(SSTKernelHex8Mesh, NGP_tke_sst_trans_node) +{ + // Only execute for 1 processor runs + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + // Setup solution options + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::NodeHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 1, partVec_[0]); + + helperObjs.nodeAlg->add_kernel( + *meta_); + + helperObjs.execute(); + + Kokkos::deep_copy( + helperObjs.linsys->hostNumSumIntoCalls_, + helperObjs.linsys->numSumIntoCalls_); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->hostNumSumIntoCalls_(0), 8u); + + namespace hex8_golds = hex8_golds::tke_sst_trans; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<8>( + helperObjs.linsys->lhs_, hex8_golds::lhs, 1.0e-12); +} + TEST_F(SSTKernelHex8Mesh, NGP_sdr_sst_node) { // Only execute for 1 processor runs @@ -1118,3 +1343,39 @@ TEST_F(SSTKernelHex8Mesh, NGP_sdr_sst_des_sust_node) unit_test_kernel_utils::expect_all_near<8>( helperObjs.linsys->lhs_, hex8_golds::sdr_sst_des::lhs, 1.0e-12); } + +TEST_F(SSTKernelHex8Mesh, NGP_sdr_sst_trans_node) +{ + // Only execute for 1 processor runs + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + // Setup solution options + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::NodeHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 1, partVec_[0]); + + helperObjs.nodeAlg->add_kernel( + *meta_); + + helperObjs.execute(); + + Kokkos::deep_copy( + helperObjs.linsys->hostNumSumIntoCalls_, + helperObjs.linsys->numSumIntoCalls_); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->hostNumSumIntoCalls_(0), 8u); + + namespace hex8_golds = hex8_golds::sdr_sst_trans; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<8>( + helperObjs.linsys->lhs_, hex8_golds::lhs, 1.0e-12); +}