diff --git a/include/AMSAlgDriver.h b/include/AMSAlgDriver.h index 14442e642..6ed3ea257 100644 --- a/include/AMSAlgDriver.h +++ b/include/AMSAlgDriver.h @@ -15,7 +15,11 @@ #include "ngp_algorithms/NgpAlgDriver.h" #include "ngp_algorithms/FieldUpdateAlgDriver.h" #include "ngp_algorithms/AMSAvgMdotEdgeAlg.h" +#include "ngp_algorithms/AMSAveragesAlg.h" #include "ngp_algorithms/SSTAMSAveragesAlg.h" +#include "ngp_algorithms/SSTLRAMSAveragesAlg.h" +#include "ngp_algorithms/KEAMSAveragesAlg.h" +#include "ngp_algorithms/KOAMSAveragesAlg.h" namespace stk { struct topology; @@ -62,8 +66,15 @@ class AMSAlgDriver ScalarFieldType* avgMdot_; VectorFieldType* forcingComp_; + ScalarFieldType* magPM_; + ScalarFieldType* PMmax_; + ScalarFieldType* PM1_; + ScalarFieldType* PM2_; + ScalarFieldType* PM3_; + FieldUpdateAlgDriver metricTensorAlgDriver_; - std::unique_ptr avgAlg_; + std::unique_ptr avgAlg_; + NgpAlgDriver avgMdotAlg_; const TurbulenceModel turbulenceModel_; diff --git a/include/Enums.h b/include/Enums.h index e54bc29cc..c612c84fe 100644 --- a/include/Enums.h +++ b/include/Enums.h @@ -166,16 +166,19 @@ enum class TurbulenceModel { SSTLR, SST_DES, SST_AMS, + SSTLR_AMS, SST_IDDES, KE, + KE_AMS, KO, + KO_AMS, TurbulenceModel_END }; // matching string name index into above enums (must match PERFECTLY) static const std::string TurbulenceModelNames[] = { - "laminar", "ksgs", "smagorinsky", "wale", "sst", "sstlr", - "sst_des", "sst_ams", "sst_iddes", "ke", "ko"}; + "laminar", "ksgs", "smagorinsky", "wale", "sst", "sstlr", "sst_des", + "sst_ams", "sstlr_ams", "sst_iddes", "ke", "ke_ams", "ko", "ko_ams"}; enum TurbulenceModelConstant { TM_cMu = 0, @@ -238,18 +241,21 @@ enum TurbulenceModelConstant { TM_fOne = 57, TM_sigmaK = 58, TM_sigmaEps = 59, - TM_sstLRDestruct = 60, - TM_sstLRProd = 61, - TM_tkeAmb = 62, - 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_alphaPow = 60, + TM_alphaScaPow = 61, + TM_coeffR = 62, + TM_sstLRDestruct = 63, + TM_sstLRProd = 64, + TM_tkeAmb = 65, + TM_sdrAmb = 66, + TM_avgTimeCoeff = 67, + TM_alphaInf = 68, + TM_caOne = 69, + TM_caTwo = 70, + TM_ceOne = 71, + TM_ceTwo = 72, + TM_c0t = 73, + TM_END = 74 }; static const std::string TurbulenceModelConstantNames[] = { @@ -313,6 +319,9 @@ static const std::string TurbulenceModelConstantNames[] = { "fOne", "sigmaK", "sigmaEps", + "alphaPow", + "alphaScaPow", + "coeffR", "sstLRDestruct", "sstLRProd", "tke_amb", diff --git a/include/Realm.h b/include/Realm.h index 047253238..b36b0d9fe 100644 --- a/include/Realm.h +++ b/include/Realm.h @@ -319,6 +319,8 @@ class Realm bool is_turbulent(); void is_turbulent(bool isIt); + bool is_ams_model(); + bool needs_enthalpy(); void needs_enthalpy(bool needsEnthalpy); diff --git a/include/SolutionOptions.h b/include/SolutionOptions.h index 6dde276fc..2156fbf0d 100644 --- a/include/SolutionOptions.h +++ b/include/SolutionOptions.h @@ -124,6 +124,7 @@ class SolutionOptions bool mdotInterpRhoUTogether_; bool solveIncompressibleContinuity_; bool isTurbulent_; + bool isAMSModel_; TurbulenceModel turbulenceModel_; bool meshMotion_; bool meshTransformation_; diff --git a/include/edge_kernels/MomentumKEAMSDiffEdgeKernel.h b/include/edge_kernels/MomentumKEAMSDiffEdgeKernel.h new file mode 100644 index 000000000..2f4573046 --- /dev/null +++ b/include/edge_kernels/MomentumKEAMSDiffEdgeKernel.h @@ -0,0 +1,90 @@ +// 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 MOMENTUMKEAMSDIFFEDGEKERNEL_H +#define MOMENTUMKEAMSDIFFEDGEKERNEL_H + +#include "edge_kernels/EdgeKernel.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 SolutionOptions; + +class MomentumKEAMSDiffEdgeKernel + : public NGPEdgeKernel +{ +public: + MomentumKEAMSDiffEdgeKernel( + const stk::mesh::BulkData&, const SolutionOptions&); + + MomentumKEAMSDiffEdgeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~MomentumKEAMSDiffEdgeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + EdgeKernelTraits::ShmemDataType&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField edgeAreaVec_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField velocity_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tdr_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField nodalMij_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField avgVelocity_; + stk::mesh::NgpField avgDudx_; + stk::mesh::NgpField avgResAdeq_; + + unsigned edgeAreaVecID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned velocityID_{stk::mesh::InvalidOrdinal}; + unsigned turbViscID_{stk::mesh::InvalidOrdinal}; + unsigned densityNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tdrNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned MijID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; + + const double includeDivU_; + + const double betaStar_; + const double CMdeg_; + const double aspectRatioSwitch_; + const double alphaPow_; + const double alphaScaPow_; + + const int nDim_; + + double relaxFacU_{1.0}; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* MOMENTUMKEAMSDIFFEDGEKERNEL_H */ diff --git a/include/edge_kernels/MomentumKOAMSDiffEdgeKernel.h b/include/edge_kernels/MomentumKOAMSDiffEdgeKernel.h new file mode 100644 index 000000000..72989a1b6 --- /dev/null +++ b/include/edge_kernels/MomentumKOAMSDiffEdgeKernel.h @@ -0,0 +1,94 @@ +// 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 MOMENTUMKOAMSDIFFEDGEKERNEL_H +#define MOMENTUMKOAMSDIFFEDGEKERNEL_H + +#include "edge_kernels/EdgeKernel.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 SolutionOptions; + +class MomentumKOAMSDiffEdgeKernel + : public NGPEdgeKernel +{ +public: + MomentumKOAMSDiffEdgeKernel( + const stk::mesh::BulkData&, const SolutionOptions&); + + MomentumKOAMSDiffEdgeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~MomentumKOAMSDiffEdgeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + EdgeKernelTraits::ShmemDataType&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField edgeAreaVec_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField velocity_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField visc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField sdr_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField nodalMij_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField avgVelocity_; + stk::mesh::NgpField avgDudx_; + stk::mesh::NgpField avgResAdeq_; + + unsigned edgeAreaVecID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned velocityID_{stk::mesh::InvalidOrdinal}; + unsigned turbViscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned densityNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tkeNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned sdrNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned MijID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; + + const double includeDivU_; + + const double betaStar_; + const double CMdeg_; + const double aspectRatioSwitch_; + const double alphaPow_; + const double alphaScaPow_; + + const int nDim_; + + double relaxFacU_{1.0}; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* MOMENTUMKOAMSDIFFEDGEKERNEL_H */ diff --git a/include/edge_kernels/MomentumSSTAMSDiffEdgeKernel.h b/include/edge_kernels/MomentumSSTAMSDiffEdgeKernel.h index e39c46136..08b4e37d5 100644 --- a/include/edge_kernels/MomentumSSTAMSDiffEdgeKernel.h +++ b/include/edge_kernels/MomentumSSTAMSDiffEdgeKernel.h @@ -78,6 +78,8 @@ class MomentumSSTAMSDiffEdgeKernel const double betaStar_; const double CMdeg_; const double aspectRatioSwitch_; + const double alphaPow_; + const double alphaScaPow_; const int nDim_; diff --git a/include/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h b/include/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h new file mode 100644 index 000000000..629e5088a --- /dev/null +++ b/include/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h @@ -0,0 +1,96 @@ +// 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 MOMENTUMSSTLRAMSDIFFEDGEKERNEL_H +#define MOMENTUMSSTLRAMSDIFFEDGEKERNEL_H + +#include "edge_kernels/EdgeKernel.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 SolutionOptions; + +class MomentumSSTLRAMSDiffEdgeKernel + : public NGPEdgeKernel +{ +public: + MomentumSSTLRAMSDiffEdgeKernel( + const stk::mesh::BulkData&, const SolutionOptions&); + + MomentumSSTLRAMSDiffEdgeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~MomentumSSTLRAMSDiffEdgeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + EdgeKernelTraits::ShmemDataType&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField edgeAreaVec_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField velocity_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField visc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField sdr_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField nodalMij_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField avgVelocity_; + stk::mesh::NgpField avgDudx_; + stk::mesh::NgpField avgResAdeq_; + stk::mesh::NgpField fOneBlend_; + + unsigned edgeAreaVecID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned velocityID_{stk::mesh::InvalidOrdinal}; + unsigned turbViscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned densityNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tkeNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned sdrNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned MijID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxID_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; + unsigned fOneBlendID_{stk::mesh::InvalidOrdinal}; + + const double includeDivU_; + + const double betaStar_; + const double CMdeg_; + const double aspectRatioSwitch_; + const double alphaPow_; + const double alphaScaPow_; + + const int nDim_; + + double relaxFacU_{1.0}; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* MOMENTUMSSTLRAMSDIFFEDGEKERNEL_H */ diff --git a/include/ngp_algorithms/AMSAveragesAlg.h b/include/ngp_algorithms/AMSAveragesAlg.h new file mode 100644 index 000000000..1d932a260 --- /dev/null +++ b/include/ngp_algorithms/AMSAveragesAlg.h @@ -0,0 +1,38 @@ +// 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 AMSAveragesAlg_h +#define AMSAveragesAlg_h + +#include "Algorithm.h" +#include "FieldTypeDef.h" + +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class AMSAveragesAlg : public Algorithm +{ +public: + using DblType = double; + + AMSAveragesAlg(Realm& realm, stk::mesh::Part* part); + + virtual ~AMSAveragesAlg() = default; + + virtual void execute() = 0; +}; + +} // namespace nalu +} // namespace sierra + +#endif diff --git a/include/ngp_algorithms/KEAMSAveragesAlg.h b/include/ngp_algorithms/KEAMSAveragesAlg.h new file mode 100644 index 000000000..b2ab6ce6c --- /dev/null +++ b/include/ngp_algorithms/KEAMSAveragesAlg.h @@ -0,0 +1,74 @@ +// 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 KEAMSAveragesAlg_h +#define KEAMSAveragesAlg_h + +#include "AMSAveragesAlg.h" +#include "FieldTypeDef.h" + +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class KEAMSAveragesAlg : public AMSAveragesAlg +{ +public: + using DblType = double; + + KEAMSAveragesAlg(Realm& realm, stk::mesh::Part* part); + + virtual ~KEAMSAveragesAlg() = default; + + virtual void execute() override; + +private: + const DblType CMdeg_; + const DblType v2cMu_; + const DblType aspectRatioSwitch_; + const DblType alphaPow_; + const DblType alphaScaPow_; + const DblType coeffR_; + const bool meshMotion_; + + unsigned velocity_{stk::mesh::InvalidOrdinal}; + unsigned density_{stk::mesh::InvalidOrdinal}; + unsigned dudx_{stk::mesh::InvalidOrdinal}; + unsigned resAdeq_{stk::mesh::InvalidOrdinal}; + unsigned turbKineticEnergy_{stk::mesh::InvalidOrdinal}; + unsigned totDissipationRate_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocity_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityN_{stk::mesh::InvalidOrdinal}; + unsigned avgDudx_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxN_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeRes_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeResN_{stk::mesh::InvalidOrdinal}; + unsigned avgProd_{stk::mesh::InvalidOrdinal}; + unsigned avgProdN_{stk::mesh::InvalidOrdinal}; + unsigned avgTime_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeq_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqN_{stk::mesh::InvalidOrdinal}; + unsigned tvisc_{stk::mesh::InvalidOrdinal}; + unsigned visc_{stk::mesh::InvalidOrdinal}; + unsigned beta_{stk::mesh::InvalidOrdinal}; + unsigned Mij_{stk::mesh::InvalidOrdinal}; + unsigned wallDist_{stk::mesh::InvalidOrdinal}; + + // Proper definition of beta_kol in SST-AMS doesn't work + // near walls, so emprically tested floor is used currently + static constexpr double beta_kol = 0.01; +}; + +} // namespace nalu +} // namespace sierra + +#endif diff --git a/include/ngp_algorithms/KOAMSAveragesAlg.h b/include/ngp_algorithms/KOAMSAveragesAlg.h new file mode 100644 index 000000000..196072f3d --- /dev/null +++ b/include/ngp_algorithms/KOAMSAveragesAlg.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 KOAMSAveragesAlg_h +#define KOAMSAveragesAlg_h + +#include "AMSAveragesAlg.h" +#include "FieldTypeDef.h" + +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class KOAMSAveragesAlg : public AMSAveragesAlg +{ +public: + using DblType = double; + + KOAMSAveragesAlg(Realm& realm, stk::mesh::Part* part); + + virtual ~KOAMSAveragesAlg() = default; + + virtual void execute() override; + +private: + const DblType betaStar_; + const DblType CMdeg_; + const DblType v2cMu_; + const DblType aspectRatioSwitch_; + const DblType alphaPow_; + const DblType alphaScaPow_; + const DblType coeffR_; + const bool meshMotion_; + + unsigned velocity_{stk::mesh::InvalidOrdinal}; + unsigned density_{stk::mesh::InvalidOrdinal}; + unsigned dudx_{stk::mesh::InvalidOrdinal}; + unsigned resAdeq_{stk::mesh::InvalidOrdinal}; + unsigned turbKineticEnergy_{stk::mesh::InvalidOrdinal}; + unsigned specDissipationRate_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocity_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityN_{stk::mesh::InvalidOrdinal}; + unsigned avgDudx_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxN_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeRes_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeResN_{stk::mesh::InvalidOrdinal}; + unsigned avgProd_{stk::mesh::InvalidOrdinal}; + unsigned avgProdN_{stk::mesh::InvalidOrdinal}; + unsigned avgTime_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeq_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqN_{stk::mesh::InvalidOrdinal}; + unsigned tvisc_{stk::mesh::InvalidOrdinal}; + unsigned visc_{stk::mesh::InvalidOrdinal}; + unsigned beta_{stk::mesh::InvalidOrdinal}; + unsigned Mij_{stk::mesh::InvalidOrdinal}; + unsigned wallDist_{stk::mesh::InvalidOrdinal}; + + // Proper definition of beta_kol in SST-AMS doesn't work + // near walls, so emprically tested floor is used currently + static constexpr double beta_kol = 0.01; +}; + +} // namespace nalu +} // namespace sierra + +#endif diff --git a/include/ngp_algorithms/SSTAMSAveragesAlg.h b/include/ngp_algorithms/SSTAMSAveragesAlg.h index 3594b4b68..529afb8ba 100644 --- a/include/ngp_algorithms/SSTAMSAveragesAlg.h +++ b/include/ngp_algorithms/SSTAMSAveragesAlg.h @@ -10,7 +10,7 @@ #ifndef SSTAMSAveragesAlg_h #define SSTAMSAveragesAlg_h -#include "Algorithm.h" +#include "AMSAveragesAlg.h" #include "FieldTypeDef.h" #include "stk_mesh/base/Types.hpp" @@ -20,7 +20,7 @@ namespace nalu { class Realm; -class SSTAMSAveragesAlg : public Algorithm +class SSTAMSAveragesAlg : public AMSAveragesAlg { public: using DblType = double; @@ -37,6 +37,9 @@ class SSTAMSAveragesAlg : public Algorithm const DblType v2cMu_; const DblType aspectRatioSwitch_; const DblType avgTimeCoeff_; + const DblType alphaPow_; + const DblType alphaScaPow_; + const DblType coeffR_; const bool meshMotion_; const bool RANSBelowKs_; const DblType z0_; diff --git a/include/ngp_algorithms/SSTLRAMSAveragesAlg.h b/include/ngp_algorithms/SSTLRAMSAveragesAlg.h new file mode 100644 index 000000000..8769ae097 --- /dev/null +++ b/include/ngp_algorithms/SSTLRAMSAveragesAlg.h @@ -0,0 +1,82 @@ +// 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 SSTLRAMSAveragesAlg_h +#define SSTLRAMSAveragesAlg_h + +#include "AMSAveragesAlg.h" +#include "FieldTypeDef.h" + +#include "stk_mesh/base/Types.hpp" + +namespace sierra { +namespace nalu { + +class Realm; + +class SSTLRAMSAveragesAlg : public AMSAveragesAlg +{ +public: + using DblType = double; + + SSTLRAMSAveragesAlg(Realm& realm, stk::mesh::Part* part); + + virtual ~SSTLRAMSAveragesAlg() = default; + + virtual void execute() override; + +private: + const DblType betaStar_; + const DblType CMdeg_; + const DblType v2cMu_; + const DblType aspectRatioSwitch_; + const DblType alphaPow_; + const DblType alphaScaPow_; + const DblType coeffR_; + const bool meshMotion_; + + unsigned velocity_{stk::mesh::InvalidOrdinal}; + unsigned density_{stk::mesh::InvalidOrdinal}; + unsigned dudx_{stk::mesh::InvalidOrdinal}; + unsigned resAdeq_{stk::mesh::InvalidOrdinal}; + unsigned turbKineticEnergy_{stk::mesh::InvalidOrdinal}; + unsigned specDissipationRate_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocity_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityN_{stk::mesh::InvalidOrdinal}; + unsigned avgDudx_{stk::mesh::InvalidOrdinal}; + unsigned avgDudxN_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeRes_{stk::mesh::InvalidOrdinal}; + unsigned avgTkeResN_{stk::mesh::InvalidOrdinal}; + unsigned avgProd_{stk::mesh::InvalidOrdinal}; + unsigned avgProdN_{stk::mesh::InvalidOrdinal}; + unsigned avgTime_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeq_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqN_{stk::mesh::InvalidOrdinal}; + unsigned fOneBlend_{stk::mesh::InvalidOrdinal}; + unsigned tvisc_{stk::mesh::InvalidOrdinal}; + unsigned visc_{stk::mesh::InvalidOrdinal}; + unsigned beta_{stk::mesh::InvalidOrdinal}; + unsigned Mij_{stk::mesh::InvalidOrdinal}; + unsigned wallDist_{stk::mesh::InvalidOrdinal}; + + unsigned magPM_{stk::mesh::InvalidOrdinal}; + unsigned PMmax_{stk::mesh::InvalidOrdinal}; + unsigned PM1_{stk::mesh::InvalidOrdinal}; + unsigned PM2_{stk::mesh::InvalidOrdinal}; + unsigned PM3_{stk::mesh::InvalidOrdinal}; + + // Proper definition of beta_kol in SSTLR-AMS doesn't work + // near walls, so emprically tested floor is used currently + static constexpr double beta_kol = 0.01; +}; + +} // namespace nalu +} // namespace sierra + +#endif diff --git a/include/node_kernels/MomentumKEAMSForcingNodeKernel.h b/include/node_kernels/MomentumKEAMSForcingNodeKernel.h new file mode 100644 index 000000000..dcb3bb307 --- /dev/null +++ b/include/node_kernels/MomentumKEAMSForcingNodeKernel.h @@ -0,0 +1,98 @@ +// 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 MOMENTUMKEAMSFORCINGNODEKERNEL_H +#define MOMENTUMKEAMSFORCINGNODEKERNEL_H + +#include "node_kernels/NodeKernel.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 SolutionOptions; + +class MomentumKEAMSForcingNodeKernel + : public NGPNodeKernel +{ +public: + MomentumKEAMSForcingNodeKernel( + const stk::mesh::BulkData&, const SolutionOptions&); + + MomentumKEAMSForcingNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~MomentumKEAMSForcingNodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField dualNodalVolume_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField velocity_; + stk::mesh::NgpField viscosity_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField tdr_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField Mij_; + stk::mesh::NgpField minDist_; + stk::mesh::NgpField avgVelocity_; + stk::mesh::NgpField avgTime_; + stk::mesh::NgpField avgResAdeq_; + stk::mesh::NgpField forcingComp_; + + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned velocityID_{stk::mesh::InvalidOrdinal}; + unsigned viscosityID_{stk::mesh::InvalidOrdinal}; + unsigned turbViscID_{stk::mesh::InvalidOrdinal}; + unsigned densityNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tkeNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tdrNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned MijID_{stk::mesh::InvalidOrdinal}; + unsigned minDistID_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; + unsigned forcingCompID_{stk::mesh::InvalidOrdinal}; + + const double betaStar_; + const double forceCl_; + const double Ceta_; + const double Ct_; + const double blT_; + const double blKol_; + const double forceFactor_; + const double cMu_; + const double periodicForcingLengthX_; + const double periodicForcingLengthY_; + const double periodicForcingLengthZ_; + const int nDim_; + + double time_; + double dt_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* MOMENTUMKEAMSFORCINGNODEKERNEL_H */ diff --git a/include/node_kernels/MomentumKOAMSForcingNodeKernel.h b/include/node_kernels/MomentumKOAMSForcingNodeKernel.h new file mode 100644 index 000000000..a3b8dc026 --- /dev/null +++ b/include/node_kernels/MomentumKOAMSForcingNodeKernel.h @@ -0,0 +1,98 @@ +// 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 MOMENTUMKOAMSFORCINGNODEKERNEL_H +#define MOMENTUMKOAMSFORCINGNODEKERNEL_H + +#include "node_kernels/NodeKernel.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 SolutionOptions; + +class MomentumKOAMSForcingNodeKernel + : public NGPNodeKernel +{ +public: + MomentumKOAMSForcingNodeKernel( + const stk::mesh::BulkData&, const SolutionOptions&); + + MomentumKOAMSForcingNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~MomentumKOAMSForcingNodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField dualNodalVolume_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField velocity_; + stk::mesh::NgpField viscosity_; + stk::mesh::NgpField tvisc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField sdr_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField Mij_; + stk::mesh::NgpField minDist_; + stk::mesh::NgpField avgVelocity_; + stk::mesh::NgpField avgTime_; + stk::mesh::NgpField avgResAdeq_; + stk::mesh::NgpField forcingComp_; + + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned velocityID_{stk::mesh::InvalidOrdinal}; + unsigned viscosityID_{stk::mesh::InvalidOrdinal}; + unsigned turbViscID_{stk::mesh::InvalidOrdinal}; + unsigned densityNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned tkeNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned sdrNp1ID_{stk::mesh::InvalidOrdinal}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned MijID_{stk::mesh::InvalidOrdinal}; + unsigned minDistID_{stk::mesh::InvalidOrdinal}; + unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; + unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; + unsigned forcingCompID_{stk::mesh::InvalidOrdinal}; + + const double betaStar_; + const double forceCl_; + const double Ceta_; + const double Ct_; + const double blT_; + const double blKol_; + const double forceFactor_; + const double v2cMu_; + const double periodicForcingLengthX_; + const double periodicForcingLengthY_; + const double periodicForcingLengthZ_; + const int nDim_; + + double time_; + double dt_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* MOMENTUMKOAMSFORCINGNODEKERNEL_H */ diff --git a/include/node_kernels/MomentumSSTAMSForcingNodeKernel.h b/include/node_kernels/MomentumSSTAMSForcingNodeKernel.h index 9c3b896c3..7018d26f9 100644 --- a/include/node_kernels/MomentumSSTAMSForcingNodeKernel.h +++ b/include/node_kernels/MomentumSSTAMSForcingNodeKernel.h @@ -10,6 +10,8 @@ #ifndef MOMENTUMSSTAMSFORCINGNODEKERNEL_H #define MOMENTUMSSTAMSFORCINGNODEKERNEL_H +#include "Enums.h" + #include "node_kernels/NodeKernel.h" #include "stk_mesh/base/BulkData.hpp" @@ -62,6 +64,7 @@ class MomentumSSTAMSForcingNodeKernel stk::mesh::NgpField avgTime_; stk::mesh::NgpField avgResAdeq_; stk::mesh::NgpField forcingComp_; + stk::mesh::NgpField fOneBlend_; unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; @@ -77,7 +80,9 @@ class MomentumSSTAMSForcingNodeKernel unsigned avgVelocityID_{stk::mesh::InvalidOrdinal}; unsigned avgResAdeqID_{stk::mesh::InvalidOrdinal}; unsigned forcingCompID_{stk::mesh::InvalidOrdinal}; + unsigned fOneBlendID_{stk::mesh::InvalidOrdinal}; + const TurbulenceModel turbModel_; const double betaStar_; const double forceCl_; const double Ceta_; diff --git a/include/node_kernels/SDRKOAMSNodeKernel.h b/include/node_kernels/SDRKOAMSNodeKernel.h new file mode 100644 index 000000000..d57057071 --- /dev/null +++ b/include/node_kernels/SDRKOAMSNodeKernel.h @@ -0,0 +1,81 @@ +// 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 SDRKOAMSNODEKERNEL_H +#define SDRKOAMSNODEKERNEL_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 SDRKOAMSNodeKernel : public NGPNodeKernel +{ +public: + SDRKOAMSNodeKernel(const stk::mesh::MetaData&); + + SDRKOAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~SDRKOAMSNodeKernel() = 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 visc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField dkdx_; + stk::mesh::NgpField dwdx_; + stk::mesh::NgpField prod_; + stk::mesh::NgpField dualNodalVolume_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned dkdxID_{stk::mesh::InvalidOrdinal}; + unsigned dwdxID_{stk::mesh::InvalidOrdinal}; + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType sigmaWTwo_; + NodeKernelTraits::DblType betaOne_; + NodeKernelTraits::DblType betaTwo_; + NodeKernelTraits::DblType gammaOne_; + NodeKernelTraits::DblType gammaTwo_; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* SDRKOAMSNODEKERNEL_H */ diff --git a/include/node_kernels/SDRSSTAMSNodeKernel.h b/include/node_kernels/SDRSSTAMSNodeKernel.h index 7c8ee4258..9b9f0ebb7 100644 --- a/include/node_kernels/SDRSSTAMSNodeKernel.h +++ b/include/node_kernels/SDRSSTAMSNodeKernel.h @@ -79,6 +79,7 @@ class SDRSSTAMSNodeKernel : public NGPNodeKernel NodeKernelTraits::DblType referenceVelocity_; NodeKernelTraits::DblType gammaOne_; NodeKernelTraits::DblType gammaTwo_; + NodeKernelTraits::DblType sdrAmb_; }; } // namespace nalu diff --git a/include/node_kernels/SDRSSTLRAMSNodeKernel.h b/include/node_kernels/SDRSSTLRAMSNodeKernel.h new file mode 100644 index 000000000..e314d0c76 --- /dev/null +++ b/include/node_kernels/SDRSSTLRAMSNodeKernel.h @@ -0,0 +1,89 @@ +// 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 SDRSSTLRAMSNODEKERNEL_H +#define SDRSSTLRAMSNODEKERNEL_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 SDRSSTLRAMSNodeKernel : public NGPNodeKernel +{ +public: + SDRSSTLRAMSNodeKernel(const stk::mesh::MetaData&, const std::string); + + SDRSSTLRAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~SDRSSTLRAMSNodeKernel() = 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 visc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField dkdx_; + stk::mesh::NgpField dwdx_; + stk::mesh::NgpField dualNodalVolume_; + stk::mesh::NgpField fOneBlend_; + stk::mesh::NgpField beta_; + stk::mesh::NgpField prod_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{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}; + unsigned betaID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType alphaInf_; + NodeKernelTraits::DblType sigmaWTwo_; + NodeKernelTraits::DblType betaOne_; + NodeKernelTraits::DblType betaTwo_; + NodeKernelTraits::DblType gammaOne_; + NodeKernelTraits::DblType gammaTwo_; + NodeKernelTraits::DblType sstLRDestruct_; + NodeKernelTraits::DblType sstLRProd_; + NodeKernelTraits::DblType sdrAmb_; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* SDRSSTLRAMSNODEKERNEL_H */ diff --git a/include/node_kernels/SDRSSTLRNodeKernel.h b/include/node_kernels/SDRSSTLRNodeKernel.h index a4f955d8d..91e94096a 100644 --- a/include/node_kernels/SDRSSTLRNodeKernel.h +++ b/include/node_kernels/SDRSSTLRNodeKernel.h @@ -66,6 +66,7 @@ class SDRSSTLRNodeKernel : public NGPNodeKernel NodeKernelTraits::DblType betaStar_; NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType alphaInf_; NodeKernelTraits::DblType sigmaWTwo_; NodeKernelTraits::DblType betaOne_; NodeKernelTraits::DblType betaTwo_; diff --git a/include/node_kernels/TDRKEAMSNodeKernel.h b/include/node_kernels/TDRKEAMSNodeKernel.h new file mode 100644 index 000000000..12e593570 --- /dev/null +++ b/include/node_kernels/TDRKEAMSNodeKernel.h @@ -0,0 +1,74 @@ +// 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 TDRKEAMSNODEKERNEL_H +#define TDRKEAMSNODEKERNEL_H + +#include "node_kernels/NodeKernel.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 SolutionOptions; + +class TDRKEAMSNodeKernel : public NGPNodeKernel +{ +public: + TDRKEAMSNodeKernel(const stk::mesh::MetaData&, const std::string); + + TDRKEAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~TDRKEAMSNodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField dualNodalVolume_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField visc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField tdr_; + stk::mesh::NgpField prod_; + stk::mesh::NgpField dplus_; + stk::mesh::NgpField wallDist_; + + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned tdrID_{stk::mesh::InvalidOrdinal}; + unsigned dplusID_{stk::mesh::InvalidOrdinal}; + unsigned wallDistID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType cEpsOne_; + NodeKernelTraits::DblType cEpsTwo_; + NodeKernelTraits::DblType fOne_; + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* TDRKEAMSNODEKERNEL_H */ diff --git a/include/node_kernels/TKEKEAMSNodeKernel.h b/include/node_kernels/TKEKEAMSNodeKernel.h new file mode 100644 index 000000000..60fabea9d --- /dev/null +++ b/include/node_kernels/TKEKEAMSNodeKernel.h @@ -0,0 +1,69 @@ +// 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 TKEKEAMSNODEKERNEL_H +#define TKEKEAMSNODEKERNEL_H + +#include "node_kernels/NodeKernel.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 SolutionOptions; + +class TKEKEAMSNodeKernel : public NGPNodeKernel +{ +public: + TKEKEAMSNodeKernel(const stk::mesh::MetaData&, const std::string); + + TKEKEAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~TKEKEAMSNodeKernel() = default; + + virtual void setup(Realm&) override; + + KOKKOS_FUNCTION + virtual void execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType&, + const stk::mesh::FastMeshIndex&) override; + +private: + stk::mesh::NgpField dualNodalVolume_; + + stk::mesh::NgpField coordinates_; + stk::mesh::NgpField visc_; + stk::mesh::NgpField density_; + stk::mesh::NgpField tke_; + stk::mesh::NgpField tdr_; + stk::mesh::NgpField prod_; + stk::mesh::NgpField wallDist_; + + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned coordinatesID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned tdrID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned wallDistID_{stk::mesh::InvalidOrdinal}; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* TKEKEAMSNODEKERNEL_H */ diff --git a/include/node_kernels/TKEKOAMSNodeKernel.h b/include/node_kernels/TKEKOAMSNodeKernel.h new file mode 100644 index 000000000..df5d4e415 --- /dev/null +++ b/include/node_kernels/TKEKOAMSNodeKernel.h @@ -0,0 +1,71 @@ +// 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 TKEKOAMSNODEKERNEL_H +#define TKEKOAMSNODEKERNEL_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 TKEKOAMSNodeKernel : public NGPNodeKernel +{ +public: + TKEKOAMSNodeKernel(const stk::mesh::MetaData&); + + TKEKOAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~TKEKOAMSNodeKernel() = 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 visc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField dualNodalVolume_; + stk::mesh::NgpField prod_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* TKEKOAMSNODEKERNEL_H */ diff --git a/include/node_kernels/TKESSTAMSNodeKernel.h b/include/node_kernels/TKESSTAMSNodeKernel.h index 722dca908..2ce1c1e18 100644 --- a/include/node_kernels/TKESSTAMSNodeKernel.h +++ b/include/node_kernels/TKESSTAMSNodeKernel.h @@ -62,6 +62,8 @@ class TKESSTAMSNodeKernel : public NGPNodeKernel NodeKernelTraits::DblType betaStar_; NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType tkeAmb_; + NodeKernelTraits::DblType sdrAmb_; const int nDim_; }; diff --git a/include/node_kernels/TKESSTLRAMSNodeKernel.h b/include/node_kernels/TKESSTLRAMSNodeKernel.h new file mode 100644 index 000000000..8f135aebf --- /dev/null +++ b/include/node_kernels/TKESSTLRAMSNodeKernel.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 TKESSTLRAMSNODEKERNEL_H +#define TKESSTLRAMSNODEKERNEL_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 TKESSTLRAMSNodeKernel : public NGPNodeKernel +{ +public: + TKESSTLRAMSNodeKernel(const stk::mesh::MetaData&, const std::string); + + TKESSTLRAMSNodeKernel() = delete; + + KOKKOS_DEFAULTED_FUNCTION + virtual ~TKESSTLRAMSNodeKernel() = 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 visc_; + stk::mesh::NgpField dudx_; + stk::mesh::NgpField fOneBlend_; + stk::mesh::NgpField dualNodalVolume_; + stk::mesh::NgpField prod_; + + unsigned tkeID_{stk::mesh::InvalidOrdinal}; + unsigned sdrID_{stk::mesh::InvalidOrdinal}; + unsigned densityID_{stk::mesh::InvalidOrdinal}; + unsigned tviscID_{stk::mesh::InvalidOrdinal}; + unsigned viscID_{stk::mesh::InvalidOrdinal}; + unsigned dudxID_{stk::mesh::InvalidOrdinal}; + unsigned fOneBlendID_{stk::mesh::InvalidOrdinal}; + unsigned dualNodalVolumeID_{stk::mesh::InvalidOrdinal}; + unsigned prodID_{stk::mesh::InvalidOrdinal}; + + NodeKernelTraits::DblType betaStar_; + NodeKernelTraits::DblType tkeProdLimitRatio_; + NodeKernelTraits::DblType tkeAmb_; + NodeKernelTraits::DblType sdrAmb_; + + const int nDim_; +}; + +} // namespace nalu +} // namespace sierra + +#endif /* TKESSTLRAMSNODEKERNEL_H */ diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index 33b6afca5..1937601d0 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -224,6 +224,9 @@ if(NOT ENABLE_CUDA AND NOT ENABLE_ROCM) add_test_r(KEChannelEdge 4) add_test_r(IDDESPeriodicHillEdge 4) add_test_r_rst(SSTAMSChannelEdge 4) + add_test_r_rst(SSTLRAMSChannelEdge 4) + add_test_r_rst(KOAMSChannelEdge 4) + add_test_r_rst(KEAMSChannelEdge 4) #add_test_r_rst(SSTAMSOversetRotCylinder 2) add_test_r(SSTChannelEdge 4) add_test_r(SSTLRChannelEdge 4) diff --git a/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge.yaml b/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge.yaml new file mode 100644 index 000000000..15abd1887 --- /dev/null +++ b/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge.yaml @@ -0,0 +1,200 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: ../../mesh/periodicChannel.g + use_edges: yes + check_for_missing_bcs: yes + automatic_decomposition_type: rcb + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + total_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-8 + + - LowMachEOM: + name: myLowMach + max_iterations: 1 + convergence_tolerance: 1e-8 + + - ChienKEpsilon: + name: myKE + max_iterations: 1 + convergence_tolerance: 1e-8 + + initial_conditions: + - constant: ic_1 + target_name: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.0005 + total_dissipation_rate: 0.0005 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: ke + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + total_dissipation_rate: 0.0 + + - noc_correction: + pressure: yes + + - limiter: + pressure: no + velocity: yes + turbulent_ke: yes + total_dissipation_rate: yes + + - projected_nodal_gradient: + velocity: element + pressure: element + turbulent_ke: element + total_dissipation_rate: element + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: KEAMSChannelEdge.rst + restart_frequency: 10 + restart_start: 0 + + output: + output_data_base_name: KEAMSChannelEdge.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - total_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - element_courant + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 10 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge_rst.yaml b/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge_rst.yaml new file mode 100644 index 000000000..901a252b5 --- /dev/null +++ b/reg_tests/test_files/KEAMSChannelEdge/KEAMSChannelEdge_rst.yaml @@ -0,0 +1,220 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: KEAMSChannelEdge.rst + use_edges: yes + check_for_missing_bcs: yes + support_inconsistent_multi_state_restart: yes + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + total_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-8 + + - LowMachEOM: + name: myLowMach + max_iterations: 1 + convergence_tolerance: 1e-8 + + - ChienKEpsilon: + name: myKE + max_iterations: 1 + convergence_tolerance: 1e-8 + + initial_conditions: + - constant: ic_1 + target_name: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.0005 + total_dissipation_rate: 0.0005 + average_velocity: [22.78,0.0,0.0] + average_tke_resolved: 0.0 + average_dudx: 0.0 + k_ratio: 1.0 + avg_res_adequacy_parameter: 1.0 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: ke_ams + reset_AMS_averages_on_init: true + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + total_dissipation_rate: 0.0 + + - noc_correction: + pressure: yes + + - limiter: + pressure: no + velocity: yes + turbulent_ke: yes + total_dissipation_rate: yes + + - projected_nodal_gradient: + velocity: element + pressure: element + turbulent_ke: element + total_dissipation_rate: element + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + total_dissipation_rate: 1.0 + + - turbulence_model_constants: + forcingFactor: 32.0 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: KEAMSChannelEdge-ams.rst + restart_frequency: 10 + restart_start: 0 + restart_time: 100 + + output: + output_data_base_name: KEAMSChannelEdge-ams.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - average_velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - total_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - k_ratio + - rans_time_scale + - average_mass_flow_rate + - average_tke_resolved + - avg_res_adequacy_parameter + - resolution_adequacy_parameter + - metric_tensor + - element_courant + - average_production + - average_dudx + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 20 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge.yaml b/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge.yaml new file mode 100644 index 000000000..36326ef27 --- /dev/null +++ b/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge.yaml @@ -0,0 +1,203 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: ../../mesh/periodicChannel.g + use_edges: yes + check_for_missing_bcs: yes + automatic_decomposition_type: rcb + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + specific_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-8 + + - LowMachEOM: + name: myLowMach + max_iterations: 1 + convergence_tolerance: 1e-8 + + - WilcoxKOmega: + name: myKO + max_iterations: 1 + convergence_tolerance: 1e-8 + + initial_conditions: + - constant: ic_1 + target_name: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.05 + specific_dissipation_rate: 3528.0 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: ko + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + specific_dissipation_rate: 0.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 + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - turbulence_model_constants: + SDRWallFactor: 0.625 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: KOAMSChannelEdge.rst + restart_frequency: 10 + restart_start: 0 + + output: + output_data_base_name: KOAMSChannelEdge.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - specific_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - element_courant + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 10 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge_rst.yaml b/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge_rst.yaml new file mode 100644 index 000000000..6be7d7558 --- /dev/null +++ b/reg_tests/test_files/KOAMSChannelEdge/KOAMSChannelEdge_rst.yaml @@ -0,0 +1,221 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: KOAMSChannelEdge.rst + use_edges: yes + check_for_missing_bcs: yes + support_inconsistent_multi_state_restart: yes + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + specific_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-8 + + - LowMachEOM: + name: myLowMach + max_iterations: 1 + convergence_tolerance: 1e-8 + + - WilcoxKOmega: + name: myKO + max_iterations: 1 + convergence_tolerance: 1e-8 + + initial_conditions: + - constant: ic_1 + target_name: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.05 + specific_dissipation_rate: 3528.0 + average_velocity: [22.78,0.0,0.0] + average_tke_resolved: 0.0 + average_dudx: 0.0 + k_ratio: 1.0 + avg_res_adequacy_parameter: 1.0 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: ko_ams + reset_AMS_averages_on_init: true + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + specific_dissipation_rate: 0.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 + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - turbulence_model_constants: + SDRWallFactor: 0.625 + forcingFactor: 32.0 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: KOAMSChannelEdge-ams.rst + restart_frequency: 10 + restart_start: 0 + restart_time: 100 + + output: + output_data_base_name: KOAMSChannelEdge-ams.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - average_velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - specific_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - k_ratio + - rans_time_scale + - average_mass_flow_rate + - average_tke_resolved + - avg_res_adequacy_parameter + - resolution_adequacy_parameter + - metric_tensor + - element_courant + - average_production + - average_dudx + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 20 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/SSTAMSChannelEdge/SSTAMSChannelEdge_rst.yaml b/reg_tests/test_files/SSTAMSChannelEdge/SSTAMSChannelEdge_rst.yaml index 52a15f392..4d96070d4 100644 --- a/reg_tests/test_files/SSTAMSChannelEdge/SSTAMSChannelEdge_rst.yaml +++ b/reg_tests/test_files/SSTAMSChannelEdge/SSTAMSChannelEdge_rst.yaml @@ -30,7 +30,7 @@ realms: - name: realm_1 mesh: SSTAMSChannelEdge.rst - use_edges: yes + use_edges: yes check_for_missing_bcs: yes support_inconsistent_multi_state_restart: yes @@ -48,7 +48,6 @@ realms: specific_dissipation_rate: solve_scalar pressure: solve_cont ndtw: solve_cont - time_averaged_model_split: solve_cont systems: - WallDistance: @@ -78,7 +77,7 @@ realms: average_tke_resolved: 0.0 average_dudx: 0.0 k_ratio: 1.0 - avg_res_adequacy_parameter: 1.0 + avg_res_adequacy_parameter: 1.0 material_properties: target_name: Unspecified-2-HEX @@ -88,7 +87,7 @@ realms: value: 1.0 - name: viscosity type: constant - value: 9.99488e-4 + value: 9.99488e-4 boundary_conditions: @@ -119,7 +118,7 @@ realms: solution_options: name: myOptions turbulence_model: sst_ams - reset_AMS_averages_on_init: true + reset_AMS_averages_on_init: true projected_timescale_type: momentum_diag_inv fix_pressure_at_node: @@ -162,7 +161,7 @@ realms: ndtw: element - relaxation_factor: - velocity: 1.0 + velocity: 1.0 pressure: 1.0 turbulent_ke: 1.0 specific_dissipation_rate: 1.0 diff --git a/reg_tests/test_files/SSTAMSOversetRotCylinder/SSTAMSOversetRotCylinder_rst.yaml b/reg_tests/test_files/SSTAMSOversetRotCylinder/SSTAMSOversetRotCylinder_rst.yaml index ae9f7609e..70d641e91 100644 --- a/reg_tests/test_files/SSTAMSOversetRotCylinder/SSTAMSOversetRotCylinder_rst.yaml +++ b/reg_tests/test_files/SSTAMSOversetRotCylinder/SSTAMSOversetRotCylinder_rst.yaml @@ -40,7 +40,6 @@ realms: specific_dissipation_rate: solve_scalar pressure: solve_cont ndtw: solve_cont - time_averaged_model_split: solve_cont systems: - WallDistance: diff --git a/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge.yaml b/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge.yaml new file mode 100644 index 000000000..2500eb8e6 --- /dev/null +++ b/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge.yaml @@ -0,0 +1,205 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: ../../mesh/periodicChannel.g + use_edges: yes + check_for_missing_bcs: yes + automatic_decomposition_type: rcb + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + specific_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-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: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.05 + specific_dissipation_rate: 3528.0 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: sstlr + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + specific_dissipation_rate: 0.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 + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - turbulence_model_constants: + SDRWallFactor: 0.625 + sigmaKOne: 0.5 + sigmaWOne: 0.5 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: SSTLRAMSChannelEdge.rst + restart_frequency: 10 + restart_start: 0 + + output: + output_data_base_name: SSTLRAMSChannelEdge.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - specific_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - element_courant + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 10 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge_rst.yaml b/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge_rst.yaml new file mode 100644 index 000000000..abf1b829c --- /dev/null +++ b/reg_tests/test_files/SSTLRAMSChannelEdge/SSTLRAMSChannelEdge_rst.yaml @@ -0,0 +1,223 @@ +Simulations: + - name: sim1 + time_integrator: ti_1 + optimizer: opt1 + +linear_solvers: + + - name: solve_scalar + type: tpetra + method: gmres + preconditioner: riluk + tolerance: 1e-5 + max_iterations: 200 + kspace: 200 + output_level: 0 + + - name: solve_cont + type: hypre + method: hypre_gmres + preconditioner: boomerAMG + tolerance: 1e-5 + max_iterations: 50 + kspace: 75 + output_level: 0 + bamg_coarsen_type: 8 + bamg_interp_type: 6 + bamg_cycle_type: 1 + +realms: + + - name: realm_1 + mesh: SSTLRAMSChannelEdge.rst + use_edges: yes + check_for_missing_bcs: yes + support_inconsistent_multi_state_restart: yes + + time_step_control: + target_courant: 1.0 + time_step_change_factor: 1.2 + + equation_systems: + name: theEqSys + max_iterations: 4 + + solver_system_specification: + velocity: solve_scalar + turbulent_ke: solve_scalar + specific_dissipation_rate: solve_scalar + pressure: solve_cont + ndtw: solve_cont + + systems: + - WallDistance: + name: myNDTW + max_iterations: 1 + convergence_tolerance: 1.0e-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: Unspecified-2-HEX + value: + pressure: 0 + velocity: [22.0,0.0,0.0] + turbulent_ke: 0.0005 + specific_dissipation_rate: 0.0005 + average_velocity: [22.78,0.0,0.0] + average_tke_resolved: 0.0 + average_dudx: 0.0 + k_ratio: 1.0 + avg_res_adequacy_parameter: 1.0 + + material_properties: + target_name: Unspecified-2-HEX + specifications: + - name: density + type: constant + value: 1.0 + - name: viscosity + type: constant + value: 9.99488e-4 + + boundary_conditions: + + - wall_boundary_condition: bc_bot + target_name: bottom + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - wall_boundary_condition: bc_top + target_name: top + wall_user_data: + velocity: [0,0,0] + turbulent_ke: 0.0 + use_wall_function: no + + - periodic_boundary_condition: bc_inlet_outlet + target_name: [inlet, outlet] + periodic_user_data: + search_tolerance: 0.001 + + - periodic_boundary_condition: bc_front_back + target_name: [front, back] + periodic_user_data: + search_tolerance: 0.001 + + solution_options: + name: myOptions + turbulence_model: sstlr_ams + reset_AMS_averages_on_init: true + projected_timescale_type: momentum_diag_inv + + fix_pressure_at_node: + value: 0.0 + node_lookup_type: spatial_location + location: [ 1.0, 1.0, 1.0 ] + search_target_part: [Unspecified-2-HEX] + search_method: stk_kdtree + + options: + - hybrid_factor: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - alpha_upw: + velocity: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - upw_factor: + velocity: 1.0 + turbulent_ke: 0.0 + specific_dissipation_rate: 0.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 + ndtw: element + + - relaxation_factor: + velocity: 1.0 + pressure: 1.0 + turbulent_ke: 1.0 + specific_dissipation_rate: 1.0 + + - turbulence_model_constants: + SDRWallFactor: 0.625 + forcingFactor: 32.0 + sigmaKOne: 0.5 + sigmaWOne: 0.5 + + - source_terms: + momentum: body_force + + - source_term_parameters: + momentum: [1.00, 0.0, 0.0] + + restart: + restart_data_base_name: SSTLRAMSChannelEdge-ams.rst + restart_frequency: 10 + restart_start: 0 + restart_time: 100 + + output: + output_data_base_name: SSTLRAMSChannelEdge-ams.e + output_frequency: 10 + output_node_set: no + output_variables: + - velocity + - average_velocity + - pressure + - pressure_force + - tau_wall + - turbulent_ke + - specific_dissipation_rate + - minimum_distance_to_wall + - turbulent_viscosity + - k_ratio + - rans_time_scale + - average_mass_flow_rate + - average_tke_resolved + - avg_res_adequacy_parameter + - resolution_adequacy_parameter + - metric_tensor + - element_courant + - average_production + - average_dudx + +Time_Integrators: + - StandardTimeIntegrator: + name: ti_1 + start_time: 0 + time_step: 2.0e-3 + termination_step_count: 20 + time_stepping_type: fixed + time_step_count: 0 + second_order_accuracy: yes + + realms: + - realm_1 diff --git a/reg_tests/test_files/ablNeutralEdgeAMS/ablNeutralEdgeAMS.yaml b/reg_tests/test_files/ablNeutralEdgeAMS/ablNeutralEdgeAMS.yaml index 75c6af29d..035b7215c 100644 --- a/reg_tests/test_files/ablNeutralEdgeAMS/ablNeutralEdgeAMS.yaml +++ b/reg_tests/test_files/ablNeutralEdgeAMS/ablNeutralEdgeAMS.yaml @@ -68,7 +68,6 @@ realms: specific_dissipation_rate: solve_scalar pressure: solve_cont ndtw: solve_cont - time_averaged_model_split: solve_cont # This defines the equation systems, maximum number of inner iterations, # and scaled nonlinear residual tolerance. @@ -77,14 +76,14 @@ realms: name: myNDTW max_iterations: 1 convergence_tolerance: 1e-8 - + - LowMachEOM: name: myLowMach max_iterations: 1 convergence_tolerance: 1e-8 - ShearStressTransport: - name: mySST + name: mySST max_iterations: 1 convergence_tolerance: 1e-8 @@ -138,7 +137,7 @@ realms: - periodic_boundary_condition: bc_east_west target_name: [east, west] periodic_user_data: - search_tolerance: 0.0001 + search_tolerance: 0.0001 - abltop_boundary_condition: bc_upper target_name: upper @@ -241,7 +240,7 @@ realms: - source_terms: momentum: - - EarthCoriolis + - EarthCoriolis - abl_forcing - user_constants: diff --git a/reg_tests/test_files/amsChannelEdge/amsChannelEdge.yaml b/reg_tests/test_files/amsChannelEdge/amsChannelEdge.yaml index e4018bb48..89386bef5 100644 --- a/reg_tests/test_files/amsChannelEdge/amsChannelEdge.yaml +++ b/reg_tests/test_files/amsChannelEdge/amsChannelEdge.yaml @@ -30,7 +30,7 @@ realms: - name: realm_1 mesh: ../../mesh/periodicChannel.g - use_edges: yes + use_edges: yes check_for_missing_bcs: yes automatic_decomposition_type: rcb @@ -48,7 +48,6 @@ realms: specific_dissipation_rate: solve_scalar pressure: solve_cont ndtw: solve_cont - time_averaged_model_split: solve_cont systems: - WallDistance: @@ -73,12 +72,12 @@ realms: pressure: 0 velocity: [22.0,0.0,0.0] turbulent_ke: 0.05 - specific_dissipation_rate: 3528.0 + specific_dissipation_rate: 3528.0 average_velocity: [22.78,0.0,0.0] average_tke_resolved: 0.0 average_dudx: 0.0 k_ratio: 1.0 - avg_res_adequacy_parameter: 1.0 + avg_res_adequacy_parameter: 1.0 material_properties: target_name: Unspecified-2-HEX @@ -88,7 +87,7 @@ realms: value: 1.0 - name: viscosity type: constant - value: 9.99488e-4 + value: 9.99488e-4 boundary_conditions: @@ -119,7 +118,7 @@ realms: solution_options: name: myOptions turbulence_model: sst_ams - reset_AMS_averages_on_init: true + reset_AMS_averages_on_init: true projected_timescale_type: momentum_diag_inv fix_pressure_at_node: @@ -162,7 +161,7 @@ realms: ndtw: element - relaxation_factor: - velocity: 1.0 + velocity: 1.0 pressure: 1.0 turbulent_ke: 1.0 specific_dissipation_rate: 1.0 diff --git a/reg_tests/test_files/amsChannelEdge/amsChannelEdge_rst.yaml b/reg_tests/test_files/amsChannelEdge/amsChannelEdge_rst.yaml index 54c65f5a5..e981ec61f 100644 --- a/reg_tests/test_files/amsChannelEdge/amsChannelEdge_rst.yaml +++ b/reg_tests/test_files/amsChannelEdge/amsChannelEdge_rst.yaml @@ -30,7 +30,7 @@ realms: - name: realm_1 mesh: amsChannelEdge.rst - use_edges: yes + use_edges: yes check_for_missing_bcs: yes support_inconsistent_multi_state_restart: yes @@ -48,7 +48,6 @@ realms: specific_dissipation_rate: solve_scalar pressure: solve_cont ndtw: solve_cont - time_averaged_model_split: solve_cont systems: - WallDistance: @@ -78,7 +77,7 @@ realms: average_tke_resolved: 0.0 average_dudx: 0.0 k_ratio: 1.0 - avg_res_adequacy_parameter: 1.0 + avg_res_adequacy_parameter: 1.0 material_properties: target_name: Unspecified-2-HEX @@ -88,7 +87,7 @@ realms: value: 1.0 - name: viscosity type: constant - value: 9.99488e-4 + value: 9.99488e-4 boundary_conditions: @@ -119,7 +118,7 @@ realms: solution_options: name: myOptions turbulence_model: sst_ams - reset_AMS_averages_on_init: false + reset_AMS_averages_on_init: false projected_timescale_type: momentum_diag_inv fix_pressure_at_node: @@ -162,7 +161,7 @@ realms: ndtw: element - relaxation_factor: - velocity: 1.0 + velocity: 1.0 pressure: 1.0 turbulent_ke: 1.0 specific_dissipation_rate: 1.0 diff --git a/src/AMSAlgDriver.C b/src/AMSAlgDriver.C index f407d11a5..49a4b420a 100644 --- a/src/AMSAlgDriver.C +++ b/src/AMSAlgDriver.C @@ -46,6 +46,11 @@ AMSAlgDriver::AMSAlgDriver(Realm& realm) avgTime_(NULL), avgMdot_(NULL), forcingComp_(NULL), + magPM_(NULL), + PMmax_(NULL), + PM1_(NULL), + PM2_(NULL), + PM3_(NULL), metricTensorAlgDriver_(realm_, "metric_tensor"), avgMdotAlg_(realm_), turbulenceModel_(realm_.solutionOptions_->turbulenceModel_), @@ -53,10 +58,12 @@ AMSAlgDriver::AMSAlgDriver(Realm& realm) { if (!realm.realmUsesEdges_) throw std::runtime_error("AMS not supported on element runs."); - if (turbulenceModel_ != TurbulenceModel::SST_AMS) { + if (!realm.is_ams_model()) { throw std::runtime_error( "User has requested AMS, however, turbulence model has not been set " - "to sst_ams, the only one supported by this driver currently."); + "to sst_ams, sstlr_ams, ko_ams, or ke_ams, the only ones supported by " + "this " + "driver currently."); } } @@ -122,7 +129,23 @@ AMSAlgDriver::register_nodal_fields(const stk::mesh::PartVector& part_vec) forcingComp_ = &(meta.declare_field( stk::topology::NODE_RANK, "forcing_components", numStates)); - stk::mesh::put_field_on_mesh(*forcingComp_, selector, nDim, nullptr); + stk::mesh::put_field_on_mesh(*forcingComp_, *part, nDim, nullptr); + + magPM_ = + &(meta.declare_field(stk::topology::NODE_RANK, "PMmag")); + PMmax_ = + &(meta.declare_field(stk::topology::NODE_RANK, "maxPM")); + PM1_ = + &(meta.declare_field(stk::topology::NODE_RANK, "PM1")); + PM2_ = + &(meta.declare_field(stk::topology::NODE_RANK, "PM2")); + PM3_ = + &(meta.declare_field(stk::topology::NODE_RANK, "PM3")); + stk::mesh::put_field_on_mesh(*magPM_, *part, nullptr); + stk::mesh::put_field_on_mesh(*PMmax_, *part, nullptr); + stk::mesh::put_field_on_mesh(*PM1_, *part, nullptr); + stk::mesh::put_field_on_mesh(*PM2_, *part, nullptr); + stk::mesh::put_field_on_mesh(*PM3_, *part, nullptr); } void @@ -151,6 +174,15 @@ AMSAlgDriver::register_interior_algorithm(stk::mesh::Part* part) case TurbulenceModel::SST_AMS: avgAlg_.reset(new SSTAMSAveragesAlg(realm_, part)); break; + case TurbulenceModel::SSTLR_AMS: + avgAlg_.reset(new SSTLRAMSAveragesAlg(realm_, part)); + break; + case TurbulenceModel::KE_AMS: + avgAlg_.reset(new KEAMSAveragesAlg(realm_, part)); + break; + case TurbulenceModel::KO_AMS: + avgAlg_.reset(new KOAMSAveragesAlg(realm_, part)); + break; default: throw std::runtime_error("AMSAlgDriver: non-supported turb model"); } diff --git a/src/GammaEquationSystem.C b/src/GammaEquationSystem.C index 38bebb68a..a4ee5fc9b 100644 --- a/src/GammaEquationSystem.C +++ b/src/GammaEquationSystem.C @@ -216,12 +216,9 @@ GammaEquationSystem::register_interior_algorithm(stk::mesh::Part* part) if (itsi == solverAlgDriver_->solverAlgMap_.end()) { SolverAlgorithm* theAlg = NULL; if (realm_.realmUsesEdges_) { - const bool useAvgMdot = (realm_.solutionOptions_->turbulenceModel_ == - TurbulenceModel::SST_AMS) - ? true - : false; + // Currently not compatible with AMS, setting averaging to False theAlg = new ScalarEdgeSolverAlg( - realm_, part, this, gamma_, dgamdx_, evisc_, useAvgMdot); + realm_, part, this, gamma_, dgamdx_, evisc_, false); } else { throw std::runtime_error( "GAMMAEQS: Attempt to use non-NGP element solver algorithm"); diff --git a/src/LowMachEquationSystem.C b/src/LowMachEquationSystem.C index 75e5ca98e..cb00b5c27 100644 --- a/src/LowMachEquationSystem.C +++ b/src/LowMachEquationSystem.C @@ -129,6 +129,8 @@ // UT Austin Hybrid AMS kernels #include #include +#include +#include // user function #include @@ -672,7 +674,7 @@ void LowMachEquationSystem::pre_iter_work() { momentumEqSys_->pre_iter_work(); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) momentumEqSys_->AMSAlgDriver_->execute(); continuityEqSys_->pre_iter_work(); } @@ -692,7 +694,7 @@ LowMachEquationSystem::solve_and_update() timeB = NaluEnv::self().nalu_time(); continuityEqSys_->timerMisc_ += (timeB - timeA); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) { + if (realm_.is_ams_model()) { momentumEqSys_->AMSAlgDriver_->initial_mdot(); } @@ -1009,7 +1011,7 @@ LowMachEquationSystem::post_converged_work() void LowMachEquationSystem::post_iter_work() { - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) momentumEqSys_->AMSAlgDriver_->post_iter_work(); } @@ -1062,7 +1064,7 @@ MomentumEquationSystem::MomentumEquationSystem(EquationSystems& eqSystems) manage_projected_nodal_gradient(eqSystems); } - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) AMSAlgDriver_.reset(new AMSAlgDriver(realm_)); } @@ -1092,7 +1094,7 @@ MomentumEquationSystem::initial_work() compute_projected_nodal_gradient(); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) AMSAlgDriver_->initial_work(); { @@ -1107,7 +1109,7 @@ MomentumEquationSystem::initial_work() timerMisc_ += (timeB - timeA); } - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) AMSAlgDriver_->initial_production(); } @@ -1119,9 +1121,8 @@ MomentumEquationSystem::pre_timestep_work() { // call base class method due to override EquationSystem::pre_timestep_work(); - if ( - (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) && + (realm_.is_ams_model()) && (realm_.solutionOptions_->meshMotion_ || realm_.solutionOptions_->externalMeshDeformation_)) { AMSAlgDriver_->compute_metric_tensor(); @@ -1172,8 +1173,8 @@ MomentumEquationSystem::register_nodal_fields( stk::topology::NODE_RANK, "effective_viscosity_u")); stk::mesh::put_field_on_mesh(*evisc_, selector, nullptr); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) - AMSAlgDriver_->register_nodal_fields(part_vec); + if (realm_.is_ams_model()) + AMSAlgDriver_->register_nodal_fields(part); if ( realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_IDDES) { @@ -1261,8 +1262,8 @@ MomentumEquationSystem::register_edge_fields( &(realm_.meta_data().declare_field( stk::topology::EDGE_RANK, "peclet_number")); stk::mesh::put_field_on_mesh(*pecletNumber, selector, nullptr); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) - AMSAlgDriver_->register_edge_fields(part_vec); + if (realm_.is_ams_model()) + AMSAlgDriver_->register_edge_fields(part); } //-------------------------------------------------------------------------- @@ -1303,7 +1304,7 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) SolverAlgorithm* theSolverAlg = NULL; if (realm_.realmUsesEdges_) { theSolverAlg = new MomentumEdgeSolverAlg(realm_, part, this); - if (theTurbModel == TurbulenceModel::SST_AMS) { + if (realm_.is_ams_model()) { SolverAlgorithm* theSolverSrcAlg = NULL; theSolverSrcAlg = new AssembleAMSEdgeKernelAlg(realm_, part, this); solverAlgDriver_->solverAlgMap_[SRC] = theSolverSrcAlg; @@ -1312,8 +1313,7 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) realm_.is_turbulent() && realm_.solutionOptions_->useStreletsUpwinding_) { pecletAlg_.reset(new StreletsUpwindEdgeAlg(realm_, part)); - } else if ( - realm_.is_turbulent() && theTurbModel == TurbulenceModel::SST_AMS) { + } else if (realm_.is_turbulent() && (realm_.is_ams_model())) { pecletAlg_.reset(new AMSMomentumEdgePecletAlg(realm_, part, this)); } else { pecletAlg_.reset(new MomentumEdgePecletAlg(realm_, part, this)); @@ -1335,8 +1335,7 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) } else { itsi->second->partVec_.push_back(part); - const bool hasAMS = - realm_.realmUsesEdges_ && (theTurbModel == TurbulenceModel::SST_AMS); + const bool hasAMS = realm_.realmUsesEdges_ && (realm_.is_ams_model()); if (hasAMS) { auto* tamsAlg = solverAlgDriver_->solverAlgMap_.at(SRC); tamsAlg->partVec_.push_back(part); @@ -1371,9 +1370,20 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) if (!elementMassAlg) nodeAlg.add_kernel(realm_.bulk_data()); if ( - realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + (realm_.solutionOptions_->turbulenceModel_ == + TurbulenceModel::SST_AMS) || + ((realm_.solutionOptions_->turbulenceModel_ == + TurbulenceModel::SSTLR_AMS))) nodeAlg.add_kernel( realm_.bulk_data(), *realm_.solutionOptions_); + else if ( + realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::KE_AMS) + nodeAlg.add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); + else if ( + realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::KO_AMS) + nodeAlg.add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); }, [&](AssembleNGPNodeSolverAlgorithm& nodeAlg, std::string& srcName) { bool added = true; @@ -1516,6 +1526,7 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) break; case TurbulenceModel::KE: + case TurbulenceModel::KE_AMS: tviscAlg_.reset(new TurbViscKEAlg(realm_, part, tvisc_)); break; @@ -1523,10 +1534,18 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) tviscAlg_.reset(new TurbViscKOAlg(realm_, part, tvisc_)); break; + case TurbulenceModel::KO_AMS: + tviscAlg_.reset(new TurbViscKOAlg(realm_, part, tvisc_, true)); + break; + case TurbulenceModel::SSTLR: tviscAlg_.reset(new TurbViscSSTLRAlg(realm_, part, tvisc_)); break; + case TurbulenceModel::SSTLR_AMS: + tviscAlg_.reset(new TurbViscSSTLRAlg(realm_, part, tvisc_, true)); + break; + default: throw std::runtime_error("Unsupported turbulence model provided"); } @@ -1534,7 +1553,7 @@ MomentumEquationSystem::register_interior_algorithm(stk::mesh::Part* part) tviscAlg_->partVec_.push_back(part); } - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) AMSAlgDriver_->register_interior_algorithm(part); } } @@ -2449,7 +2468,7 @@ MomentumEquationSystem::predict_state() nalu_ngp::field_copy(ngpMesh, sel, velNp1, velN, meta.spatial_dimension()); velNp1.modify_on_device(); - if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + if (realm_.is_ams_model()) AMSAlgDriver_->predict_state(); } diff --git a/src/Realm.C b/src/Realm.C index f96f62fbd..f181b5968 100644 --- a/src/Realm.C +++ b/src/Realm.C @@ -4457,6 +4457,15 @@ Realm::is_turbulent(bool isIt) solutionOptions_->isTurbulent_ = isIt; } +//-------------------------------------------------------------------------- +//-------- is_ams_model ---------------------------------------------------- +//-------------------------------------------------------------------------- +bool +Realm::is_ams_model() +{ + return solutionOptions_->isAMSModel_; +} + //-------------------------------------------------------------------------- //-------- needs_enthalpy -------------------------------------------------- //-------------------------------------------------------------------------- diff --git a/src/SolutionOptions.C b/src/SolutionOptions.C index c4f5dd400..06252644f 100644 --- a/src/SolutionOptions.C +++ b/src/SolutionOptions.C @@ -52,6 +52,7 @@ SolutionOptions::SolutionOptions() solveIncompressibleContinuity_(false), isTurbulent_(false), turbulenceModel_(TurbulenceModel::LAMINAR), + isAMSModel_(false), meshMotion_(false), meshTransformation_(false), externalMeshDeformation_(false), @@ -248,6 +249,14 @@ SolutionOptions::load(const YAML::Node& y_node) if (transition_model_ == true) gammaEqActive_ = true; } + + if (((turbulenceModel_ == TurbulenceModel::SST_AMS) || + (turbulenceModel_ == TurbulenceModel::SSTLR_AMS) || + (turbulenceModel_ == TurbulenceModel::KE_AMS) || + (turbulenceModel_ == TurbulenceModel::KO_AMS))) { + isAMSModel_ = true; + } + // initialize turbulence constants since some laminar models may need such // variables, e.g., kappa initialize_turbulence_constants(); @@ -635,6 +644,7 @@ SolutionOptions::initialize_turbulence_constants() turbulenceModel_ == TurbulenceModel::SSTLR || turbulenceModel_ == TurbulenceModel::SST_DES || turbulenceModel_ == TurbulenceModel::SST_AMS || + turbulenceModel_ == TurbulenceModel::SSTLR_AMS || turbulenceModel_ == TurbulenceModel::SST_IDDES) ? 10.0 : 500.0; @@ -693,6 +703,9 @@ SolutionOptions::initialize_turbulence_constants() turbModelConstantMap_[TM_fOne] = 1.0; turbModelConstantMap_[TM_sigmaK] = 1.0; turbModelConstantMap_[TM_sigmaEps] = 1.3; + turbModelConstantMap_[TM_alphaPow] = 1.7; + turbModelConstantMap_[TM_alphaScaPow] = 1.0; + turbModelConstantMap_[TM_coeffR] = 1.0; turbModelConstantMap_[TM_sstLRDestruct] = 1.0; turbModelConstantMap_[TM_sstLRProd] = 1.0; turbModelConstantMap_[TM_tkeAmb] = 0.0; diff --git a/src/SpecificDissipationRateEquationSystem.C b/src/SpecificDissipationRateEquationSystem.C index 442383f2d..2fda226a5 100644 --- a/src/SpecificDissipationRateEquationSystem.C +++ b/src/SpecificDissipationRateEquationSystem.C @@ -52,6 +52,7 @@ #include #include #include +#include // ngp #include "ngp_utils/NgpFieldBLAS.h" @@ -67,6 +68,7 @@ // UT Austin Hybrid AMS kernel #include +#include #include @@ -231,10 +233,7 @@ SpecificDissipationRateEquationSystem::register_interior_algorithm( if (itsi == solverAlgDriver_->solverAlgMap_.end()) { SolverAlgorithm* theAlg = NULL; if (realm_.realmUsesEdges_) { - const bool useAvgMdot = (realm_.solutionOptions_->turbulenceModel_ == - TurbulenceModel::SST_AMS) - ? true - : false; + const bool useAvgMdot = realm_.is_ams_model(); theAlg = new ScalarEdgeSolverAlg( realm_, part, this, sdr_, dwdx_, evisc_, useAvgMdot); } else { @@ -288,9 +287,19 @@ SpecificDissipationRateEquationSystem::register_interior_algorithm( nodeAlg.add_kernel( realm_.meta_data(), realm_.solutionOptions_->get_coordinates_name()); + } else if ( + TurbulenceModel::SSTLR_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 if ( + TurbulenceModel::KO_AMS == + realm_.solutionOptions_->turbulenceModel_) { + nodeAlg.add_kernel(realm_.meta_data()); } else { throw std::runtime_error( "Invalid turbulence model in SDR equation system: " + @@ -314,6 +323,10 @@ SpecificDissipationRateEquationSystem::register_interior_algorithm( if (TurbulenceModel::KO == realm_.solutionOptions_->turbulenceModel_) { effDiffFluxAlg_.reset(new EffDiffFluxCoeffAlg( realm_, part, visc_, tvisc_, evisc_, 1.0, 2.0, realm_.is_turbulent())); + } else if ( + TurbulenceModel::KO_AMS == realm_.solutionOptions_->turbulenceModel_) { + effDiffFluxAlg_.reset(new EffDiffFluxCoeffAlg( + realm_, part, visc_, tvisc_, evisc_, 1.0, 2.0, realm_.is_turbulent())); } else { const double sigmaWOne = realm_.get_turb_model_constant(TM_sigmaWOne); const double sigmaWTwo = realm_.get_turb_model_constant(TM_sigmaWTwo); diff --git a/src/TotalDissipationRateEquationSystem.C b/src/TotalDissipationRateEquationSystem.C index 1a7d37306..0debd0b92 100644 --- a/src/TotalDissipationRateEquationSystem.C +++ b/src/TotalDissipationRateEquationSystem.C @@ -58,6 +58,9 @@ #include "ngp_algorithms/EffDiffFluxCoeffAlg.h" #include "utils/StkHelpers.h" +// UT Austin Hybrid AMS kernel +#include + #include // stk_util @@ -220,8 +223,7 @@ TotalDissipationRateEquationSystem::register_interior_algorithm( if (itsi == solverAlgDriver_->solverAlgMap_.end()) { SolverAlgorithm* theAlg = NULL; if (realm_.realmUsesEdges_) { - const bool useAvgMdot = - realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS; + const bool useAvgMdot = realm_.is_ams_model(); theAlg = new ScalarEdgeSolverAlg( realm_, part, this, tdr_, dedx_, evisc_, useAvgMdot); } else { @@ -258,7 +260,12 @@ TotalDissipationRateEquationSystem::register_interior_algorithm( if (TurbulenceModel::KE == realm_.solutionOptions_->turbulenceModel_) { nodeAlg.add_kernel(realm_.meta_data()); - } else { + } else if ( + TurbulenceModel::KE_AMS == realm_.solutionOptions_->turbulenceModel_) + nodeAlg.add_kernel( + realm_.meta_data(), + realm_.solutionOptions_->get_coordinates_name()); + else { nodeAlg.add_kernel(realm_.meta_data()); } }, diff --git a/src/TurbKineticEnergyEquationSystem.C b/src/TurbKineticEnergyEquationSystem.C index 3452d2f9e..d238d1cb8 100644 --- a/src/TurbKineticEnergyEquationSystem.C +++ b/src/TurbKineticEnergyEquationSystem.C @@ -44,6 +44,9 @@ // UT Austin Hybrid AMS kernel #include +#include +#include +#include // edge kernels #include @@ -151,7 +154,8 @@ TurbKineticEnergyEquationSystem::TurbKineticEnergyEquationSystem( if (!check_for_valid_turblence_model(turbulenceModel_)) { throw std::runtime_error( "User has requested TurbKinEnergyEqs, however, turbulence model is not " - "KSGS, SST, SSTLR, SST_DES, SST_IDDES, SST_AMS, KE, or KO"); + "KSGS, SST, SSTLR, SST_DES, SST_IDDES, KE, KO, SST_AMS, SSTLR_AMS, " + "KE_AMS, or KO_AMS"); } // create projected nodal gradient equation system @@ -169,10 +173,13 @@ TurbKineticEnergyEquationSystem::check_for_valid_turblence_model( case TurbulenceModel::SSTLR: case TurbulenceModel::KSGS: case TurbulenceModel::SST_DES: - case TurbulenceModel::SST_AMS: case TurbulenceModel::SST_IDDES: case TurbulenceModel::KE: case TurbulenceModel::KO: + case TurbulenceModel::SST_AMS: + case TurbulenceModel::SSTLR_AMS: + case TurbulenceModel::KE_AMS: + case TurbulenceModel::KO_AMS: return true; default: return false; @@ -266,8 +273,7 @@ TurbKineticEnergyEquationSystem::register_interior_algorithm( if (itsi == solverAlgDriver_->solverAlgMap_.end()) { SolverAlgorithm* theAlg = NULL; if (realm_.realmUsesEdges_) { - const bool useAvgMdot = - (turbulenceModel_ == TurbulenceModel::SST_AMS) ? true : false; + const bool useAvgMdot = realm_.is_ams_model(); theAlg = new ScalarEdgeSolverAlg( realm_, part, this, tke_, dkdx_, evisc_, useAvgMdot); } else { @@ -327,6 +333,19 @@ TurbKineticEnergyEquationSystem::register_interior_algorithm( case TurbulenceModel::KO: nodeAlg.add_kernel(realm_.meta_data()); break; + case TurbulenceModel::SSTLR_AMS: + nodeAlg.add_kernel( + realm_.meta_data(), + realm_.solutionOptions_->get_coordinates_name()); + break; + case TurbulenceModel::KE_AMS: + nodeAlg.add_kernel( + realm_.meta_data(), + realm_.solutionOptions_->get_coordinates_name()); + break; + case TurbulenceModel::KO_AMS: + nodeAlg.add_kernel(realm_.meta_data()); + break; default: std::runtime_error("TKEEqSys: Invalid turbulence model"); break; @@ -362,6 +381,7 @@ TurbKineticEnergyEquationSystem::register_interior_algorithm( case TurbulenceModel::SSTLR: case TurbulenceModel::SST_DES: case TurbulenceModel::SST_AMS: + case TurbulenceModel::SSTLR_AMS: case TurbulenceModel::SST_IDDES: { const double sigmaKOne = realm_.get_turb_model_constant(TM_sigmaKOne); const double sigmaKTwo = realm_.get_turb_model_constant(TM_sigmaKTwo); @@ -369,12 +389,14 @@ TurbKineticEnergyEquationSystem::register_interior_algorithm( realm_, part, visc_, tvisc_, evisc_, sigmaKOne, sigmaKTwo)); break; } - case TurbulenceModel::KO: { + case TurbulenceModel::KO: + case TurbulenceModel::KO_AMS: { effDiffFluxCoeffAlg_.reset(new EffDiffFluxCoeffAlg( realm_, part, visc_, tvisc_, evisc_, 1.0, 2.0, realm_.is_turbulent())); break; } - case TurbulenceModel::KE: { + case TurbulenceModel::KE: + case TurbulenceModel::KE_AMS: { const double sigmaK = realm_.get_turb_model_constant(TM_sigmaK); effDiffFluxCoeffAlg_.reset(new EffDiffFluxCoeffAlg( realm_, part, visc_, tvisc_, evisc_, 1.0, sigmaK, diff --git a/src/edge_kernels/AssembleAMSEdgeKernelAlg.C b/src/edge_kernels/AssembleAMSEdgeKernelAlg.C index a1a5df3a5..5fa27815d 100644 --- a/src/edge_kernels/AssembleAMSEdgeKernelAlg.C +++ b/src/edge_kernels/AssembleAMSEdgeKernelAlg.C @@ -10,6 +10,11 @@ #include "edge_kernels/AssembleAMSEdgeKernelAlg.h" #include "edge_kernels/EdgeKernel.h" #include "edge_kernels/MomentumSSTAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumKEAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumKOAMSDiffEdgeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" namespace sierra { namespace nalu { @@ -18,9 +23,28 @@ AssembleAMSEdgeKernelAlg::AssembleAMSEdgeKernelAlg( Realm& realm, stk::mesh::Part* part, EquationSystem* eqSystem) : AssembleEdgeKernelAlg(realm, part, eqSystem) { + // Register AMS Kernels directly - add_kernel( - realm_.bulk_data(), *realm_.solutionOptions_); + if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SST_AMS) + add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); + + else if ( + realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::SSTLR_AMS) + add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); + + else if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::KE_AMS) + add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); + + else if (realm_.solutionOptions_->turbulenceModel_ == TurbulenceModel::KO_AMS) + add_kernel( + realm_.bulk_data(), *realm_.solutionOptions_); + + else + throw std::runtime_error( + "AssembleAMSEdgeKernelAlg: Not a valid turbulence model"); } } // namespace nalu diff --git a/src/edge_kernels/CMakeLists.txt b/src/edge_kernels/CMakeLists.txt index bc2a53421..967d1c0ec 100644 --- a/src/edge_kernels/CMakeLists.txt +++ b/src/edge_kernels/CMakeLists.txt @@ -5,6 +5,9 @@ target_sources(nalu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ContinuityEdgeSolverAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumEdgeSolverAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumSSTAMSDiffEdgeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/MomentumSSTLRAMSDiffEdgeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/MomentumKEAMSDiffEdgeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/MomentumKOAMSDiffEdgeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/ScalarEdgeSolverAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/WallDistEdgeSolverAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumEdgePecletAlg.C diff --git a/src/edge_kernels/MomentumEdgeSolverAlg.C b/src/edge_kernels/MomentumEdgeSolverAlg.C index d58293603..5e6a256e0 100644 --- a/src/edge_kernels/MomentumEdgeSolverAlg.C +++ b/src/edge_kernels/MomentumEdgeSolverAlg.C @@ -34,9 +34,7 @@ MomentumEdgeSolverAlg::MomentumEdgeSolverAlg( velocity_ = get_field_ordinal(meta, velName, stk::mesh::StateNP1); std::string viscName; - if ( - (realm.is_turbulent()) && - (realm.solutionOptions_->turbulenceModel_ != TurbulenceModel::SST_AMS)) + if ((realm.is_turbulent()) && (!realm.is_ams_model())) viscName = "effective_viscosity_u"; else viscName = "viscosity"; diff --git a/src/edge_kernels/MomentumKEAMSDiffEdgeKernel.C b/src/edge_kernels/MomentumKEAMSDiffEdgeKernel.C new file mode 100644 index 000000000..d430915ce --- /dev/null +++ b/src/edge_kernels/MomentumKEAMSDiffEdgeKernel.C @@ -0,0 +1,314 @@ +// 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 "edge_kernels/MomentumKEAMSDiffEdgeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "EigenDecomposition.h" + +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" +#include "utils/StkHelpers.h" +#include "utils/AMSUtils.h" +#include + +namespace sierra { +namespace nalu { + +MomentumKEAMSDiffEdgeKernel::MomentumKEAMSDiffEdgeKernel( + const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) + : NGPEdgeKernel(), + includeDivU_(solnOpts.includeDivU_), + betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), + CMdeg_(solnOpts.get_turb_model_constant(TM_CMdeg)), + aspectRatioSwitch_(solnOpts.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(solnOpts.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(solnOpts.get_turb_model_constant(TM_alphaScaPow)), + nDim_(bulk.mesh_meta_data().spatial_dimension()) +{ + const auto& meta = bulk.mesh_meta_data(); + + edgeAreaVecID_ = + get_field_ordinal(meta, "edge_area_vector", stk::topology::EDGE_RANK); + + coordinatesID_ = get_field_ordinal(meta, solnOpts.get_coordinates_name()); + velocityID_ = get_field_ordinal(meta, "velocity"); + turbViscID_ = get_field_ordinal(meta, "turbulent_viscosity"); + densityNp1ID_ = get_field_ordinal(meta, "density", stk::mesh::StateNP1); + tdrNp1ID_ = + get_field_ordinal(meta, "total_dissipation_rate", stk::mesh::StateNP1); + betaID_ = get_field_ordinal(meta, "k_ratio"); + MijID_ = get_field_ordinal(meta, "metric_tensor"); + dudxID_ = get_field_ordinal(meta, "dudx"); + + // average quantities + avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); + avgDudxID_ = get_field_ordinal(meta, "average_dudx"); + avgResAdeqID_ = get_field_ordinal(meta, "avg_res_adequacy_parameter"); + + const std::string dofName = "velocity"; + relaxFacU_ = solnOpts.get_relaxation_factor(dofName); +} + +void +MomentumKEAMSDiffEdgeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + edgeAreaVec_ = fieldMgr.get_field(edgeAreaVecID_); + coordinates_ = fieldMgr.get_field(coordinatesID_); + velocity_ = fieldMgr.get_field(velocityID_); + tvisc_ = fieldMgr.get_field(turbViscID_); + density_ = fieldMgr.get_field(densityNp1ID_); + tdr_ = fieldMgr.get_field(tdrNp1ID_); + beta_ = fieldMgr.get_field(betaID_); + nodalMij_ = fieldMgr.get_field(MijID_); + dudx_ = fieldMgr.get_field(dudxID_); + avgVelocity_ = fieldMgr.get_field(avgVelocityID_); + avgDudx_ = fieldMgr.get_field(avgDudxID_); + avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); +} + +KOKKOS_FUNCTION +void +MomentumKEAMSDiffEdgeKernel::execute( + EdgeKernelTraits::ShmemDataType& smdata, + const stk::mesh::FastMeshIndex& edge, + const stk::mesh::FastMeshIndex& nodeL, + const stk::mesh::FastMeshIndex& nodeR) +{ + const int ndim = nDim_; + + // Scratch work arrays + NALU_ALIGNED EdgeKernelTraits::DblType av[EdgeKernelTraits::NDimMax]; + + for (int d = 0; d < nDim_; d++) { + av[d] = edgeAreaVec_.get(edge, d); + } + + // Mij, eigenvectors and eigenvalues + EdgeKernelTraits::DblType Mij[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType Q[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType D[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + Mij[i][j] = 0.5 * (nodalMij_.get(nodeL, i * ndim + j) + + nodalMij_.get(nodeR, i * ndim + j)); + + EigenDecomposition::sym_diagonalize(Mij, Q, D); + + // At this point we have Q, the eigenvectors and D the eigenvalues of Mij, + // so to create M43, we use Q D^(4/3) Q^T + EdgeKernelTraits::DblType M43[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + M43[i][j] = 0.0; + + const double fourThirds = 4. / 3.; + for (int k = 0; k < ndim; k++) { + const EdgeKernelTraits::DblType D43 = stk::math::pow(D[k][k], fourThirds); + for (int i = 0; i < ndim; i++) { + for (int j = 0; j < ndim; j++) { + M43[i][j] += Q[i][k] * Q[j][k] * D43; + } + } + } + + // Compute cell aspect ratio blending + const EdgeKernelTraits::DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType aspectRatio = maxEigM / minEigM; + + const EdgeKernelTraits::DblType arScale = stk::math::if_then_else( + aspectRatio > aspectRatioSwitch_, + 1.0 - stk::math::tanh((aspectRatio - aspectRatioSwitch_) / 10.0), 1.0); + const EdgeKernelTraits::DblType arInvScale = 1.0 - arScale; + + // Compute CM43 + EdgeKernelTraits::DblType CM43 = ams_utils::get_M43_constant< + EdgeKernelTraits::DblType, EdgeKernelTraits::NDimMax>(D, CMdeg_); + + const EdgeKernelTraits::DblType CM43scale = stk::math::max( + stk::math::min( + 0.5 * (stk::math::pow(avgResAdeq_.get(nodeL, 0), 2.0) + + stk::math::pow(avgResAdeq_.get(nodeR, 0), 2.0)), + 30.0), + 1.0); + + const EdgeKernelTraits::DblType muIp = + 0.5 * (tvisc_.get(nodeL, 0) + tvisc_.get(nodeR, 0)); + const EdgeKernelTraits::DblType rhoIp = + 0.5 * (density_.get(nodeL, 0) + density_.get(nodeR, 0)); + const EdgeKernelTraits::DblType tdrIp = + 0.5 * (stk::math::max(tdr_.get(nodeL, 0), 1.0e-12) + + stk::math::max(tdr_.get(nodeR, 0), 1.0e-12)); + const EdgeKernelTraits::DblType alphaIp = + 0.5 * (stk::math::pow(beta_.get(nodeL, 0), alphaPow_) + + stk::math::pow(beta_.get(nodeR, 0), alphaPow_)); + + EdgeKernelTraits::DblType avgdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType fluctdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + EdgeKernelTraits::DblType axdx = 0.0; + EdgeKernelTraits::DblType asq = 0.0; + for (int d = 0; d < ndim; ++d) { + const EdgeKernelTraits::DblType dxj = + coordinates_.get(nodeR, d) - coordinates_.get(nodeL, d); + asq += av[d] * av[d]; + axdx += av[d] * dxj; + } + const EdgeKernelTraits::DblType inv_axdx = 1.0 / axdx; + + // Compute average divU + for (int i = 0; i < ndim; ++i) { + + // difference between R and L nodes for component i + const EdgeKernelTraits::DblType avgUidiff = + avgVelocity_.get(nodeR, i) - avgVelocity_.get(nodeL, i); + const EdgeKernelTraits::DblType fluctUidiff = + (velocity_.get(nodeR, i) - velocity_.get(nodeL, i)) - avgUidiff; + + const int offSetI = ndim * i; + + // start sum for NOC contribution + EdgeKernelTraits::DblType GlavgUidxl = 0.0; + EdgeKernelTraits::DblType GlfluctUidxl = 0.0; + for (int l = 0; l < ndim; ++l) { + const int offSetIL = offSetI + l; + const EdgeKernelTraits::DblType dxl = + coordinates_.get(nodeR, l) - coordinates_.get(nodeL, l); + const EdgeKernelTraits::DblType GlavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIL) + avgDudx_.get(nodeR, offSetIL)); + const EdgeKernelTraits::DblType GlfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIL) + dudx_.get(nodeR, offSetIL)) - + GlavgUi; + GlavgUidxl += GlavgUi * dxl; + GlfluctUidxl += GlfluctUi * dxl; + } + + // form full tensor dui/dxj with NOC + for (int j = 0; j < ndim; ++j) { + const int offSetIJ = offSetI + j; + const EdgeKernelTraits::DblType GjavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIJ) + avgDudx_.get(nodeR, offSetIJ)); + const EdgeKernelTraits::DblType GjfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIJ) + dudx_.get(nodeR, offSetIJ)) - + GjavgUi; + avgdUidxj[i][j] = GjavgUi + (avgUidiff - GlavgUidxl) * av[j] * inv_axdx; + fluctdUidxj[i][j] = + GjfluctUi + (fluctUidiff - GlfluctUidxl) * av[j] * inv_axdx; + } + } + + EdgeKernelTraits::DblType avgDivU = 0.0; + for (int i = 0; i < ndim; ++i) { + avgDivU += avgdUidxj[i][i]; + } + + const EdgeKernelTraits::DblType epsilon13Ip = + stk::math::pow(tdrIp, 1.0 / 3.0); + + for (int i = 0; i < ndim; ++i) { + // Left and right row/col indices + const int rowL = i; + const int rowR = i + ndim; + + // This is the divU term for the average quantities in the model for + // tau_ij^SGRS Since we are letting SST calculate it's normal mu_t, we + // need to scale by alpha here + const EdgeKernelTraits::DblType avgDivUstress = + 2.0 / 3.0 * stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * + muIp * avgDivU * av[i] * includeDivU_; + smdata.rhs(rowL) -= avgDivUstress; + smdata.rhs(rowR) += avgDivUstress; + + EdgeKernelTraits::DblType lhs_riC_i = 0.0; + EdgeKernelTraits::DblType lhs_riC_SGRS_i = 0.0; + for (int j = 0; j < ndim; ++j) { + + // -mut^jk*dui/dxk*A_j; fixed i over j loop; see below.. + EdgeKernelTraits::DblType rhsfacDiff_i = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_i = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_i += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[j][k] * av[k] * av[j] * inv_axdx; + rhsfacDiff_i += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[j][k] * fluctdUidxj[i][k] * av[j]; + } + + lhsfacDiff_i += -arInvScale * muIp * av[j] * av[j] * inv_axdx; + rhsfacDiff_i += -arInvScale * muIp * fluctdUidxj[i][j] * av[j]; + + // Accumulate lhs + lhs_riC_i += lhsfacDiff_i; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_i = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[i][j] * av[j]; + + // Implicit treatment of SGRS (average) term + lhs_riC_SGRS_i += -stk::math::pow(alphaIp, alphaScaPow_) * + (2.0 - alphaIp) * muIp * av[j] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_i + rhsSGRSfacDiff_i; + smdata.rhs(rowR) += rhsfacDiff_i + rhsSGRSfacDiff_i; + + // -mut^ik*duj/dxk*A_j + EdgeKernelTraits::DblType rhsfacDiff_j = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_j = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_j += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[i][k] * av[k] * av[j] * inv_axdx; + rhsfacDiff_j += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[i][k] * fluctdUidxj[j][k] * av[j]; + } + + lhsfacDiff_j += -arInvScale * muIp * av[i] * av[j] * inv_axdx; + rhsfacDiff_j += -arInvScale * muIp * fluctdUidxj[j][i] * av[j]; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[j][i] * av[j]; + + // Implicit treatment of SGRS (average) term + const EdgeKernelTraits::DblType lhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + av[i] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_j + rhsSGRSfacDiff_j; + smdata.rhs(rowR) += rhsfacDiff_j + rhsSGRSfacDiff_j; + + const int colL = j; + const int colR = j + ndim; + + smdata.lhs(rowL, colL) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + smdata.lhs(rowL, colR) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colL) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colR) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + } + + smdata.lhs(rowL, rowL) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + smdata.lhs(rowL, rowR) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowL) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowR) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + } +} + +} // namespace nalu +} // namespace sierra diff --git a/src/edge_kernels/MomentumKOAMSDiffEdgeKernel.C b/src/edge_kernels/MomentumKOAMSDiffEdgeKernel.C new file mode 100644 index 000000000..29fc887de --- /dev/null +++ b/src/edge_kernels/MomentumKOAMSDiffEdgeKernel.C @@ -0,0 +1,329 @@ +// 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 "edge_kernels/MomentumKOAMSDiffEdgeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "EigenDecomposition.h" + +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" +#include "utils/StkHelpers.h" +#include "utils/AMSUtils.h" +#include + +namespace sierra { +namespace nalu { + +MomentumKOAMSDiffEdgeKernel::MomentumKOAMSDiffEdgeKernel( + const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) + : NGPEdgeKernel(), + includeDivU_(solnOpts.includeDivU_), + betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), + CMdeg_(solnOpts.get_turb_model_constant(TM_CMdeg)), + aspectRatioSwitch_(solnOpts.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(solnOpts.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(solnOpts.get_turb_model_constant(TM_alphaScaPow)), + nDim_(bulk.mesh_meta_data().spatial_dimension()) +{ + const auto& meta = bulk.mesh_meta_data(); + + edgeAreaVecID_ = + get_field_ordinal(meta, "edge_area_vector", stk::topology::EDGE_RANK); + + coordinatesID_ = get_field_ordinal(meta, solnOpts.get_coordinates_name()); + velocityID_ = get_field_ordinal(meta, "velocity"); + turbViscID_ = get_field_ordinal(meta, "turbulent_viscosity"); + viscID_ = get_field_ordinal(meta, "viscosity"); + densityNp1ID_ = get_field_ordinal(meta, "density", stk::mesh::StateNP1); + tkeNp1ID_ = get_field_ordinal(meta, "turbulent_ke", stk::mesh::StateNP1); + sdrNp1ID_ = + get_field_ordinal(meta, "specific_dissipation_rate", stk::mesh::StateNP1); + betaID_ = get_field_ordinal(meta, "k_ratio"); + MijID_ = get_field_ordinal(meta, "metric_tensor"); + dudxID_ = get_field_ordinal(meta, "dudx"); + + // average quantities + avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); + avgDudxID_ = get_field_ordinal(meta, "average_dudx"); + avgResAdeqID_ = get_field_ordinal(meta, "avg_res_adequacy_parameter"); + + const std::string dofName = "velocity"; + relaxFacU_ = solnOpts.get_relaxation_factor(dofName); +} + +void +MomentumKOAMSDiffEdgeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + edgeAreaVec_ = fieldMgr.get_field(edgeAreaVecID_); + coordinates_ = fieldMgr.get_field(coordinatesID_); + velocity_ = fieldMgr.get_field(velocityID_); + tvisc_ = fieldMgr.get_field(turbViscID_); + visc_ = fieldMgr.get_field(viscID_); + density_ = fieldMgr.get_field(densityNp1ID_); + tke_ = fieldMgr.get_field(tkeNp1ID_); + sdr_ = fieldMgr.get_field(sdrNp1ID_); + beta_ = fieldMgr.get_field(betaID_); + nodalMij_ = fieldMgr.get_field(MijID_); + dudx_ = fieldMgr.get_field(dudxID_); + avgVelocity_ = fieldMgr.get_field(avgVelocityID_); + avgDudx_ = fieldMgr.get_field(avgDudxID_); + avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); +} + +KOKKOS_FUNCTION +void +MomentumKOAMSDiffEdgeKernel::execute( + EdgeKernelTraits::ShmemDataType& smdata, + const stk::mesh::FastMeshIndex& edge, + const stk::mesh::FastMeshIndex& nodeL, + const stk::mesh::FastMeshIndex& nodeR) +{ + const int ndim = nDim_; + + // Scratch work arrays + NALU_ALIGNED EdgeKernelTraits::DblType av[EdgeKernelTraits::NDimMax]; + + for (int d = 0; d < nDim_; d++) { + av[d] = edgeAreaVec_.get(edge, d); + } + + // Mij, eigenvectors and eigenvalues + EdgeKernelTraits::DblType Mij[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType Q[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType D[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + Mij[i][j] = 0.5 * (nodalMij_.get(nodeL, i * ndim + j) + + nodalMij_.get(nodeR, i * ndim + j)); + + EigenDecomposition::sym_diagonalize(Mij, Q, D); + + // At this point we have Q, the eigenvectors and D the eigenvalues of Mij, + // so to create M43, we use Q D^(4/3) Q^T + EdgeKernelTraits::DblType M43[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + M43[i][j] = 0.0; + + const double fourThirds = 4. / 3.; + for (int k = 0; k < ndim; k++) { + const EdgeKernelTraits::DblType D43 = stk::math::pow(D[k][k], fourThirds); + for (int i = 0; i < ndim; i++) { + for (int j = 0; j < ndim; j++) { + M43[i][j] += Q[i][k] * Q[j][k] * D43; + } + } + } + + // Compute cell aspect ratio blending + const EdgeKernelTraits::DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType aspectRatio = maxEigM / minEigM; + + const EdgeKernelTraits::DblType arScale = stk::math::if_then_else( + aspectRatio > aspectRatioSwitch_, + 1.0 - stk::math::tanh((aspectRatio - aspectRatioSwitch_) / 10.0), 1.0); + const EdgeKernelTraits::DblType arInvScale = 1.0 - arScale; + + // Compute CM43 + EdgeKernelTraits::DblType CM43 = ams_utils::get_M43_constant< + EdgeKernelTraits::DblType, EdgeKernelTraits::NDimMax>(D, CMdeg_); + + const EdgeKernelTraits::DblType CM43scale = stk::math::max( + stk::math::min( + 0.5 * (stk::math::pow(avgResAdeq_.get(nodeL, 0), 2.0) + + stk::math::pow(avgResAdeq_.get(nodeR, 0), 2.0)), + 30.0), + 1.0); + + const EdgeKernelTraits::DblType muIp = + 0.5 * (tvisc_.get(nodeL, 0) + tvisc_.get(nodeR, 0)); + const EdgeKernelTraits::DblType molViscIp = + 0.5 * (visc_.get(nodeL, 0) + visc_.get(nodeR, 0)); + const EdgeKernelTraits::DblType rhoIp = + 0.5 * (density_.get(nodeL, 0) + density_.get(nodeR, 0)); + const EdgeKernelTraits::DblType tkeIp = + 0.5 * (stk::math::max(tke_.get(nodeL, 0), 1.0e-12) + + stk::math::max(tke_.get(nodeR, 0), 1.0e-12)); + const EdgeKernelTraits::DblType sdrIp = + 0.5 * (stk::math::max(sdr_.get(nodeL, 0), 1.0e-12) + + stk::math::max(sdr_.get(nodeR, 0), 1.0e-12)); + const EdgeKernelTraits::DblType alphaIp = + 0.5 * (stk::math::pow(beta_.get(nodeL, 0), alphaPow_) + + stk::math::pow(beta_.get(nodeR, 0), alphaPow_)); + + EdgeKernelTraits::DblType avgdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType fluctdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + EdgeKernelTraits::DblType axdx = 0.0; + EdgeKernelTraits::DblType asq = 0.0; + for (int d = 0; d < ndim; ++d) { + const EdgeKernelTraits::DblType dxj = + coordinates_.get(nodeR, d) - coordinates_.get(nodeL, d); + asq += av[d] * av[d]; + axdx += av[d] * dxj; + } + const EdgeKernelTraits::DblType inv_axdx = 1.0 / axdx; + + // Compute average divU + for (int i = 0; i < ndim; ++i) { + + // difference between R and L nodes for component i + const EdgeKernelTraits::DblType avgUidiff = + avgVelocity_.get(nodeR, i) - avgVelocity_.get(nodeL, i); + const EdgeKernelTraits::DblType fluctUidiff = + (velocity_.get(nodeR, i) - velocity_.get(nodeL, i)) - avgUidiff; + + const int offSetI = ndim * i; + + // start sum for NOC contribution + EdgeKernelTraits::DblType GlavgUidxl = 0.0; + EdgeKernelTraits::DblType GlfluctUidxl = 0.0; + for (int l = 0; l < ndim; ++l) { + const int offSetIL = offSetI + l; + const EdgeKernelTraits::DblType dxl = + coordinates_.get(nodeR, l) - coordinates_.get(nodeL, l); + const EdgeKernelTraits::DblType GlavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIL) + avgDudx_.get(nodeR, offSetIL)); + const EdgeKernelTraits::DblType GlfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIL) + dudx_.get(nodeR, offSetIL)) - + GlavgUi; + GlavgUidxl += GlavgUi * dxl; + GlfluctUidxl += GlfluctUi * dxl; + } + + // form full tensor dui/dxj with NOC + for (int j = 0; j < ndim; ++j) { + const int offSetIJ = offSetI + j; + const EdgeKernelTraits::DblType GjavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIJ) + avgDudx_.get(nodeR, offSetIJ)); + const EdgeKernelTraits::DblType GjfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIJ) + dudx_.get(nodeR, offSetIJ)) - + GjavgUi; + avgdUidxj[i][j] = GjavgUi + (avgUidiff - GlavgUidxl) * av[j] * inv_axdx; + fluctdUidxj[i][j] = + GjfluctUi + (fluctUidiff - GlfluctUidxl) * av[j] * inv_axdx; + } + } + + EdgeKernelTraits::DblType avgDivU = 0.0; + for (int i = 0; i < ndim; ++i) { + avgDivU += avgdUidxj[i][i]; + } + + const EdgeKernelTraits::DblType ReT = rhoIp * tkeIp / sdrIp / molViscIp; + const EdgeKernelTraits::DblType Rbeta = 8.0; + const EdgeKernelTraits::DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + + const EdgeKernelTraits::DblType epsilon13Ip = + stk::math::pow(betaStarLowRe * tkeIp * sdrIp, 1.0 / 3.0); + + for (int i = 0; i < ndim; ++i) { + // Left and right row/col indices + const int rowL = i; + const int rowR = i + ndim; + + // This is the divU term for the average quantities in the model for + // tau_ij^SGRS Since we are letting SST calculate it's normal mu_t, we + // need to scale by alpha here + const EdgeKernelTraits::DblType avgDivUstress = + 2.0 / 3.0 * stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * + muIp * avgDivU * av[i] * includeDivU_; + smdata.rhs(rowL) -= avgDivUstress; + smdata.rhs(rowR) += avgDivUstress; + + EdgeKernelTraits::DblType lhs_riC_i = 0.0; + EdgeKernelTraits::DblType lhs_riC_SGRS_i = 0.0; + for (int j = 0; j < ndim; ++j) { + + // -mut^jk*dui/dxk*A_j; fixed i over j loop; see below.. + EdgeKernelTraits::DblType rhsfacDiff_i = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_i = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_i += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[j][k] * av[k] * av[j] * inv_axdx; + rhsfacDiff_i += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[j][k] * fluctdUidxj[i][k] * av[j]; + } + + lhsfacDiff_i += -arInvScale * muIp * av[j] * av[j] * inv_axdx; + rhsfacDiff_i += -arInvScale * muIp * fluctdUidxj[i][j] * av[j]; + + // Accumulate lhs + lhs_riC_i += lhsfacDiff_i; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_i = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[i][j] * av[j]; + + // Implicit treatment of SGRS (average) term + lhs_riC_SGRS_i += -stk::math::pow(alphaIp, alphaScaPow_) * + (2.0 - alphaIp) * muIp * av[j] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_i + rhsSGRSfacDiff_i; + smdata.rhs(rowR) += rhsfacDiff_i + rhsSGRSfacDiff_i; + + // -mut^ik*duj/dxk*A_j + EdgeKernelTraits::DblType rhsfacDiff_j = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_j = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_j += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[i][k] * av[k] * av[j] * inv_axdx; + rhsfacDiff_j += -rhoIp * CM43scale * CM43 * epsilon13Ip * arScale * + M43[i][k] * fluctdUidxj[j][k] * av[j]; + } + + lhsfacDiff_j += -arInvScale * muIp * av[i] * av[j] * inv_axdx; + rhsfacDiff_j += -arInvScale * muIp * fluctdUidxj[j][i] * av[j]; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[j][i] * av[j]; + + // Implicit treatment of SGRS (average) term + const EdgeKernelTraits::DblType lhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + av[i] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_j + rhsSGRSfacDiff_j; + smdata.rhs(rowR) += rhsfacDiff_j + rhsSGRSfacDiff_j; + + const int colL = j; + const int colR = j + ndim; + + smdata.lhs(rowL, colL) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + smdata.lhs(rowL, colR) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colL) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colR) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + } + + smdata.lhs(rowL, rowL) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + smdata.lhs(rowL, rowR) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowL) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowR) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + } +} + +} // namespace nalu +} // namespace sierra diff --git a/src/edge_kernels/MomentumSSTAMSDiffEdgeKernel.C b/src/edge_kernels/MomentumSSTAMSDiffEdgeKernel.C index 7e9a4f745..351b94dd3 100644 --- a/src/edge_kernels/MomentumSSTAMSDiffEdgeKernel.C +++ b/src/edge_kernels/MomentumSSTAMSDiffEdgeKernel.C @@ -28,6 +28,8 @@ MomentumSSTAMSDiffEdgeKernel::MomentumSSTAMSDiffEdgeKernel( betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), CMdeg_(solnOpts.get_turb_model_constant(TM_CMdeg)), aspectRatioSwitch_(solnOpts.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(solnOpts.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(solnOpts.get_turb_model_constant(TM_alphaScaPow)), nDim_(bulk.mesh_meta_data().spatial_dimension()) { const auto& meta = bulk.mesh_meta_data(); @@ -158,8 +160,8 @@ MomentumSSTAMSDiffEdgeKernel::execute( 0.5 * (stk::math::max(sdr_.get(nodeL, 0), 1.0e-12) + stk::math::max(sdr_.get(nodeR, 0), 1.0e-12)); const EdgeKernelTraits::DblType alphaIp = - 0.5 * (stk::math::pow(beta_.get(nodeL, 0), 1.7) + - stk::math::pow(beta_.get(nodeR, 0), 1.7)); + 0.5 * (stk::math::pow(beta_.get(nodeL, 0), alphaPow_) + + stk::math::pow(beta_.get(nodeR, 0), alphaPow_)); EdgeKernelTraits::DblType avgdUidxj[EdgeKernelTraits::NDimMax] [EdgeKernelTraits::NDimMax]; @@ -232,8 +234,8 @@ MomentumSSTAMSDiffEdgeKernel::execute( // tau_ij^SGRS Since we are letting SST calculate it's normal mu_t, we // need to scale by alpha here const EdgeKernelTraits::DblType avgDivUstress = - 2.0 / 3.0 * alphaIp * (2.0 - alphaIp) * muIp * avgDivU * av[i] * - includeDivU_; + 2.0 / 3.0 * stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * + muIp * avgDivU * av[i] * includeDivU_; smdata.rhs(rowL) -= avgDivUstress; smdata.rhs(rowR) += avgDivUstress; @@ -259,11 +261,12 @@ MomentumSSTAMSDiffEdgeKernel::execute( // SGRS (average) term, scaled by alpha const EdgeKernelTraits::DblType rhsSGRSfacDiff_i = - -alphaIp * (2.0 - alphaIp) * muIp * avgdUidxj[i][j] * av[j]; + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[i][j] * av[j]; // Implicit treatment of SGRS (average) term - lhs_riC_SGRS_i += - -alphaIp * (2.0 - alphaIp) * muIp * av[j] * av[j] * inv_axdx; + lhs_riC_SGRS_i += -stk::math::pow(alphaIp, alphaScaPow_) * + (2.0 - alphaIp) * muIp * av[j] * av[j] * inv_axdx; smdata.rhs(rowL) -= rhsfacDiff_i + rhsSGRSfacDiff_i; smdata.rhs(rowR) += rhsfacDiff_i + rhsSGRSfacDiff_i; @@ -283,11 +286,13 @@ MomentumSSTAMSDiffEdgeKernel::execute( // SGRS (average) term, scaled by alpha const EdgeKernelTraits::DblType rhsSGRSfacDiff_j = - -alphaIp * (2.0 - alphaIp) * muIp * avgdUidxj[j][i] * av[j]; + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[j][i] * av[j]; // Implicit treatment of SGRS (average) term const EdgeKernelTraits::DblType lhsSGRSfacDiff_j = - -alphaIp * (2.0 - alphaIp) * muIp * av[i] * av[j] * inv_axdx; + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + av[i] * av[j] * inv_axdx; smdata.rhs(rowL) -= rhsfacDiff_j + rhsSGRSfacDiff_j; smdata.rhs(rowR) += rhsfacDiff_j + rhsSGRSfacDiff_j; diff --git a/src/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.C b/src/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.C new file mode 100644 index 000000000..ea7330b71 --- /dev/null +++ b/src/edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.C @@ -0,0 +1,337 @@ +// 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 "edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "EigenDecomposition.h" + +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" +#include "utils/StkHelpers.h" +#include "utils/AMSUtils.h" +#include + +namespace sierra { +namespace nalu { + +MomentumSSTLRAMSDiffEdgeKernel::MomentumSSTLRAMSDiffEdgeKernel( + const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) + : NGPEdgeKernel(), + includeDivU_(solnOpts.includeDivU_), + betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), + CMdeg_(solnOpts.get_turb_model_constant(TM_CMdeg)), + aspectRatioSwitch_(solnOpts.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(solnOpts.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(solnOpts.get_turb_model_constant(TM_alphaScaPow)), + nDim_(bulk.mesh_meta_data().spatial_dimension()) +{ + const auto& meta = bulk.mesh_meta_data(); + + edgeAreaVecID_ = + get_field_ordinal(meta, "edge_area_vector", stk::topology::EDGE_RANK); + + coordinatesID_ = get_field_ordinal(meta, solnOpts.get_coordinates_name()); + velocityID_ = get_field_ordinal(meta, "velocity"); + turbViscID_ = get_field_ordinal(meta, "turbulent_viscosity"); + viscID_ = get_field_ordinal(meta, "viscosity"); + densityNp1ID_ = get_field_ordinal(meta, "density", stk::mesh::StateNP1); + tkeNp1ID_ = get_field_ordinal(meta, "turbulent_ke", stk::mesh::StateNP1); + sdrNp1ID_ = + get_field_ordinal(meta, "specific_dissipation_rate", stk::mesh::StateNP1); + betaID_ = get_field_ordinal(meta, "k_ratio"); + MijID_ = get_field_ordinal(meta, "metric_tensor"); + fOneBlendID_ = get_field_ordinal(meta, "sst_f_one_blending"); + dudxID_ = get_field_ordinal(meta, "dudx"); + + // average quantities + avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); + avgDudxID_ = get_field_ordinal(meta, "average_dudx"); + avgResAdeqID_ = get_field_ordinal(meta, "avg_res_adequacy_parameter"); + + const std::string dofName = "velocity"; + relaxFacU_ = solnOpts.get_relaxation_factor(dofName); +} + +KOKKOS_FUNCTION +void +MomentumSSTLRAMSDiffEdgeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + edgeAreaVec_ = fieldMgr.get_field(edgeAreaVecID_); + coordinates_ = fieldMgr.get_field(coordinatesID_); + velocity_ = fieldMgr.get_field(velocityID_); + tvisc_ = fieldMgr.get_field(turbViscID_); + visc_ = fieldMgr.get_field(viscID_); + density_ = fieldMgr.get_field(densityNp1ID_); + tke_ = fieldMgr.get_field(tkeNp1ID_); + sdr_ = fieldMgr.get_field(sdrNp1ID_); + beta_ = fieldMgr.get_field(betaID_); + nodalMij_ = fieldMgr.get_field(MijID_); + fOneBlend_ = fieldMgr.get_field(fOneBlendID_); + dudx_ = fieldMgr.get_field(dudxID_); + avgVelocity_ = fieldMgr.get_field(avgVelocityID_); + avgDudx_ = fieldMgr.get_field(avgDudxID_); + avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); +} + +void +MomentumSSTLRAMSDiffEdgeKernel::execute( + EdgeKernelTraits::ShmemDataType& smdata, + const stk::mesh::FastMeshIndex& edge, + const stk::mesh::FastMeshIndex& nodeL, + const stk::mesh::FastMeshIndex& nodeR) +{ + const int ndim = nDim_; + + // Scratch work arrays + NALU_ALIGNED EdgeKernelTraits::DblType av[EdgeKernelTraits::NDimMax]; + + for (int d = 0; d < nDim_; d++) { + av[d] = edgeAreaVec_.get(edge, d); + } + + // Mij, eigenvectors and eigenvalues + EdgeKernelTraits::DblType Mij[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType Q[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType D[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + Mij[i][j] = 0.5 * (nodalMij_.get(nodeL, i * ndim + j) + + nodalMij_.get(nodeR, i * ndim + j)); + + EigenDecomposition::sym_diagonalize(Mij, Q, D); + + // At this point we have Q, the eigenvectors and D the eigenvalues of Mij, + // so to create M43, we use Q D^(4/3) Q^T + EdgeKernelTraits::DblType M43[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + for (int i = 0; i < ndim; i++) + for (int j = 0; j < ndim; j++) + M43[i][j] = 0.0; + + const double fourThirds = 4. / 3.; + for (int k = 0; k < ndim; k++) { + const EdgeKernelTraits::DblType D43 = stk::math::pow(D[k][k], fourThirds); + for (int i = 0; i < ndim; i++) { + for (int j = 0; j < ndim; j++) { + M43[i][j] += Q[i][k] * Q[j][k] * D43; + } + } + } + + // Compute cell aspect ratio blending + const EdgeKernelTraits::DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + const EdgeKernelTraits::DblType aspectRatio = maxEigM / minEigM; + + const EdgeKernelTraits::DblType arScale = + 1.0 - stk::math::tanh(stk::math::max( + 0.5 * (avgResAdeq_.get(nodeL, 0) + avgResAdeq_.get(nodeR, 0)) - 1.0, + 0.0)); + + const EdgeKernelTraits::DblType arInvScale = 1.0 - arScale; + + // Compute CM43 + EdgeKernelTraits::DblType CM43 = ams_utils::get_M43_constant< + EdgeKernelTraits::DblType, EdgeKernelTraits::NDimMax>(D, CMdeg_); + + const EdgeKernelTraits::DblType CM43scale = stk::math::max( + stk::math::min( + 0.5 * (stk::math::pow(avgResAdeq_.get(nodeL, 0), 2.0) + + stk::math::pow(avgResAdeq_.get(nodeR, 0), 2.0)), + 30.0), + 1.0); + + const EdgeKernelTraits::DblType muIp = + 0.5 * (tvisc_.get(nodeL, 0) + tvisc_.get(nodeR, 0)); + const EdgeKernelTraits::DblType rhoIp = + 0.5 * (density_.get(nodeL, 0) + density_.get(nodeR, 0)); + const EdgeKernelTraits::DblType tkeIp = + 0.5 * (stk::math::max(tke_.get(nodeL, 0), 1.0e-12) + + stk::math::max(tke_.get(nodeR, 0), 1.0e-12)); + const EdgeKernelTraits::DblType sdrIp = + 0.5 * (stk::math::max(sdr_.get(nodeL, 0), 1.0e-12) + + stk::math::max(sdr_.get(nodeR, 0), 1.0e-12)); + const EdgeKernelTraits::DblType alphaIp = + 0.5 * (stk::math::pow(beta_.get(nodeL, 0), alphaPow_) + + stk::math::pow(beta_.get(nodeR, 0), alphaPow_)); + const EdgeKernelTraits::DblType fOneBlendIp = + 0.5 * (fOneBlend_.get(nodeL, 0) + fOneBlend_.get(nodeR, 0)); + const EdgeKernelTraits::DblType molViscIp = + 0.5 * (visc_.get(nodeL, 0) + visc_.get(nodeR, 0)); + + EdgeKernelTraits::DblType avgdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + EdgeKernelTraits::DblType fluctdUidxj[EdgeKernelTraits::NDimMax] + [EdgeKernelTraits::NDimMax]; + + EdgeKernelTraits::DblType axdx = 0.0; + EdgeKernelTraits::DblType asq = 0.0; + for (int d = 0; d < ndim; ++d) { + const EdgeKernelTraits::DblType dxj = + coordinates_.get(nodeR, d) - coordinates_.get(nodeL, d); + asq += av[d] * av[d]; + axdx += av[d] * dxj; + } + const EdgeKernelTraits::DblType inv_axdx = 1.0 / axdx; + + // Compute average divU + for (int i = 0; i < ndim; ++i) { + + // difference between R and L nodes for component i + const EdgeKernelTraits::DblType avgUidiff = + avgVelocity_.get(nodeR, i) - avgVelocity_.get(nodeL, i); + const EdgeKernelTraits::DblType fluctUidiff = + (velocity_.get(nodeR, i) - velocity_.get(nodeL, i)) - avgUidiff; + + const int offSetI = ndim * i; + + // start sum for NOC contribution + EdgeKernelTraits::DblType GlavgUidxl = 0.0; + EdgeKernelTraits::DblType GlfluctUidxl = 0.0; + for (int l = 0; l < ndim; ++l) { + const int offSetIL = offSetI + l; + const EdgeKernelTraits::DblType dxl = + coordinates_.get(nodeR, l) - coordinates_.get(nodeL, l); + const EdgeKernelTraits::DblType GlavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIL) + avgDudx_.get(nodeR, offSetIL)); + const EdgeKernelTraits::DblType GlfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIL) + dudx_.get(nodeR, offSetIL)) - + GlavgUi; + GlavgUidxl += GlavgUi * dxl; + GlfluctUidxl += GlfluctUi * dxl; + } + + // form full tensor dui/dxj with NOC + for (int j = 0; j < ndim; ++j) { + const int offSetIJ = offSetI + j; + const EdgeKernelTraits::DblType GjavgUi = + 0.5 * (avgDudx_.get(nodeL, offSetIJ) + avgDudx_.get(nodeR, offSetIJ)); + const EdgeKernelTraits::DblType GjfluctUi = + 0.5 * (dudx_.get(nodeL, offSetIJ) + dudx_.get(nodeR, offSetIJ)) - + GjavgUi; + avgdUidxj[i][j] = GjavgUi + (avgUidiff - GlavgUidxl) * av[j] * inv_axdx; + fluctdUidxj[i][j] = + GjfluctUi + (fluctUidiff - GlfluctUidxl) * av[j] * inv_axdx; + } + } + + EdgeKernelTraits::DblType avgDivU = 0.0; + for (int i = 0; i < ndim; ++i) { + avgDivU += avgdUidxj[i][i]; + } + + const EdgeKernelTraits::DblType ReT = rhoIp * tkeIp / sdrIp / molViscIp; + const EdgeKernelTraits::DblType Rbeta = 8.0; + const EdgeKernelTraits::DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + const EdgeKernelTraits::DblType betaStarBlend = + fOneBlendIp * betaStarLowRe + (1.0 - fOneBlendIp) * betaStar_; + + const EdgeKernelTraits::DblType epsilon13Ip = + stk::math::pow(betaStarBlend * tkeIp * sdrIp, 1.0 / 3.0); + + for (int i = 0; i < ndim; ++i) { + // Left and right row/col indices + const int rowL = i; + const int rowR = i + ndim; + + // This is the divU term for the average quantities in the model for + // tau_ij^SGRS Since we are letting SST calculate it's normal mu_t, we + // need to scale by alpha here + const EdgeKernelTraits::DblType avgDivUstress = + 2.0 / 3.0 * stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * + muIp * avgDivU * av[i] * includeDivU_; + smdata.rhs(rowL) -= avgDivUstress; + smdata.rhs(rowR) += avgDivUstress; + + EdgeKernelTraits::DblType lhs_riC_i = 0.0; + EdgeKernelTraits::DblType lhs_riC_SGRS_i = 0.0; + for (int j = 0; j < ndim; ++j) { + + // -mut^jk*dui/dxk*A_j; fixed i over j loop; see below.. + EdgeKernelTraits::DblType rhsfacDiff_i = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_i = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_i += -rhoIp * CMdeg_ * epsilon13Ip * arScale * M43[j][k] * + av[k] * av[j] * inv_axdx; + rhsfacDiff_i += -rhoIp * CMdeg_ * epsilon13Ip * arScale * M43[j][k] * + fluctdUidxj[i][k] * av[j]; + } + + lhsfacDiff_i += -arInvScale * muIp * av[j] * av[j] * inv_axdx; + rhsfacDiff_i += -arInvScale * muIp * fluctdUidxj[i][j] * av[j]; + + // Accumulate lhs + lhs_riC_i += lhsfacDiff_i; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_i = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[i][j] * av[j]; + + // Implicit treatment of SGRS (average) term + lhs_riC_SGRS_i += -stk::math::pow(alphaIp, alphaScaPow_) * + (2.0 - alphaIp) * muIp * av[j] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_i + rhsSGRSfacDiff_i; + smdata.rhs(rowR) += rhsfacDiff_i + rhsSGRSfacDiff_i; + + // -mut^ik*duj/dxk*A_j + EdgeKernelTraits::DblType rhsfacDiff_j = 0.0; + EdgeKernelTraits::DblType lhsfacDiff_j = 0.0; + for (int k = 0; k < ndim; ++k) { + lhsfacDiff_j += -rhoIp * CMdeg_ * epsilon13Ip * arScale * M43[i][k] * + av[k] * av[j] * inv_axdx; + rhsfacDiff_j += -rhoIp * CMdeg_ * epsilon13Ip * arScale * M43[i][k] * + fluctdUidxj[j][k] * av[j]; + } + + lhsfacDiff_j += -arInvScale * muIp * av[i] * av[j] * inv_axdx; + rhsfacDiff_j += -arInvScale * muIp * fluctdUidxj[j][i] * av[j]; + + // SGRS (average) term, scaled by alpha + const EdgeKernelTraits::DblType rhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + avgdUidxj[j][i] * av[j]; + + // Implicit treatment of SGRS (average) term + const EdgeKernelTraits::DblType lhsSGRSfacDiff_j = + -stk::math::pow(alphaIp, alphaScaPow_) * (2.0 - alphaIp) * muIp * + av[i] * av[j] * inv_axdx; + + smdata.rhs(rowL) -= rhsfacDiff_j + rhsSGRSfacDiff_j; + smdata.rhs(rowR) += rhsfacDiff_j + rhsSGRSfacDiff_j; + + const int colL = j; + const int colR = j + ndim; + + smdata.lhs(rowL, colL) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + smdata.lhs(rowL, colR) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colL) += (lhsfacDiff_j + lhsSGRSfacDiff_j); + smdata.lhs(rowR, colR) -= (lhsfacDiff_j + lhsSGRSfacDiff_j) / relaxFacU_; + } + + smdata.lhs(rowL, rowL) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + smdata.lhs(rowL, rowR) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowL) += (lhs_riC_i + lhs_riC_SGRS_i); + smdata.lhs(rowR, rowR) -= (lhs_riC_i + lhs_riC_SGRS_i) / relaxFacU_; + } +} + +} // namespace nalu +} // namespace sierra diff --git a/src/ngp_algorithms/AMSAveragesAlg.C b/src/ngp_algorithms/AMSAveragesAlg.C new file mode 100644 index 000000000..bbf4381c8 --- /dev/null +++ b/src/ngp_algorithms/AMSAveragesAlg.C @@ -0,0 +1,29 @@ +// 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 "ngp_algorithms/AMSAveragesAlg.h" +#include "ngp_utils/NgpLoopUtils.h" +#include "ngp_utils/NgpTypes.h" +#include "ngp_utils/NgpFieldManager.h" +#include "Realm.h" +#include "utils/StkHelpers.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/NgpMesh.hpp" +#include "EigenDecomposition.h" +#include "utils/AMSUtils.h" + +namespace sierra { +namespace nalu { + +AMSAveragesAlg::AMSAveragesAlg(Realm& realm, stk::mesh::Part* part) + : Algorithm(realm, part) +{ +} +} // namespace nalu +} // namespace sierra diff --git a/src/ngp_algorithms/CMakeLists.txt b/src/ngp_algorithms/CMakeLists.txt index 87ba9cec7..0e0fdc816 100644 --- a/src/ngp_algorithms/CMakeLists.txt +++ b/src/ngp_algorithms/CMakeLists.txt @@ -14,7 +14,11 @@ target_sources(nalu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/MdotOpenCorrectorAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/MdotOpenEdgeAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/AMSAvgMdotEdgeAlg.C + ${CMAKE_CURRENT_SOURCE_DIR}/AMSAveragesAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/SSTAMSAveragesAlg.C + ${CMAKE_CURRENT_SOURCE_DIR}/SSTLRAMSAveragesAlg.C + ${CMAKE_CURRENT_SOURCE_DIR}/KEAMSAveragesAlg.C + ${CMAKE_CURRENT_SOURCE_DIR}/KOAMSAveragesAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/MetricTensorElemAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/TurbViscKsgsAlg.C ${CMAKE_CURRENT_SOURCE_DIR}/TurbViscSSTAlg.C diff --git a/src/ngp_algorithms/KEAMSAveragesAlg.C b/src/ngp_algorithms/KEAMSAveragesAlg.C new file mode 100644 index 000000000..4afb323f7 --- /dev/null +++ b/src/ngp_algorithms/KEAMSAveragesAlg.C @@ -0,0 +1,402 @@ +// 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 "ngp_algorithms/KEAMSAveragesAlg.h" +#include "ngp_utils/NgpLoopUtils.h" +#include "ngp_utils/NgpTypes.h" +#include "ngp_utils/NgpFieldManager.h" +#include "Realm.h" +#include "utils/StkHelpers.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/NgpMesh.hpp" +#include "EigenDecomposition.h" +#include "utils/AMSUtils.h" + +namespace sierra { +namespace nalu { + +KEAMSAveragesAlg::KEAMSAveragesAlg(Realm& realm, stk::mesh::Part* part) + : AMSAveragesAlg(realm, part), + CMdeg_(realm.get_turb_model_constant(TM_CMdeg)), + v2cMu_(realm.get_turb_model_constant(TM_v2cMu)), + aspectRatioSwitch_(realm.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(realm.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(realm.get_turb_model_constant(TM_alphaScaPow)), + coeffR_(realm.get_turb_model_constant(TM_coeffR)), + meshMotion_(realm.does_mesh_move()), + velocity_(get_field_ordinal(realm.meta_data(), "velocity")), + density_(get_field_ordinal(realm.meta_data(), "density")), + dudx_(get_field_ordinal(realm.meta_data(), "dudx")), + resAdeq_( + get_field_ordinal(realm.meta_data(), "resolution_adequacy_parameter")), + turbKineticEnergy_(get_field_ordinal(realm.meta_data(), "turbulent_ke")), + totDissipationRate_( + get_field_ordinal(realm.meta_data(), "total_dissipation_rate")), + avgVelocity_(get_field_ordinal(realm.meta_data(), "average_velocity")), + avgVelocityN_(get_field_ordinal( + realm.meta_data(), "average_velocity", stk::mesh::StateN)), + avgDudx_(get_field_ordinal(realm.meta_data(), "average_dudx")), + avgDudxN_( + get_field_ordinal(realm.meta_data(), "average_dudx", stk::mesh::StateN)), + avgTkeRes_(get_field_ordinal(realm.meta_data(), "average_tke_resolved")), + avgTkeResN_(get_field_ordinal( + realm.meta_data(), "average_tke_resolved", stk::mesh::StateN)), + avgProd_(get_field_ordinal(realm.meta_data(), "average_production")), + avgProdN_(get_field_ordinal( + realm.meta_data(), "average_production", stk::mesh::StateN)), + avgTime_(get_field_ordinal(realm.meta_data(), "rans_time_scale")), + avgResAdeq_( + get_field_ordinal(realm.meta_data(), "avg_res_adequacy_parameter")), + avgResAdeqN_(get_field_ordinal( + realm.meta_data(), "avg_res_adequacy_parameter", stk::mesh::StateN)), + tvisc_(get_field_ordinal(realm.meta_data(), "turbulent_viscosity")), + visc_(get_field_ordinal(realm.meta_data(), "viscosity")), + beta_(get_field_ordinal(realm.meta_data(), "k_ratio")), + Mij_(get_field_ordinal(realm.meta_data(), "metric_tensor")), + wallDist_(get_field_ordinal(realm.meta_data(), "minimum_distance_to_wall")) +{ +} + +void +KEAMSAveragesAlg::execute() +{ + using Traits = nalu_ngp::NGPMeshTraits; + + const auto& meta = realm_.meta_data(); + if (meta.spatial_dimension() != 3) { + throw std::runtime_error("KEAMSAveragesAlg only supported in 3D."); + } + const DblType dt = realm_.get_time_step(); + + const stk::mesh::Selector sel = + (meta.locally_owned_part() | meta.globally_shared_part()) & + stk::mesh::selectField( + *meta.get_field(stk::topology::NODE_RANK, "average_velocity")); + + const auto& meshInfo = realm_.mesh_info(); + const auto ngpMesh = meshInfo.ngp_mesh(); + const auto& fieldMgr = meshInfo.ngp_field_manager(); + + const auto tvisc = fieldMgr.get_field(tvisc_); + const auto visc = fieldMgr.get_field(visc_); + const auto tke = fieldMgr.get_field(turbKineticEnergy_); + const auto tdr = fieldMgr.get_field(totDissipationRate_); + const auto density = fieldMgr.get_field(density_); + auto beta = fieldMgr.get_field(beta_); + auto avgProd = fieldMgr.get_field(avgProd_); + auto avgProdN = fieldMgr.get_field(avgProdN_); + auto avgTkeRes = fieldMgr.get_field(avgTkeRes_); + auto avgTkeResN = fieldMgr.get_field(avgTkeResN_); + auto avgTime = fieldMgr.get_field(avgTime_); + auto resAdeq = fieldMgr.get_field(resAdeq_); + auto avgResAdeq = fieldMgr.get_field(avgResAdeq_); + auto avgResAdeqN = fieldMgr.get_field(avgResAdeqN_); + const auto vel = fieldMgr.get_field(velocity_); + const auto dudx = fieldMgr.get_field(dudx_); + auto avgVel = fieldMgr.get_field(avgVelocity_); + auto avgVelN = fieldMgr.get_field(avgVelocityN_); + auto avgDudx = fieldMgr.get_field(avgDudx_); + auto avgDudxN = fieldMgr.get_field(avgDudxN_); + const auto Mij = fieldMgr.get_field(Mij_); + const auto wallDist = fieldMgr.get_field(wallDist_); + + const DblType CMdeg = CMdeg_; + const DblType v2cMu = v2cMu_; + const DblType beta_kol_local = beta_kol; + const DblType aspectRatioSwitch = aspectRatioSwitch_; + const DblType alphaPow = alphaPow_; + const DblType alphaScaPow = alphaScaPow_; + const DblType coeffR = coeffR_; + + nalu_ngp::run_entity_algorithm( + "KEAMSAveragesAlg_computeAverages", ngpMesh, stk::topology::NODE_RANK, sel, + KOKKOS_LAMBDA(const Traits::MeshIndex& mi) { + // Calculate alpha + if (tke.get(mi, 0) == 0.0) + beta.get(mi, 0) = 1.0; + else { + beta.get(mi, 0) = + (tke.get(mi, 0) - avgTkeRes.get(mi, 0)) / tke.get(mi, 0); + + // limiters + beta.get(mi, 0) = stk::math::min(beta.get(mi, 0), 1.0); + + beta.get(mi, 0) = stk::math::max(beta.get(mi, 0), beta_kol_local); + } + + const DblType alpha = stk::math::pow(beta.get(mi, 0), alphaPow); + + // store RANS time scale + avgTime.get(mi, 0) = tke.get(mi, 0) / tdr.get(mi, 0); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType weightAvg = + stk::math::max(1.0 - dt / avgTime.get(mi, 0), 0.0); + const DblType weightInst = stk::math::min(dt / avgTime.get(mi, 0), 1.0); + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + avgVel.get(mi, i) = + weightAvg * avgVelN.get(mi, i) + weightInst * vel.get(mi, i); + + DblType tkeRes = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tkeRes += (vel.get(mi, i) - avgVel.get(mi, i)) * + (vel.get(mi, i) - avgVel.get(mi, i)); + + avgTkeRes.get(mi, 0) = + weightAvg * avgTkeResN.get(mi, 0) + weightInst * 0.5 * tkeRes; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) = + weightAvg * avgDudxN.get(mi, i * nalu_ngp::NDimMax + j) + + weightInst * dudx.get(mi, i * nalu_ngp::NDimMax + j); + } + } + + // Production averaging + DblType tij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + const DblType avgSij = + 0.5 * (avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + tij[i][j] = 2.0 * stk::math::pow(alpha, alphaScaPow) * (2.0 - alpha) * + tvisc.get(mi, 0) * avgSij; + } + } + + DblType Pij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + Pij[i][j] = 0.0; + for (int m = 0; m < nalu_ngp::NDimMax; ++m) { + Pij[i][j] += + avgDudx.get(mi, i * nalu_ngp::NDimMax + m) * tij[j][m] + + avgDudx.get(mi, j * nalu_ngp::NDimMax + m) * tij[i][m]; + } + Pij[i][j] *= 0.5; + } + } + + DblType P_res = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + P_res += density.get(mi, 0) * + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) * + ((avgVel.get(mi, i) - vel.get(mi, i)) * + (avgVel.get(mi, j) - vel.get(mi, j))); + } + } + + DblType instProd = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + instProd += Pij[i][i]; + + instProd -= P_res; + + // Use a longer averaging timescale for production + const DblType prodAvgTime = 4.0 * avgTime.get(mi, 0); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType prodWeightAvg = stk::math::max(1.0 - dt / prodAvgTime, 0.0); + const DblType prodWeightInst = stk::math::min(dt / prodAvgTime, 1.0); + + avgProd.get(mi, 0) = + prodWeightAvg * avgProdN.get(mi, 0) + prodWeightInst * instProd; + + // get Mij field_data + DblType p_Mij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType PM[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Q[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType D[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + const int iNdim = i * nalu_ngp::NDimMax; + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + p_Mij[i][j] = Mij.get(mi, iNdim + j); + } + } + + // Eigenvalue decomposition of metric tensor + EigenDecomposition::sym_diagonalize(p_Mij, Q, D); + + // initialize M43 to 0 + DblType M43[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + M43[i][j] = 0.0; + + const DblType fourThirds = 4.0 / 3.0; + + for (int l = 0; l < nalu_ngp::NDimMax; l++) { + const DblType D43 = stk::math::pow(D[l][l], fourThirds); + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + M43[i][j] += Q[i][l] * Q[j][l] * D43; + } + } + } + + const DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + + const DblType aspectRatio = maxEigM / minEigM; + + // zeroing out tensors + DblType tauSGRS[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tauSGET[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tau[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Psgs[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + tauSGRS[i][j] = 0.0; + tauSGET[i][j] = 0.0; + tau[i][j] = 0.0; + Psgs[i][j] = 0.0; + } + } + + const DblType CM43 = + ams_utils::get_M43_constant(D, CMdeg); + + const DblType CM43scale = stk::math::max( + stk::math::min(stk::math::pow(avgResAdeq.get(mi, 0), 2.0), 30.0), 1.0); + + const DblType epsilon13 = stk::math::pow(tdr.get(mi, 0), 1.0 / 3.0); + + const DblType arScale = stk::math::if_then_else( + aspectRatio > aspectRatioSwitch, + 1.0 - stk::math::tanh((aspectRatio - aspectRatioSwitch) / 10.0), 1.0); + + const DblType arInvScale = 1.0 - arScale; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + // Calculate tauSGRS_ij = 2*alpha*nu_t* where nu_t comes from + // the SST model and is the strain rate tensor based on the + // mean quantities... i.e this is (tauSGRS = alpha*tauSST) + // The 2 in the coeff cancels with the 1/2 in the strain rate tensor + const DblType coeffSGRS = stk::math::pow(alpha, alphaScaPow) * + (2.0 - alpha) * tvisc.get(mi, 0) / + density.get(mi, 0); + tauSGRS[i][j] = avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i); + tauSGRS[i][j] *= coeffSGRS; + + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + // Calculate tauSGET_ij = CM43*^(1/3)*(M43_ik*dkuj' + + // M43_jkdkui') where is the mean dissipation backed out from + // the SST mean k and mean omega and dkuj' is the fluctuating + // velocity gradients. + const DblType coeffSGET = CM43scale * CM43 * epsilon13; + const DblType fluctDudx_jl = + dudx.get(mi, j * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + l); + const DblType fluctDudx_il = + dudx.get(mi, i * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + l); + tauSGET[i][j] += + coeffSGET * arScale * + (M43[i][l] * fluctDudx_jl + M43[j][l] * fluctDudx_il); + } + tauSGET[i][j] += arInvScale * tvisc.get(mi, 0) / density.get(mi, 0) * + (dudx.get(mi, i * nalu_ngp::NDimMax + j) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + dudx.get(mi, j * nalu_ngp::NDimMax + i) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + } + } + + // Remove trace of tauSGET + DblType tauSGET_tr = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tauSGET_tr += tauSGET[i][i]; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tauSGET[i][i] -= tauSGET_tr / nalu_ngp::NDimMax; + + // Calculate the full subgrid stress including the isotropic portion + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + tau[i][j] = + tauSGRS[i][j] + tauSGET[i][j] - + ((i == j) ? 2.0 / 3.0 * beta.get(mi, 0) * tke.get(mi, 0) : 0.0); + + // Calculate the SGS production PSGS_ij = 1/2(tau_ik*djuk + tau_jk*diuk) + // where diuj is the instantaneous velocity gradients + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + Psgs[i][j] += tau[i][l] * dudx.get(mi, l * nalu_ngp::NDimMax + j) + + tau[j][l] * dudx.get(mi, l * nalu_ngp::NDimMax + i); + } + Psgs[i][j] *= 0.5; + } + } + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + PM[i][j] = 0.0; + for (int l = 0; l < nalu_ngp::NDimMax; ++l) + PM[i][j] += Psgs[i][l] * p_Mij[l][j]; + } + } + + // Scale PM first + const DblType v2 = + 1.0 / v2cMu * + (tvisc.get(mi, 0) / density.get(mi, 0) / avgTime.get(mi, 0)); + const DblType PMscale = + coeffR * stk::math::pow(1.5 * beta.get(mi, 0) * v2, -1.5); + + // Handle case where tke = 0, should only occur at a wall boundary + if (tke.get(mi, 0) == 0.0) + resAdeq.get(mi, 0) = 1.0; + else { + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PM[i][j] = PM[i][j] * PMscale; + + DblType PMmag = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PMmag += PM[i][j] * PM[i][j]; + + PMmag = stk::math::sqrt(PMmag); + + EigenDecomposition::general_eigenvalues(PM, Q, D); + + // Take only positive eigenvalues of PM + DblType maxPM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + + // Update the instantaneous resAdeq field + resAdeq.get(mi, 0) = + stk::math::max(stk::math::min(maxPM, PMmag), 0.00000001); + + resAdeq.get(mi, 0) = stk::math::min(resAdeq.get(mi, 0), 30.0); + + if (alpha >= 1.0) { + resAdeq.get(mi, 0) = stk::math::min(resAdeq.get(mi, 0), 1.0); + } + + if (alpha <= beta_kol_local) + resAdeq.get(mi, 0) = stk::math::max(resAdeq.get(mi, 0), 1.0); + } + + avgResAdeq.get(mi, 0) = + weightAvg * avgResAdeqN.get(mi, 0) + weightInst * resAdeq.get(mi, 0); + }); +} + +} // namespace nalu +} // namespace sierra diff --git a/src/ngp_algorithms/KOAMSAveragesAlg.C b/src/ngp_algorithms/KOAMSAveragesAlg.C new file mode 100644 index 000000000..deac19dd5 --- /dev/null +++ b/src/ngp_algorithms/KOAMSAveragesAlg.C @@ -0,0 +1,412 @@ +// 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 "ngp_algorithms/KOAMSAveragesAlg.h" +#include "ngp_utils/NgpLoopUtils.h" +#include "ngp_utils/NgpTypes.h" +#include "ngp_utils/NgpFieldManager.h" +#include "Realm.h" +#include "utils/StkHelpers.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/NgpMesh.hpp" +#include "EigenDecomposition.h" +#include "utils/AMSUtils.h" + +namespace sierra { +namespace nalu { + +KOAMSAveragesAlg::KOAMSAveragesAlg(Realm& realm, stk::mesh::Part* part) + : AMSAveragesAlg(realm, part), + betaStar_(realm.get_turb_model_constant(TM_betaStar)), + CMdeg_(realm.get_turb_model_constant(TM_CMdeg)), + v2cMu_(realm.get_turb_model_constant(TM_v2cMu)), + aspectRatioSwitch_(realm.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(realm.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(realm.get_turb_model_constant(TM_alphaScaPow)), + coeffR_(realm.get_turb_model_constant(TM_coeffR)), + meshMotion_(realm.does_mesh_move()), + velocity_(get_field_ordinal(realm.meta_data(), "velocity")), + density_(get_field_ordinal(realm.meta_data(), "density")), + dudx_(get_field_ordinal(realm.meta_data(), "dudx")), + resAdeq_( + get_field_ordinal(realm.meta_data(), "resolution_adequacy_parameter")), + turbKineticEnergy_(get_field_ordinal(realm.meta_data(), "turbulent_ke")), + specDissipationRate_( + get_field_ordinal(realm.meta_data(), "specific_dissipation_rate")), + avgVelocity_(get_field_ordinal(realm.meta_data(), "average_velocity")), + avgVelocityN_(get_field_ordinal( + realm.meta_data(), "average_velocity", stk::mesh::StateN)), + avgDudx_(get_field_ordinal(realm.meta_data(), "average_dudx")), + avgDudxN_( + get_field_ordinal(realm.meta_data(), "average_dudx", stk::mesh::StateN)), + avgTkeRes_(get_field_ordinal(realm.meta_data(), "average_tke_resolved")), + avgTkeResN_(get_field_ordinal( + realm.meta_data(), "average_tke_resolved", stk::mesh::StateN)), + avgProd_(get_field_ordinal(realm.meta_data(), "average_production")), + avgProdN_(get_field_ordinal( + realm.meta_data(), "average_production", stk::mesh::StateN)), + avgTime_(get_field_ordinal(realm.meta_data(), "rans_time_scale")), + avgResAdeq_( + get_field_ordinal(realm.meta_data(), "avg_res_adequacy_parameter")), + avgResAdeqN_(get_field_ordinal( + realm.meta_data(), "avg_res_adequacy_parameter", stk::mesh::StateN)), + tvisc_(get_field_ordinal(realm.meta_data(), "turbulent_viscosity")), + visc_(get_field_ordinal(realm.meta_data(), "viscosity")), + beta_(get_field_ordinal(realm.meta_data(), "k_ratio")), + Mij_(get_field_ordinal(realm.meta_data(), "metric_tensor")), + wallDist_(get_field_ordinal(realm.meta_data(), "minimum_distance_to_wall")) +{ +} + +void +KOAMSAveragesAlg::execute() +{ + using Traits = nalu_ngp::NGPMeshTraits; + + const auto& meta = realm_.meta_data(); + if (meta.spatial_dimension() != 3) { + throw std::runtime_error("KOAMSAveragesAlg only supported in 3D."); + } + const DblType dt = realm_.get_time_step(); + + const stk::mesh::Selector sel = + (meta.locally_owned_part() | meta.globally_shared_part()) & + stk::mesh::selectField( + *meta.get_field(stk::topology::NODE_RANK, "average_velocity")); + + const auto& meshInfo = realm_.mesh_info(); + const auto ngpMesh = meshInfo.ngp_mesh(); + const auto& fieldMgr = meshInfo.ngp_field_manager(); + + const auto tvisc = fieldMgr.get_field(tvisc_); + const auto visc = fieldMgr.get_field(visc_); + const auto tke = fieldMgr.get_field(turbKineticEnergy_); + const auto sdr = fieldMgr.get_field(specDissipationRate_); + const auto density = fieldMgr.get_field(density_); + auto beta = fieldMgr.get_field(beta_); + auto avgProd = fieldMgr.get_field(avgProd_); + auto avgProdN = fieldMgr.get_field(avgProdN_); + auto avgTkeRes = fieldMgr.get_field(avgTkeRes_); + auto avgTkeResN = fieldMgr.get_field(avgTkeResN_); + auto avgTime = fieldMgr.get_field(avgTime_); + auto resAdeq = fieldMgr.get_field(resAdeq_); + auto avgResAdeq = fieldMgr.get_field(avgResAdeq_); + auto avgResAdeqN = fieldMgr.get_field(avgResAdeqN_); + const auto vel = fieldMgr.get_field(velocity_); + const auto dudx = fieldMgr.get_field(dudx_); + auto avgVel = fieldMgr.get_field(avgVelocity_); + auto avgVelN = fieldMgr.get_field(avgVelocityN_); + auto avgDudx = fieldMgr.get_field(avgDudx_); + auto avgDudxN = fieldMgr.get_field(avgDudxN_); + const auto Mij = fieldMgr.get_field(Mij_); + const auto wallDist = fieldMgr.get_field(wallDist_); + + const DblType betaStar = betaStar_; + const DblType CMdeg = CMdeg_; + const DblType v2cMu = v2cMu_; + const DblType beta_kol_local = beta_kol; + const DblType aspectRatioSwitch = aspectRatioSwitch_; + const DblType alphaPow = alphaPow_; + const DblType alphaScaPow = alphaScaPow_; + const DblType coeffR = coeffR_; + + nalu_ngp::run_entity_algorithm( + "KOAMSAveragesAlg_computeAverages", ngpMesh, stk::topology::NODE_RANK, sel, + KOKKOS_LAMBDA(const Traits::MeshIndex& mi) { + // Calculate alpha + if (tke.get(mi, 0) == 0.0) + beta.get(mi, 0) = 1.0; + else { + beta.get(mi, 0) = + (tke.get(mi, 0) - avgTkeRes.get(mi, 0)) / tke.get(mi, 0); + + // limiters + beta.get(mi, 0) = stk::math::min(beta.get(mi, 0), 1.0); + + beta.get(mi, 0) = stk::math::max(beta.get(mi, 0), beta_kol_local); + } + + const DblType alpha = stk::math::pow(beta.get(mi, 0), alphaPow); + + const DblType ReT = + density.get(mi, 0) * tke.get(mi, 0) / sdr.get(mi, 0) / visc.get(mi, 0); + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + + // store RANS time scale + avgTime.get(mi, 0) = 1.0 / (betaStarLowRe * sdr.get(mi, 0)); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType weightAvg = + stk::math::max(1.0 - dt / avgTime.get(mi, 0), 0.0); + const DblType weightInst = stk::math::min(dt / avgTime.get(mi, 0), 1.0); + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + avgVel.get(mi, i) = + weightAvg * avgVelN.get(mi, i) + weightInst * vel.get(mi, i); + + DblType tkeRes = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tkeRes += (vel.get(mi, i) - avgVel.get(mi, i)) * + (vel.get(mi, i) - avgVel.get(mi, i)); + + avgTkeRes.get(mi, 0) = + weightAvg * avgTkeResN.get(mi, 0) + weightInst * 0.5 * tkeRes; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) = + weightAvg * avgDudxN.get(mi, i * nalu_ngp::NDimMax + j) + + weightInst * dudx.get(mi, i * nalu_ngp::NDimMax + j); + } + } + + // Production averaging + DblType tij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + const DblType avgSij = + 0.5 * (avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + tij[i][j] = 2.0 * stk::math::pow(alpha, alphaScaPow) * (2.0 - alpha) * + tvisc.get(mi, 0) * avgSij; + } + } + + DblType Pij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + Pij[i][j] = 0.0; + for (int m = 0; m < nalu_ngp::NDimMax; ++m) { + Pij[i][j] += + avgDudx.get(mi, i * nalu_ngp::NDimMax + m) * tij[j][m] + + avgDudx.get(mi, j * nalu_ngp::NDimMax + m) * tij[i][m]; + } + Pij[i][j] *= 0.5; + } + } + + DblType P_res = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + P_res += density.get(mi, 0) * + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) * + ((avgVel.get(mi, i) - vel.get(mi, i)) * + (avgVel.get(mi, j) - vel.get(mi, j))); + } + } + + DblType instProd = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + instProd += Pij[i][i]; + + instProd -= P_res; + + // Use a longer averaging timescale for production + const DblType prodAvgTime = 4.0 * avgTime.get(mi, 0); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType prodWeightAvg = stk::math::max(1.0 - dt / prodAvgTime, 0.0); + const DblType prodWeightInst = stk::math::min(dt / prodAvgTime, 1.0); + + avgProd.get(mi, 0) = + prodWeightAvg * avgProdN.get(mi, 0) + prodWeightInst * instProd; + + // get Mij field_data + DblType p_Mij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType PM[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Q[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType D[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + const int iNdim = i * nalu_ngp::NDimMax; + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + p_Mij[i][j] = Mij.get(mi, iNdim + j); + } + } + + // Eigenvalue decomposition of metric tensor + EigenDecomposition::sym_diagonalize(p_Mij, Q, D); + + // initialize M43 to 0 + DblType M43[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + M43[i][j] = 0.0; + + const DblType fourThirds = 4.0 / 3.0; + + for (int l = 0; l < nalu_ngp::NDimMax; l++) { + const DblType D43 = stk::math::pow(D[l][l], fourThirds); + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + M43[i][j] += Q[i][l] * Q[j][l] * D43; + } + } + } + + const DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + + const DblType aspectRatio = maxEigM / minEigM; + + // zeroing out tensors + DblType tauSGRS[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tauSGET[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tau[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Psgs[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + tauSGRS[i][j] = 0.0; + tauSGET[i][j] = 0.0; + tau[i][j] = 0.0; + Psgs[i][j] = 0.0; + } + } + + const DblType CM43 = + ams_utils::get_M43_constant(D, CMdeg); + + const DblType CM43scale = stk::math::max( + stk::math::min(stk::math::pow(avgResAdeq.get(mi, 0), 2.0), 30.0), 1.0); + + const DblType epsilon13 = stk::math::pow( + betaStarLowRe * tke.get(mi, 0) * sdr.get(mi, 0), 1.0 / 3.0); + + const DblType arScale = stk::math::if_then_else( + aspectRatio > aspectRatioSwitch, + 1.0 - stk::math::tanh((aspectRatio - aspectRatioSwitch) / 10.0), 1.0); + + const DblType arInvScale = 1.0 - arScale; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + // Calculate tauSGRS_ij = 2*alpha*nu_t* where nu_t comes from + // the SST model and is the strain rate tensor based on the + // mean quantities... i.e this is (tauSGRS = alpha*tauSST) + // The 2 in the coeff cancels with the 1/2 in the strain rate tensor + const DblType coeffSGRS = stk::math::pow(alpha, alphaScaPow) * + (2.0 - alpha) * tvisc.get(mi, 0) / + density.get(mi, 0); + tauSGRS[i][j] = avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i); + tauSGRS[i][j] *= coeffSGRS; + + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + // Calculate tauSGET_ij = CM43*^(1/3)*(M43_ik*dkuj' + + // M43_jkdkui') where is the mean dissipation backed out from + // the SST mean k and mean omega and dkuj' is the fluctuating + // velocity gradients. + const DblType coeffSGET = CM43scale * CM43 * epsilon13; + const DblType fluctDudx_jl = + dudx.get(mi, j * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + l); + const DblType fluctDudx_il = + dudx.get(mi, i * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + l); + tauSGET[i][j] += + coeffSGET * arScale * + (M43[i][l] * fluctDudx_jl + M43[j][l] * fluctDudx_il); + } + tauSGET[i][j] += arInvScale * tvisc.get(mi, 0) / density.get(mi, 0) * + (dudx.get(mi, i * nalu_ngp::NDimMax + j) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + dudx.get(mi, j * nalu_ngp::NDimMax + i) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + } + } + + // Remove trace of tauSGET + DblType tauSGET_tr = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tauSGET_tr += tauSGET[i][i]; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tauSGET[i][i] -= tauSGET_tr / nalu_ngp::NDimMax; + + // Calculate the full subgrid stress including the isotropic portion + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + tau[i][j] = + tauSGRS[i][j] + tauSGET[i][j] - + ((i == j) ? 2.0 / 3.0 * beta.get(mi, 0) * tke.get(mi, 0) : 0.0); + + // Calculate the SGS production PSGS_ij = 1/2(tau_ik*djuk + tau_jk*diuk) + // where diuj is the instantaneous velocity gradients + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + Psgs[i][j] += tau[i][l] * dudx.get(mi, l * nalu_ngp::NDimMax + j) + + tau[j][l] * dudx.get(mi, l * nalu_ngp::NDimMax + i); + } + Psgs[i][j] *= 0.5; + } + } + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + PM[i][j] = 0.0; + for (int l = 0; l < nalu_ngp::NDimMax; ++l) + PM[i][j] += Psgs[i][l] * p_Mij[l][j]; + } + } + + // Scale PM first + const DblType v2 = + 1.0 / v2cMu * + (tvisc.get(mi, 0) / density.get(mi, 0) / avgTime.get(mi, 0)); + const DblType PMscale = + coeffR * stk::math::pow(1.5 * beta.get(mi, 0) * v2, -1.5); + + // Handle case where tke = 0, should only occur at a wall boundary + if (tke.get(mi, 0) == 0.0) + resAdeq.get(mi, 0) = 1.0; + else { + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PM[i][j] = PM[i][j] * PMscale; + + DblType PMmag = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PMmag += PM[i][j] * PM[i][j]; + + PMmag = stk::math::sqrt(PMmag); + + EigenDecomposition::general_eigenvalues(PM, Q, D); + + // Take only positive eigenvalues of PM + DblType maxPM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + + // Update the instantaneous resAdeq field + resAdeq.get(mi, 0) = + stk::math::max(stk::math::min(maxPM, PMmag), 0.00000001); + + resAdeq.get(mi, 0) = stk::math::min(resAdeq.get(mi, 0), 30.0); + + if (alpha >= 1.0) { + resAdeq.get(mi, 0) = stk::math::min(resAdeq.get(mi, 0), 1.0); + } + + if (alpha <= beta_kol_local) + resAdeq.get(mi, 0) = stk::math::max(resAdeq.get(mi, 0), 1.0); + } + + avgResAdeq.get(mi, 0) = + weightAvg * avgResAdeqN.get(mi, 0) + weightInst * resAdeq.get(mi, 0); + }); +} + +} // namespace nalu +} // namespace sierra diff --git a/src/ngp_algorithms/SSTAMSAveragesAlg.C b/src/ngp_algorithms/SSTAMSAveragesAlg.C index 4d7a92c9e..36a1da8ee 100644 --- a/src/ngp_algorithms/SSTAMSAveragesAlg.C +++ b/src/ngp_algorithms/SSTAMSAveragesAlg.C @@ -23,12 +23,15 @@ namespace sierra { namespace nalu { SSTAMSAveragesAlg::SSTAMSAveragesAlg(Realm& realm, stk::mesh::Part* part) - : Algorithm(realm, part), + : AMSAveragesAlg(realm, part), betaStar_(realm.get_turb_model_constant(TM_betaStar)), CMdeg_(realm.get_turb_model_constant(TM_CMdeg)), v2cMu_(realm.get_turb_model_constant(TM_v2cMu)), aspectRatioSwitch_(realm.get_turb_model_constant(TM_aspRatSwitch)), avgTimeCoeff_(realm.get_turb_model_constant(TM_avgTimeCoeff)), + alphaPow_(realm.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(realm.get_turb_model_constant(TM_alphaScaPow)), + coeffR_(realm.get_turb_model_constant(TM_coeffR)), meshMotion_(realm.does_mesh_move()), RANSBelowKs_(realm_.solutionOptions_->RANSBelowKs_), z0_(realm_.solutionOptions_->roughnessHeight_), @@ -121,6 +124,9 @@ SSTAMSAveragesAlg::execute() const DblType aspectRatioSwitch = aspectRatioSwitch_; const DblType avgTimeCoeff = avgTimeCoeff_; const auto lengthScaleLimiter = lengthScaleLimiter_; + const DblType alphaPow = alphaPow_; + const DblType alphaScaPow = alphaScaPow_; + const DblType coeffR = coeffR_; const bool RANSBelowKs = RANSBelowKs_; DblType k_s = 0; @@ -154,7 +160,7 @@ SSTAMSAveragesAlg::execute() beta.get(mi, 0) = stk::math::max(beta.get(mi, 0), beta_kol_local); } - const DblType alpha = stk::math::pow(beta.get(mi, 0), 1.7); + const DblType alpha = stk::math::pow(beta.get(mi, 0), alphaPow); // store RANS time scale if (lengthScaleLimiter) { @@ -198,7 +204,8 @@ SSTAMSAveragesAlg::execute() const DblType avgSij = 0.5 * (avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); - tij[i][j] = 2.0 * alpha * (2.0 - alpha) * tvisc.get(mi, 0) * avgSij; + tij[i][j] = 2.0 * stk::math::pow(alpha, alphaScaPow) * (2.0 - alpha) * + tvisc.get(mi, 0) * avgSij; } } @@ -316,8 +323,9 @@ SSTAMSAveragesAlg::execute() // the SST model and is the strain rate tensor based on the // mean quantities... i.e this is (tauSGRS = alpha*tauSST) // The 2 in the coeff cancels with the 1/2 in the strain rate tensor - const DblType coeffSGRS = - alpha * (2.0 - alpha) * tvisc.get(mi, 0) / density.get(mi, 0); + const DblType coeffSGRS = stk::math::pow(alpha, alphaScaPow) * + (2.0 - alpha) * tvisc.get(mi, 0) / + density.get(mi, 0); tauSGRS[i][j] = avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + avgDudx.get(mi, j * nalu_ngp::NDimMax + i); tauSGRS[i][j] *= coeffSGRS; @@ -385,7 +393,8 @@ SSTAMSAveragesAlg::execute() const DblType v2 = 1.0 / v2cMu * (tvisc.get(mi, 0) / density.get(mi, 0) / avgTime.get(mi, 0)); - const DblType PMscale = stk::math::pow(1.5 * beta.get(mi, 0) * v2, -1.5); + const DblType PMscale = + coeffR * stk::math::pow(1.5 * beta.get(mi, 0) * v2, -1.5); // Handle case where tke = 0, should only occur at a wall boundary if (tke.get(mi, 0) == 0.0) diff --git a/src/ngp_algorithms/SSTLRAMSAveragesAlg.C b/src/ngp_algorithms/SSTLRAMSAveragesAlg.C new file mode 100644 index 000000000..1bd748b47 --- /dev/null +++ b/src/ngp_algorithms/SSTLRAMSAveragesAlg.C @@ -0,0 +1,414 @@ +// 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 "ngp_algorithms/SSTLRAMSAveragesAlg.h" +#include "ngp_utils/NgpLoopUtils.h" +#include "ngp_utils/NgpTypes.h" +#include "ngp_utils/NgpFieldManager.h" +#include "Realm.h" +#include "utils/StkHelpers.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/NgpMesh.hpp" +#include "EigenDecomposition.h" +#include "utils/AMSUtils.h" + +namespace sierra { +namespace nalu { + +SSTLRAMSAveragesAlg::SSTLRAMSAveragesAlg(Realm& realm, stk::mesh::Part* part) + : AMSAveragesAlg(realm, part), + betaStar_(realm.get_turb_model_constant(TM_betaStar)), + CMdeg_(realm.get_turb_model_constant(TM_CMdeg)), + v2cMu_(realm.get_turb_model_constant(TM_v2cMu)), + aspectRatioSwitch_(realm.get_turb_model_constant(TM_aspRatSwitch)), + alphaPow_(realm.get_turb_model_constant(TM_alphaPow)), + alphaScaPow_(realm.get_turb_model_constant(TM_alphaScaPow)), + coeffR_(realm.get_turb_model_constant(TM_coeffR)), + meshMotion_(realm.does_mesh_move()), + velocity_(get_field_ordinal(realm.meta_data(), "velocity")), + density_(get_field_ordinal(realm.meta_data(), "density")), + dudx_(get_field_ordinal(realm.meta_data(), "dudx")), + resAdeq_( + get_field_ordinal(realm.meta_data(), "resolution_adequacy_parameter")), + turbKineticEnergy_(get_field_ordinal(realm.meta_data(), "turbulent_ke")), + specDissipationRate_( + get_field_ordinal(realm.meta_data(), "specific_dissipation_rate")), + avgVelocity_(get_field_ordinal(realm.meta_data(), "average_velocity")), + avgVelocityN_(get_field_ordinal( + realm.meta_data(), "average_velocity", stk::mesh::StateN)), + avgDudx_(get_field_ordinal(realm.meta_data(), "average_dudx")), + avgDudxN_( + get_field_ordinal(realm.meta_data(), "average_dudx", stk::mesh::StateN)), + avgTkeRes_(get_field_ordinal(realm.meta_data(), "average_tke_resolved")), + avgTkeResN_(get_field_ordinal( + realm.meta_data(), "average_tke_resolved", stk::mesh::StateN)), + avgProd_(get_field_ordinal(realm.meta_data(), "average_production")), + avgProdN_(get_field_ordinal( + realm.meta_data(), "average_production", stk::mesh::StateN)), + avgTime_(get_field_ordinal(realm.meta_data(), "rans_time_scale")), + avgResAdeq_( + get_field_ordinal(realm.meta_data(), "avg_res_adequacy_parameter")), + avgResAdeqN_(get_field_ordinal( + realm.meta_data(), "avg_res_adequacy_parameter", stk::mesh::StateN)), + fOneBlend_(get_field_ordinal(realm.meta_data(), "sst_f_one_blending")), + tvisc_(get_field_ordinal(realm.meta_data(), "turbulent_viscosity")), + visc_(get_field_ordinal(realm.meta_data(), "viscosity")), + beta_(get_field_ordinal(realm.meta_data(), "k_ratio")), + Mij_(get_field_ordinal(realm.meta_data(), "metric_tensor")), + wallDist_(get_field_ordinal(realm.meta_data(), "minimum_distance_to_wall")), + + magPM_(get_field_ordinal(realm.meta_data(), "PMmag")), + PMmax_(get_field_ordinal(realm.meta_data(), "maxPM")), + PM1_(get_field_ordinal(realm.meta_data(), "PM1")), + PM2_(get_field_ordinal(realm.meta_data(), "PM2")), + PM3_(get_field_ordinal(realm.meta_data(), "PM3")) +{ +} + +void +SSTLRAMSAveragesAlg::execute() +{ + using Traits = nalu_ngp::NGPMeshTraits; + + const auto& meta = realm_.meta_data(); + if (meta.spatial_dimension() != 3) { + throw std::runtime_error("SSTLRAMSAveragesAlg only supported in 3D."); + } + const DblType dt = realm_.get_time_step(); + + const stk::mesh::Selector sel = + (meta.locally_owned_part() | meta.globally_shared_part()) & + stk::mesh::selectField( + *meta.get_field(stk::topology::NODE_RANK, "average_velocity")); + + const auto& meshInfo = realm_.mesh_info(); + const auto ngpMesh = meshInfo.ngp_mesh(); + const auto& fieldMgr = meshInfo.ngp_field_manager(); + + const auto tvisc = fieldMgr.get_field(tvisc_); + const auto visc = fieldMgr.get_field(visc_); + const auto tke = fieldMgr.get_field(turbKineticEnergy_); + const auto sdr = fieldMgr.get_field(specDissipationRate_); + const auto density = fieldMgr.get_field(density_); + auto beta = fieldMgr.get_field(beta_); + auto avgProd = fieldMgr.get_field(avgProd_); + auto avgProdN = fieldMgr.get_field(avgProdN_); + auto avgTkeRes = fieldMgr.get_field(avgTkeRes_); + auto avgTkeResN = fieldMgr.get_field(avgTkeResN_); + auto avgTime = fieldMgr.get_field(avgTime_); + auto resAdeq = fieldMgr.get_field(resAdeq_); + auto avgResAdeq = fieldMgr.get_field(avgResAdeq_); + auto avgResAdeqN = fieldMgr.get_field(avgResAdeqN_); + const auto vel = fieldMgr.get_field(velocity_); + const auto dudx = fieldMgr.get_field(dudx_); + auto avgVel = fieldMgr.get_field(avgVelocity_); + auto avgVelN = fieldMgr.get_field(avgVelocityN_); + auto avgDudx = fieldMgr.get_field(avgDudx_); + auto avgDudxN = fieldMgr.get_field(avgDudxN_); + const auto Mij = fieldMgr.get_field(Mij_); + const auto wallDist = fieldMgr.get_field(wallDist_); + const auto fOneBlend = fieldMgr.get_field(fOneBlend_); + + auto magPM = fieldMgr.get_field(magPM_); + auto PMmax = fieldMgr.get_field(PMmax_); + auto PM1 = fieldMgr.get_field(PM1_); + auto PM2 = fieldMgr.get_field(PM2_); + auto PM3 = fieldMgr.get_field(PM3_); + + const DblType betaStar = betaStar_; + const DblType CMdeg = CMdeg_; + const DblType v2cMu = v2cMu_; + const DblType beta_kol_local = beta_kol; + const DblType aspectRatioSwitch = aspectRatioSwitch_; + const DblType alphaPow = alphaPow_; + const DblType alphaScaPow = alphaScaPow_; + const DblType coeffR = coeffR_; + + nalu_ngp::run_entity_algorithm( + "SSTLRAMSAveragesAlg_computeAverages", ngpMesh, stk::topology::NODE_RANK, + sel, KOKKOS_LAMBDA(const Traits::MeshIndex& mi) { + // Calculate alpha + if (tke.get(mi, 0) == 0.0) + beta.get(mi, 0) = 1.0; + else { + beta.get(mi, 0) = + (tke.get(mi, 0) - avgTkeRes.get(mi, 0)) / tke.get(mi, 0); + + // limiters + beta.get(mi, 0) = stk::math::min(beta.get(mi, 0), 1.0); + + beta.get(mi, 0) = stk::math::max(beta.get(mi, 0), beta_kol_local); + } + + const DblType alpha = stk::math::pow(beta.get(mi, 0), alphaPow); + + const DblType ReT = + density.get(mi, 0) * tke.get(mi, 0) / sdr.get(mi, 0) / visc.get(mi, 0); + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + const DblType betaStarBlend = fOneBlend.get(mi, 0) * betaStarLowRe + + (1.0 - fOneBlend.get(mi, 0)) * betaStar_; + + // store RANS time scale + avgTime.get(mi, 0) = 1.0 / (betaStarBlend * sdr.get(mi, 0)); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType weightAvg = + stk::math::max(1.0 - dt / avgTime.get(mi, 0), 0.0); + const DblType weightInst = stk::math::min(dt / avgTime.get(mi, 0), 1.0); + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + avgVel.get(mi, i) = + weightAvg * avgVelN.get(mi, i) + weightInst * vel.get(mi, i); + + DblType tkeRes = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + tkeRes += (vel.get(mi, i) - avgVel.get(mi, i)) * + (vel.get(mi, i) - avgVel.get(mi, i)); + + avgTkeRes.get(mi, 0) = + weightAvg * avgTkeResN.get(mi, 0) + weightInst * 0.5 * tkeRes; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) = + weightAvg * avgDudxN.get(mi, i * nalu_ngp::NDimMax + j) + + weightInst * dudx.get(mi, i * nalu_ngp::NDimMax + j); + } + } + + // Production averaging + DblType tij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + const DblType avgSij = + 0.5 * (avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + tij[i][j] = 2.0 * stk::math::pow(alpha, alphaScaPow) * (2.0 - alpha) * + tvisc.get(mi, 0) * avgSij; + } + } + + DblType Pij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + Pij[i][j] = 0.0; + for (int m = 0; m < nalu_ngp::NDimMax; ++m) { + Pij[i][j] += + avgDudx.get(mi, i * nalu_ngp::NDimMax + m) * tij[j][m] + + avgDudx.get(mi, j * nalu_ngp::NDimMax + m) * tij[i][m]; + } + Pij[i][j] *= 0.5; + } + } + + DblType P_res = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + P_res += density.get(mi, 0) * + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) * + ((avgVel.get(mi, i) - vel.get(mi, i)) * + (avgVel.get(mi, j) - vel.get(mi, j))); + } + } + + DblType instProd = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + instProd += Pij[i][i]; + + instProd -= P_res; + + // Use a longer averaging timescale for production + const DblType prodAvgTime = 4.0 * avgTime.get(mi, 0); + + // causal time average ODE: d/dt = 1/avgTime * (phi - ) + const DblType prodWeightAvg = stk::math::max(1.0 - dt / prodAvgTime, 0.0); + const DblType prodWeightInst = stk::math::min(dt / prodAvgTime, 1.0); + + avgProd.get(mi, 0) = + prodWeightAvg * avgProdN.get(mi, 0) + prodWeightInst * instProd; + + // get Mij field_data + DblType p_Mij[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType PM[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Q[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType D[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + const int iNdim = i * nalu_ngp::NDimMax; + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + p_Mij[i][j] = Mij.get(mi, iNdim + j); + } + } + + // Eigenvalue decomposition of metric tensor + EigenDecomposition::sym_diagonalize(p_Mij, Q, D); + + // initialize M43 to 0 + DblType M43[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + M43[i][j] = 0.0; + + const DblType fourThirds = 4.0 / 3.0; + + for (int l = 0; l < nalu_ngp::NDimMax; l++) { + const DblType D43 = stk::math::pow(D[l][l], fourThirds); + for (int i = 0; i < nalu_ngp::NDimMax; i++) { + for (int j = 0; j < nalu_ngp::NDimMax; j++) { + M43[i][j] += Q[i][l] * Q[j][l] * D43; + } + } + } + + const DblType maxEigM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + const DblType minEigM = + stk::math::min(D[0][0], stk::math::min(D[1][1], D[2][2])); + + const DblType aspectRatio = maxEigM / minEigM; + + // zeroing out tensors + DblType tauSGRS[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tauSGET[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType tau[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + DblType Psgs[nalu_ngp::NDimMax][nalu_ngp::NDimMax]; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + tauSGRS[i][j] = 0.0; + tauSGET[i][j] = 0.0; + tau[i][j] = 0.0; + Psgs[i][j] = 0.0; + } + } + + const DblType CM43 = + ams_utils::get_M43_constant(D, CMdeg); + + const DblType CM43scale = stk::math::max( + stk::math::min(stk::math::pow(avgResAdeq.get(mi, 0), 2.0), 30.0), 1.0); + + const DblType epsilon13 = stk::math::pow( + betaStarBlend * tke.get(mi, 0) * sdr.get(mi, 0), 1.0 / 3.0); + + const DblType arScale = + 1.0 - stk::math::tanh(stk::math::max(avgResAdeq.get(mi, 0) - 1.0, 0.0)); + + const DblType arInvScale = 1.0 - arScale; + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + // Calculate tauSGRS_ij = 2*alpha*nu_t* where nu_t comes from + // the SST model and is the strain rate tensor based on the + // mean quantities... i.e this is (tauSGRS = alpha*tauSST) + // The 2 in the coeff cancels with the 1/2 in the strain rate tensor + const DblType coeffSGRS = stk::math::pow(alpha, alphaScaPow) * + (2.0 - alpha) * tvisc.get(mi, 0) / + density.get(mi, 0); + tauSGRS[i][j] = avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + avgDudx.get(mi, j * nalu_ngp::NDimMax + i); + tauSGRS[i][j] *= coeffSGRS; + + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + // Calculate tauSGET_ij = CM43*^(1/3)*(M43_ik*dkuj' + + // M43_jkdkui') where is the mean dissipation backed out from + // the SST mean k and mean omega and dkuj' is the fluctuating + // velocity gradients. + const DblType coeffSGET = CMdeg * epsilon13; + const DblType fluctDudx_jl = + dudx.get(mi, j * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + l); + const DblType fluctDudx_il = + dudx.get(mi, i * nalu_ngp::NDimMax + l) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + l); + tauSGET[i][j] += + coeffSGET * arScale * + (M43[i][l] * fluctDudx_jl + M43[j][l] * fluctDudx_il); + } + tauSGET[i][j] += arInvScale * tvisc.get(mi, 0) / density.get(mi, 0) * + (dudx.get(mi, i * nalu_ngp::NDimMax + j) - + avgDudx.get(mi, i * nalu_ngp::NDimMax + j) + + dudx.get(mi, j * nalu_ngp::NDimMax + i) - + avgDudx.get(mi, j * nalu_ngp::NDimMax + i)); + } + } + + // Calculate the full subgrid stress including the isotropic portion + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + tau[i][j] = + tauSGRS[i][j] + tauSGET[i][j] - + ((i == j) ? 2.0 / 3.0 * beta.get(mi, 0) * tke.get(mi, 0) : 0.0); + + // Calculate the SGS production PSGS_ij = 1/2(tau_ik*djuk + tau_jk*diuk) + // where diuj is the instantaneous velocity gradients + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + for (int l = 0; l < nalu_ngp::NDimMax; ++l) { + Psgs[i][j] += tau[i][l] * dudx.get(mi, l * nalu_ngp::NDimMax + j) + + tau[j][l] * dudx.get(mi, l * nalu_ngp::NDimMax + i); + } + Psgs[i][j] *= 0.5; + } + } + + for (int i = 0; i < nalu_ngp::NDimMax; ++i) { + for (int j = 0; j < nalu_ngp::NDimMax; ++j) { + PM[i][j] = 0.0; + for (int l = 0; l < nalu_ngp::NDimMax; ++l) + PM[i][j] += Psgs[i][l] * p_Mij[l][j]; + } + } + + // Scale PM first + const DblType v2 = + 1.0 / v2cMu * + (tvisc.get(mi, 0) / density.get(mi, 0) / avgTime.get(mi, 0)); + const DblType PMscale = + coeffR * stk::math::pow(beta.get(mi, 0) * v2, -1.5); + + // Handle case where tke = 0, should only occur at a wall boundary + if (tke.get(mi, 0) == 0.0) + resAdeq.get(mi, 0) = 1.0; + else { + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PM[i][j] = PM[i][j] * PMscale; + + DblType PMmag = 0.0; + for (int i = 0; i < nalu_ngp::NDimMax; ++i) + for (int j = 0; j < nalu_ngp::NDimMax; ++j) + PMmag += PM[i][j] * PM[i][j]; + + PMmag = 0.5 * stk::math::sqrt(PMmag); + + EigenDecomposition::general_eigenvalues(PM, Q, D); + + // Take only positive eigenvalues of PM + DblType maxPM = + stk::math::max(D[0][0], stk::math::max(D[1][1], D[2][2])); + + magPM.get(mi, 0) = PMmag; + PMmax.get(mi, 0) = maxPM; + PM1.get(mi, 0) = D[0][0]; + PM2.get(mi, 0) = D[1][1]; + PM3.get(mi, 0) = D[2][2]; + + resAdeq.get(mi, 0) = PMmag; + } + + avgResAdeq.get(mi, 0) = + weightAvg * avgResAdeqN.get(mi, 0) + weightInst * resAdeq.get(mi, 0); + }); +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/CMakeLists.txt b/src/node_kernels/CMakeLists.txt index 2d8d0e3cf..eab41c393 100644 --- a/src/node_kernels/CMakeLists.txt +++ b/src/node_kernels/CMakeLists.txt @@ -10,12 +10,20 @@ target_sources(nalu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/MomentumMassBDFNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumActuatorNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumCoriolisNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/MomentumKEAMSForcingNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/MomentumKOAMSForcingNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/MomentumSSTAMSForcingNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/ScalarGclNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/ScalarMassBDFNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/SDRSSTAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/SDRSSTLRAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/SDRKOAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/TDRKEAMSNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/TDRKENodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/TKESSTAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/TKESSTLRAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/TKEKEAMSNodeKernel.C + ${CMAKE_CURRENT_SOURCE_DIR}/TKEKOAMSNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/TKERodiNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/TKEKsgsNodeKernel.C ${CMAKE_CURRENT_SOURCE_DIR}/TKESSTNodeKernel.C diff --git a/src/node_kernels/MomentumKEAMSForcingNodeKernel.C b/src/node_kernels/MomentumKEAMSForcingNodeKernel.C new file mode 100644 index 000000000..5731b4ce1 --- /dev/null +++ b/src/node_kernels/MomentumKEAMSForcingNodeKernel.C @@ -0,0 +1,225 @@ +// 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/MomentumKEAMSForcingNodeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" +#include "utils/StkHelpers.h" +#include + +namespace sierra { +namespace nalu { + +MomentumKEAMSForcingNodeKernel::MomentumKEAMSForcingNodeKernel( + const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) + : NGPNodeKernel(), + betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), + forceCl_(solnOpts.get_turb_model_constant(TM_forCl)), + Ceta_(solnOpts.get_turb_model_constant(TM_forCeta)), + Ct_(solnOpts.get_turb_model_constant(TM_forCt)), + blT_(solnOpts.get_turb_model_constant(TM_forBlT)), + blKol_(solnOpts.get_turb_model_constant(TM_forBlKol)), + forceFactor_(solnOpts.get_turb_model_constant(TM_forFac)), + cMu_(solnOpts.get_turb_model_constant(TM_v2cMu)), + periodicForcingLengthX_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthX)), + periodicForcingLengthY_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthY)), + periodicForcingLengthZ_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthZ)), + nDim_(bulk.mesh_meta_data().spatial_dimension()) +{ + const auto& meta = bulk.mesh_meta_data(); + + dualNodalVolumeID_ = get_field_ordinal(meta, "dual_nodal_volume"); + + coordinatesID_ = get_field_ordinal(meta, solnOpts.get_coordinates_name()); + const std::string velField = "velocity"; + velocityID_ = get_field_ordinal(meta, velField); + viscosityID_ = get_field_ordinal(meta, "viscosity"); + turbViscID_ = get_field_ordinal(meta, "turbulent_viscosity"); + densityNp1ID_ = get_field_ordinal(meta, "density", stk::mesh::StateNP1); + tkeNp1ID_ = get_field_ordinal(meta, "turbulent_ke", stk::mesh::StateNP1); + tdrNp1ID_ = + get_field_ordinal(meta, "total_dissipation_rate", stk::mesh::StateNP1); + betaID_ = get_field_ordinal(meta, "k_ratio"); + MijID_ = get_field_ordinal(meta, "metric_tensor"); + minDistID_ = get_field_ordinal(meta, "minimum_distance_to_wall"); + + // average quantities + avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); + avgResAdeqID_ = get_field_ordinal(meta, "avg_res_adequacy_parameter"); + + // output quantities + forcingCompID_ = get_field_ordinal(meta, "forcing_components"); +} + +void +MomentumKEAMSForcingNodeKernel::setup(Realm& realm) +{ + // Time information + dt_ = realm.get_time_step(); + time_ = realm.get_current_time(); + + const auto& fieldMgr = realm.ngp_field_manager(); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + coordinates_ = fieldMgr.get_field(coordinatesID_); + velocity_ = fieldMgr.get_field(velocityID_); + viscosity_ = fieldMgr.get_field(viscosityID_); + tvisc_ = fieldMgr.get_field(turbViscID_); + density_ = fieldMgr.get_field(densityNp1ID_); + tke_ = fieldMgr.get_field(tkeNp1ID_); + tdr_ = fieldMgr.get_field(tdrNp1ID_); + beta_ = fieldMgr.get_field(betaID_); + Mij_ = fieldMgr.get_field(MijID_); + minDist_ = fieldMgr.get_field(minDistID_); + avgVelocity_ = fieldMgr.get_field(avgVelocityID_); + avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); + forcingComp_ = fieldMgr.get_field(forcingCompID_); +} + +KOKKOS_FUNCTION +void +MomentumKEAMSForcingNodeKernel::execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType& rhs, + const stk::mesh::FastMeshIndex& node) +{ + // Scratch work arrays + NALU_ALIGNED NodeKernelTraits::DblType + coords[NodeKernelTraits::NDimMax]; // coordinates + NALU_ALIGNED NodeKernelTraits::DblType + avgU[NodeKernelTraits::NDimMax]; // averageVelocity + NALU_ALIGNED NodeKernelTraits::DblType + fluctU[NodeKernelTraits::NDimMax]; // fluctuatingVelocity + + const NodeKernelTraits::DblType dualVolume = dualNodalVolume_.get(node, 0); + + const NodeKernelTraits::DblType mu = viscosity_.get(node, 0); + const NodeKernelTraits::DblType tvisc = tvisc_.get(node, 0); + const NodeKernelTraits::DblType rho = density_.get(node, 0); + const NodeKernelTraits::DblType tke = + stk::math::max(tke_.get(node, 0), 1.0e-12); + const NodeKernelTraits::DblType tdr = tdr_.get(node, 0); + const NodeKernelTraits::DblType beta = beta_.get(node, 0); + const NodeKernelTraits::DblType wallDist = minDist_.get(node, 0); + const NodeKernelTraits::DblType avgResAdeq = avgResAdeq_.get(node, 0); + + for (int d = 0; d < nDim_; d++) { + avgU[d] = avgVelocity_.get(node, d); + fluctU[d] = velocity_.get(node, d) - avgVelocity_.get(node, d); + coords[d] = coordinates_.get(node, d); + } + + const NodeKernelTraits::DblType eps = tdr; + + const NodeKernelTraits::DblType smallCl_ = 2.0; + const NodeKernelTraits::DblType clOffset_ = 0.2; + + NodeKernelTraits::DblType length = + (forceCl_ + (1.0 - stk::math::max(beta, 1.0 - clOffset_)) / clOffset_ * + (smallCl_ - forceCl_)) * + stk::math::pow(beta * tke, 1.5) / eps; + length = stk::math::max( + length, + Ceta_ * (stk::math::pow(mu / rho, 0.75) / stk::math::pow(eps, 0.25))); + + const NodeKernelTraits::DblType lengthY = stk::math::min(length, wallDist); + + NodeKernelTraits::DblType T_beta = beta * tke / eps; + T_beta = stk::math::max(T_beta, Ct_ * stk::math::sqrt(mu / rho / eps)); + T_beta = blT_ * T_beta; + + // FIXME : Make this aware of wall direction, for now it is + // generalized using lengthY for all directions + const NodeKernelTraits::DblType clipLengthX = + stk::math::min(lengthY, periodicForcingLengthX_); + const NodeKernelTraits::DblType clipLengthY = + stk::math::min(lengthY, periodicForcingLengthY_); + const NodeKernelTraits::DblType clipLengthZ = + stk::math::min(lengthY, periodicForcingLengthZ_); + + const NodeKernelTraits::DblType ratioX = + std::floor(periodicForcingLengthX_ / (clipLengthX + 1.e-12) + 0.5); + const NodeKernelTraits::DblType ratioY = + std::floor(periodicForcingLengthY_ / (clipLengthY + 1.e-12) + 0.5); + const NodeKernelTraits::DblType ratioZ = + std::floor(periodicForcingLengthZ_ / (clipLengthZ + 1.e-12) + 0.5); + + const NodeKernelTraits::DblType denomX = periodicForcingLengthX_ / ratioX; + const NodeKernelTraits::DblType denomY = periodicForcingLengthY_ / ratioY; + const NodeKernelTraits::DblType denomZ = periodicForcingLengthZ_ / ratioZ; + + const NodeKernelTraits::DblType ax = M_PI / denomX; + const NodeKernelTraits::DblType ay = M_PI / denomY; + const NodeKernelTraits::DblType az = M_PI / denomZ; + + // Then we calculate the arguments for the Taylor-Green Vortex + const NodeKernelTraits::DblType xarg = ax * (coords[0] - avgU[0] * time_); + const NodeKernelTraits::DblType yarg = ay * (coords[1] - avgU[1] * time_); + const NodeKernelTraits::DblType zarg = az * (coords[2] - avgU[2] * time_); + + // Now we calculate the initial Taylor-Green field + NodeKernelTraits::DblType hX = 1. / 3. * stk::math::cos(xarg) * + stk::math::sin(yarg) * stk::math::sin(zarg); + NodeKernelTraits::DblType hY = + -1. * stk::math::sin(xarg) * stk::math::cos(yarg) * stk::math::sin(zarg); + NodeKernelTraits::DblType hZ = 2. / 3. * stk::math::sin(xarg) * + stk::math::sin(yarg) * stk::math::cos(zarg); + + // Now we calculate the scaling of the initial field + const NodeKernelTraits::DblType v2 = tvisc * eps / (cMu_ * rho * tke); + const NodeKernelTraits::DblType F_target = + forceFactor_ * stk::math::sqrt(beta * v2) / T_beta; + + const NodeKernelTraits::DblType prod_r_temp = + (F_target * dt_) * (hX * fluctU[0] + hY * fluctU[1] + hZ * fluctU[2]); + + const NodeKernelTraits::DblType prod_r_sgn = + stk::math::if_then_else(prod_r_temp < 0.0, -1.0, 1.0); + const NodeKernelTraits::DblType prod_r_abs = prod_r_sgn * prod_r_temp; + + const NodeKernelTraits::DblType prod_r = + stk::math::if_then_else(prod_r_abs >= 1.0e-15, prod_r_temp, 0.0); + + const NodeKernelTraits::DblType b_kol = + stk::math::min(blKol_ * stk::math::sqrt(mu * eps / rho) / tke, 1.0); + + const NodeKernelTraits::DblType bhat = stk::math::if_then_else( + (1.0 - b_kol) > 0.0, (1.0 - beta) / (1.0 - b_kol), 10000.0); + + NodeKernelTraits::DblType C_F_tmp = + -1.0 * stk::math::tanh( + 1.0 - 1.0 / stk::math::sqrt(stk::math::min(avgResAdeq, 1.0))); + + C_F_tmp = + C_F_tmp * + (1.0 - stk::math::min(stk::math::tanh(10.0 * (bhat - 1.0)) + 1.0, 1.0)); + + const NodeKernelTraits::DblType C_F = + stk::math::if_then_else(prod_r >= 0.0, F_target * C_F_tmp, 0.0); + + // Now we determine the actual forcing field + NodeKernelTraits::DblType gX = C_F * hX; + NodeKernelTraits::DblType gY = C_F * hY; + NodeKernelTraits::DblType gZ = C_F * hZ; + + forcingComp_.get(node, 0) = gX; + forcingComp_.get(node, 1) = gY; + forcingComp_.get(node, 2) = gZ; + + rhs(0) += dualVolume * gX; + rhs(1) += dualVolume * gY; + rhs(2) += dualVolume * gZ; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/MomentumKOAMSForcingNodeKernel.C b/src/node_kernels/MomentumKOAMSForcingNodeKernel.C new file mode 100644 index 000000000..d18a709be --- /dev/null +++ b/src/node_kernels/MomentumKOAMSForcingNodeKernel.C @@ -0,0 +1,231 @@ +// 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/MomentumKOAMSForcingNodeKernel.h" +#include "Realm.h" +#include "SolutionOptions.h" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Types.hpp" +#include "utils/StkHelpers.h" +#include + +namespace sierra { +namespace nalu { + +MomentumKOAMSForcingNodeKernel::MomentumKOAMSForcingNodeKernel( + const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) + : NGPNodeKernel(), + betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), + forceCl_(solnOpts.get_turb_model_constant(TM_forCl)), + Ceta_(solnOpts.get_turb_model_constant(TM_forCeta)), + Ct_(solnOpts.get_turb_model_constant(TM_forCt)), + blT_(solnOpts.get_turb_model_constant(TM_forBlT)), + blKol_(solnOpts.get_turb_model_constant(TM_forBlKol)), + forceFactor_(solnOpts.get_turb_model_constant(TM_forFac)), + v2cMu_(solnOpts.get_turb_model_constant(TM_v2cMu)), + periodicForcingLengthX_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthX)), + periodicForcingLengthY_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthY)), + periodicForcingLengthZ_( + solnOpts.get_turb_model_constant(TM_periodicForcingLengthZ)), + nDim_(bulk.mesh_meta_data().spatial_dimension()) +{ + const auto& meta = bulk.mesh_meta_data(); + + dualNodalVolumeID_ = get_field_ordinal(meta, "dual_nodal_volume"); + + coordinatesID_ = get_field_ordinal(meta, solnOpts.get_coordinates_name()); + const std::string velField = "velocity"; + velocityID_ = get_field_ordinal(meta, velField); + viscosityID_ = get_field_ordinal(meta, "viscosity"); + turbViscID_ = get_field_ordinal(meta, "turbulent_viscosity"); + densityNp1ID_ = get_field_ordinal(meta, "density", stk::mesh::StateNP1); + tkeNp1ID_ = get_field_ordinal(meta, "turbulent_ke", stk::mesh::StateNP1); + sdrNp1ID_ = + get_field_ordinal(meta, "specific_dissipation_rate", stk::mesh::StateNP1); + betaID_ = get_field_ordinal(meta, "k_ratio"); + MijID_ = get_field_ordinal(meta, "metric_tensor"); + minDistID_ = get_field_ordinal(meta, "minimum_distance_to_wall"); + + // average quantities + avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); + avgResAdeqID_ = get_field_ordinal(meta, "avg_res_adequacy_parameter"); + + // output quantities + forcingCompID_ = get_field_ordinal(meta, "forcing_components"); +} + +void +MomentumKOAMSForcingNodeKernel::setup(Realm& realm) +{ + // Time information + dt_ = realm.get_time_step(); + time_ = realm.get_current_time(); + + const auto& fieldMgr = realm.ngp_field_manager(); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + coordinates_ = fieldMgr.get_field(coordinatesID_); + velocity_ = fieldMgr.get_field(velocityID_); + viscosity_ = fieldMgr.get_field(viscosityID_); + tvisc_ = fieldMgr.get_field(turbViscID_); + density_ = fieldMgr.get_field(densityNp1ID_); + tke_ = fieldMgr.get_field(tkeNp1ID_); + sdr_ = fieldMgr.get_field(sdrNp1ID_); + beta_ = fieldMgr.get_field(betaID_); + Mij_ = fieldMgr.get_field(MijID_); + minDist_ = fieldMgr.get_field(minDistID_); + avgVelocity_ = fieldMgr.get_field(avgVelocityID_); + avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); + forcingComp_ = fieldMgr.get_field(forcingCompID_); +} + +KOKKOS_FUNCTION +void +MomentumKOAMSForcingNodeKernel::execute( + NodeKernelTraits::LhsType&, + NodeKernelTraits::RhsType& rhs, + const stk::mesh::FastMeshIndex& node) +{ + // Scratch work arrays + NALU_ALIGNED NodeKernelTraits::DblType + coords[NodeKernelTraits::NDimMax]; // coordinates + NALU_ALIGNED NodeKernelTraits::DblType + avgU[NodeKernelTraits::NDimMax]; // averageVelocity + NALU_ALIGNED NodeKernelTraits::DblType + fluctU[NodeKernelTraits::NDimMax]; // fluctuatingVelocity + + const NodeKernelTraits::DblType dualVolume = dualNodalVolume_.get(node, 0); + + const NodeKernelTraits::DblType mu = viscosity_.get(node, 0); + const NodeKernelTraits::DblType tvisc = tvisc_.get(node, 0); + const NodeKernelTraits::DblType rho = density_.get(node, 0); + const NodeKernelTraits::DblType tke = + stk::math::max(tke_.get(node, 0), 1.0e-12); + const NodeKernelTraits::DblType sdr = sdr_.get(node, 0); + const NodeKernelTraits::DblType beta = beta_.get(node, 0); + const NodeKernelTraits::DblType wallDist = minDist_.get(node, 0); + const NodeKernelTraits::DblType avgResAdeq = avgResAdeq_.get(node, 0); + + for (int d = 0; d < nDim_; d++) { + avgU[d] = avgVelocity_.get(node, d); + fluctU[d] = velocity_.get(node, d) - avgVelocity_.get(node, d); + coords[d] = coordinates_.get(node, d); + } + + const NodeKernelTraits::DblType ReT = rho * tke / sdr / mu; + const NodeKernelTraits::DblType Rbeta = 8.0; + const NodeKernelTraits::DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + + const NodeKernelTraits::DblType eps = betaStarLowRe * tke * sdr; + + const NodeKernelTraits::DblType smallCl_ = 2.0; + const NodeKernelTraits::DblType clOffset_ = 0.2; + + NodeKernelTraits::DblType length = + (forceCl_ + (1.0 - stk::math::max(beta, 1.0 - clOffset_)) / clOffset_ * + (smallCl_ - forceCl_)) * + stk::math::pow(beta * tke, 1.5) / eps; + length = stk::math::max( + length, + Ceta_ * (stk::math::pow(mu / rho, 0.75) / stk::math::pow(eps, 0.25))); + + const NodeKernelTraits::DblType lengthY = stk::math::min(length, wallDist); + + NodeKernelTraits::DblType T_beta = beta * tke / eps; + T_beta = stk::math::max(T_beta, Ct_ * stk::math::sqrt(mu / rho / eps)); + T_beta = blT_ * T_beta; + + // FIXME : Make this aware of wall direction, for now it is + // generalized using lengthY for all directions + const NodeKernelTraits::DblType clipLengthX = + stk::math::min(lengthY, periodicForcingLengthX_); + const NodeKernelTraits::DblType clipLengthY = + stk::math::min(lengthY, periodicForcingLengthY_); + const NodeKernelTraits::DblType clipLengthZ = + stk::math::min(lengthY, periodicForcingLengthZ_); + + const NodeKernelTraits::DblType ratioX = + std::floor(periodicForcingLengthX_ / (clipLengthX + 1.e-12) + 0.5); + const NodeKernelTraits::DblType ratioY = + std::floor(periodicForcingLengthY_ / (clipLengthY + 1.e-12) + 0.5); + const NodeKernelTraits::DblType ratioZ = + std::floor(periodicForcingLengthZ_ / (clipLengthZ + 1.e-12) + 0.5); + + const NodeKernelTraits::DblType denomX = periodicForcingLengthX_ / ratioX; + const NodeKernelTraits::DblType denomY = periodicForcingLengthY_ / ratioY; + const NodeKernelTraits::DblType denomZ = periodicForcingLengthZ_ / ratioZ; + + const NodeKernelTraits::DblType ax = M_PI / denomX; + const NodeKernelTraits::DblType ay = M_PI / denomY; + const NodeKernelTraits::DblType az = M_PI / denomZ; + + // Then we calculate the arguments for the Taylor-Green Vortex + const NodeKernelTraits::DblType xarg = ax * (coords[0] - avgU[0] * time_); + const NodeKernelTraits::DblType yarg = ay * (coords[1] - avgU[1] * time_); + const NodeKernelTraits::DblType zarg = az * (coords[2] - avgU[2] * time_); + + // Now we calculate the initial Taylor-Green field + NodeKernelTraits::DblType hX = 1. / 3. * stk::math::cos(xarg) * + stk::math::sin(yarg) * stk::math::sin(zarg); + NodeKernelTraits::DblType hY = + -1. * stk::math::sin(xarg) * stk::math::cos(yarg) * stk::math::sin(zarg); + NodeKernelTraits::DblType hZ = 2. / 3. * stk::math::sin(xarg) * + stk::math::sin(yarg) * stk::math::cos(zarg); + + // Now we calculate the scaling of the initial field + const NodeKernelTraits::DblType v2 = tvisc * eps / (v2cMu_ * rho * tke); + const NodeKernelTraits::DblType F_target = + forceFactor_ * stk::math::sqrt(beta * v2) / T_beta; + + const NodeKernelTraits::DblType prod_r_temp = + (F_target * dt_) * (hX * fluctU[0] + hY * fluctU[1] + hZ * fluctU[2]); + + const NodeKernelTraits::DblType prod_r_sgn = + stk::math::if_then_else(prod_r_temp < 0.0, -1.0, 1.0); + const NodeKernelTraits::DblType prod_r_abs = prod_r_sgn * prod_r_temp; + + const NodeKernelTraits::DblType prod_r = + stk::math::if_then_else(prod_r_abs >= 1.0e-15, prod_r_temp, 0.0); + + const NodeKernelTraits::DblType b_kol = + stk::math::min(blKol_ * stk::math::sqrt(mu * eps / rho) / tke, 1.0); + + const NodeKernelTraits::DblType bhat = stk::math::if_then_else( + (1.0 - b_kol) > 0.0, (1.0 - beta) / (1.0 - b_kol), 10000.0); + + NodeKernelTraits::DblType C_F_tmp = + -1.0 * stk::math::tanh( + 1.0 - 1.0 / stk::math::sqrt(stk::math::min(avgResAdeq, 1.0))); + + C_F_tmp = + C_F_tmp * + (1.0 - stk::math::min(stk::math::tanh(10.0 * (bhat - 1.0)) + 1.0, 1.0)); + + const NodeKernelTraits::DblType C_F = + stk::math::if_then_else(prod_r >= 0.0, F_target * C_F_tmp, 0.0); + + // Now we determine the actual forcing field + NodeKernelTraits::DblType gX = C_F * hX; + NodeKernelTraits::DblType gY = C_F * hY; + NodeKernelTraits::DblType gZ = C_F * hZ; + + forcingComp_.get(node, 0) = gX; + forcingComp_.get(node, 1) = gY; + forcingComp_.get(node, 2) = gZ; + + rhs(0) += dualVolume * gX; + rhs(1) += dualVolume * gY; + rhs(2) += dualVolume * gZ; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/MomentumSSTAMSForcingNodeKernel.C b/src/node_kernels/MomentumSSTAMSForcingNodeKernel.C index 48a666b15..1b9bdee9b 100644 --- a/src/node_kernels/MomentumSSTAMSForcingNodeKernel.C +++ b/src/node_kernels/MomentumSSTAMSForcingNodeKernel.C @@ -21,6 +21,7 @@ namespace nalu { MomentumSSTAMSForcingNodeKernel::MomentumSSTAMSForcingNodeKernel( const stk::mesh::BulkData& bulk, const SolutionOptions& solnOpts) : NGPNodeKernel(), + turbModel_(solnOpts.turbulenceModel_), betaStar_(solnOpts.get_turb_model_constant(TM_betaStar)), forceCl_(solnOpts.get_turb_model_constant(TM_forCl)), Ceta_(solnOpts.get_turb_model_constant(TM_forCeta)), @@ -55,6 +56,7 @@ MomentumSSTAMSForcingNodeKernel::MomentumSSTAMSForcingNodeKernel( betaID_ = get_field_ordinal(meta, "k_ratio"); MijID_ = get_field_ordinal(meta, "metric_tensor"); minDistID_ = get_field_ordinal(meta, "minimum_distance_to_wall"); + fOneBlendID_ = get_field_ordinal(meta, "sst_f_one_blending"); // average quantities avgVelocityID_ = get_field_ordinal(meta, "average_velocity"); @@ -101,6 +103,7 @@ MomentumSSTAMSForcingNodeKernel::setup(Realm& realm) beta_ = fieldMgr.get_field(betaID_); Mij_ = fieldMgr.get_field(MijID_); minDist_ = fieldMgr.get_field(minDistID_); + fOneBlend_ = fieldMgr.get_field(fOneBlendID_); avgVelocity_ = fieldMgr.get_field(avgVelocityID_); avgResAdeq_ = fieldMgr.get_field(avgResAdeqID_); forcingComp_ = fieldMgr.get_field(forcingCompID_); @@ -134,6 +137,7 @@ MomentumSSTAMSForcingNodeKernel::execute( const NodeKernelTraits::DblType beta = beta_.get(node, 0); const NodeKernelTraits::DblType wallDist = minDist_.get(node, 0); const NodeKernelTraits::DblType avgResAdeq = avgResAdeq_.get(node, 0); + const NodeKernelTraits::DblType fOneBlend = fOneBlend_.get(node, 0); for (int d = 0; d < nDim_; d++) { avgU[d] = avgVelocity_.get(node, d); @@ -141,7 +145,18 @@ MomentumSSTAMSForcingNodeKernel::execute( coords[d] = coordinates_.get(node, d); } - const NodeKernelTraits::DblType eps = betaStar_ * tke * sdr; + const NodeKernelTraits::DblType ReT = rho * tke / sdr / mu; + const NodeKernelTraits::DblType Rbeta = 8.0; + const NodeKernelTraits::DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + const NodeKernelTraits::DblType betaStarBlend = + fOneBlend * betaStarLowRe + (1.0 - fOneBlend) * betaStar_; + + const NodeKernelTraits::DblType bStar = stk::math::if_then_else( + turbModel_ == TurbulenceModel::SST_AMS, betaStar_, betaStarBlend); + + const NodeKernelTraits::DblType eps = bStar * tke * sdr; const NodeKernelTraits::DblType smallCl_ = 2.0; const NodeKernelTraits::DblType clOffset_ = 0.2; @@ -185,9 +200,13 @@ MomentumSSTAMSForcingNodeKernel::execute( const NodeKernelTraits::DblType az = M_PI / denomZ; // Then we calculate the arguments for the Taylor-Green Vortex - const NodeKernelTraits::DblType xarg = ax * (coords[0] + avgU[0] * time_); - const NodeKernelTraits::DblType yarg = ay * (coords[1] + avgU[1] * time_); - const NodeKernelTraits::DblType zarg = az * (coords[2] + avgU[2] * time_); + // const NodeKernelTraits::DblType xarg = ax * (coords[0] - avgU[0] * time_); + // const NodeKernelTraits::DblType yarg = ay * (coords[1] - avgU[1] * time_); + // const NodeKernelTraits::DblType zarg = az * (coords[2] - avgU[2] * time_); + + const NodeKernelTraits::DblType xarg = ax * (coords[0]); + const NodeKernelTraits::DblType yarg = ay * (coords[1]); + const NodeKernelTraits::DblType zarg = az * (coords[2]); // Now we calculate the initial Taylor-Green field NodeKernelTraits::DblType hX = 1. / 3. * stk::math::cos(xarg) * @@ -198,7 +217,7 @@ MomentumSSTAMSForcingNodeKernel::execute( stk::math::sin(yarg) * stk::math::cos(zarg); // Now we calculate the scaling of the initial field - const NodeKernelTraits::DblType v2 = tvisc * betaStar_ * sdr / (cMu_ * rho); + const NodeKernelTraits::DblType v2 = tvisc * bStar * sdr / (cMu_ * rho); const NodeKernelTraits::DblType F_target = forceFactor_ * stk::math::sqrt(beta * v2) / T_beta; diff --git a/src/node_kernels/SDRKOAMSNodeKernel.C b/src/node_kernels/SDRKOAMSNodeKernel.C new file mode 100644 index 000000000..9d73b77a7 --- /dev/null +++ b/src/node_kernels/SDRKOAMSNodeKernel.C @@ -0,0 +1,136 @@ +// 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/SDRKOAMSNodeKernel.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 { + +SDRKOAMSNodeKernel::SDRKOAMSNodeKernel(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")), + viscID_(get_field_ordinal(meta, "viscosity")), + dudxID_(get_field_ordinal(meta, "average_dudx")), + dkdxID_(get_field_ordinal(meta, "dkdx")), + dwdxID_(get_field_ordinal(meta, "dwdx")), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + prodID_(get_field_ordinal(meta, "average_production")), + nDim_(meta.spatial_dimension()) +{ +} + +void +SDRKOAMSNodeKernel::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_); + visc_ = fieldMgr.get_field(viscID_); + dudx_ = fieldMgr.get_field(dudxID_); + dkdx_ = fieldMgr.get_field(dkdxID_); + dwdx_ = fieldMgr.get_field(dwdxID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + prod_ = fieldMgr.get_field(prodID_); + + // 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); +} + +KOKKOS_FUNCTION +void +SDRKOAMSNodeKernel::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 visc = visc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + DblType Pk = prod_.get(node, 0); + + DblType crossDiff = 0.0; + for (int i = 0; i < nDim_; ++i) { + crossDiff += dkdx_.get(node, i) * dwdx_.get(node, i); + } + + DblType chi_numer = 0.0; + for (int i = 0; i < nDim_; ++i) { + for (int j = 0; j < nDim_; ++j) { + for (int k = 0; k < nDim_; ++k) { + const auto rot_ij = 0.5 * (dudx_.get(node, i * nDim_ + j) - + dudx_.get(node, j * nDim_ + i)); + const auto rot_jk = 0.5 * (dudx_.get(node, j * nDim_ + k) - + dudx_.get(node, k * nDim_ + j)); + const auto str_ki = 0.5 * (dudx_.get(node, k * nDim_ + i) + + dudx_.get(node, i * nDim_ + k)); + chi_numer += rot_ij * rot_jk * str_ki; + } + } + } + + const NodeKernelTraits::DblType alpha0_star = 0.072 / 3.0; + const NodeKernelTraits::DblType alpha_inf = 0.52; + const NodeKernelTraits::DblType alpha0 = 1.0 / 9.0; + const NodeKernelTraits::DblType Rk = 6.0; + const NodeKernelTraits::DblType R_beta = 8.0; + const NodeKernelTraits::DblType Rw = 2.95; + const NodeKernelTraits::DblType ReT = density * tke / sdr / visc; + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + DblType Dk = betaStarLowRe * density * sdr * tke; + + const DblType chi_omega = stk::math::abs( + chi_numer / stk::math::pow(0.09 * stk::math::max(sdr, 1.e-8), 3.0)); + const DblType beta = + 0.072 * (1.0 + 70.0 * chi_omega) / (1.0 + 80.0 * chi_omega); + + const NodeKernelTraits::DblType alpha_star = + (alpha0_star + ReT / Rk) / (1.0 + ReT / Rk); + const NodeKernelTraits::DblType alpha = + (alpha_inf / alpha_star) * ((alpha0 + ReT / Rw) / (1.0 + ReT / Rw)); + + // Pw includes 1/tvisc scaling; tvisc may be zero at a dirichlet low Re + // approach (clip) + const NodeKernelTraits::DblType Pw = + alpha * Pk * sdr / stk::math::max(tke, 1.e-12); + // Production term with appropriate clipping of tvisc + const DblType Dw = beta * density * sdr * sdr; + + rhs(0) += (Pw - Dw) * dVol; + lhs(0, 0) += 2.0 * beta * density * sdr * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/SDRSSTAMSNodeKernel.C b/src/node_kernels/SDRSSTAMSNodeKernel.C index c2b25d3db..a54b809f8 100644 --- a/src/node_kernels/SDRSSTAMSNodeKernel.C +++ b/src/node_kernels/SDRSSTAMSNodeKernel.C @@ -62,6 +62,7 @@ SDRSSTAMSNodeKernel::setup(Realm& realm) gammaOne_ = realm.get_turb_model_constant(TM_gammaOne); gammaTwo_ = realm.get_turb_model_constant(TM_gammaTwo); tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); + sdrAmb_ = realm.get_turb_model_constant(TM_sdrAmb); lengthScaleLimiter_ = realm.solutionOptions_->lengthScaleLimiter_; if (lengthScaleLimiter_) { @@ -146,7 +147,10 @@ SDRSSTAMSNodeKernel::execute( const NodeKernelTraits::DblType dualVolume = dualNodalVolume_.get(node, 0); - rhs(0) += (Pw - Dw + Sw) * dualVolume; + // SUST source term + const NodeKernelTraits::DblType Dwamb = beta * rho * sdrAmb_ * sdrAmb_; + + rhs(0) += (Pw - Dw + Dwamb + Sw) * dualVolume; lhs(0, 0) += (2.0 * beta * rho * sdr + stk::math::max(Sw / sdr, 0.0)) * dualVolume; diff --git a/src/node_kernels/SDRSSTLRAMSNodeKernel.C b/src/node_kernels/SDRSSTLRAMSNodeKernel.C new file mode 100644 index 000000000..4b136a57f --- /dev/null +++ b/src/node_kernels/SDRSSTLRAMSNodeKernel.C @@ -0,0 +1,163 @@ +// 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/SDRSSTLRAMSNodeKernel.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 { + +SDRSSTLRAMSNodeKernel::SDRSSTLRAMSNodeKernel( + const stk::mesh::MetaData& meta, const std::string coordsName) + : 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")), + viscID_(get_field_ordinal(meta, "viscosity")), + dudxID_(get_field_ordinal(meta, "average_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")), + betaID_(get_field_ordinal(meta, "k_ratio")), + prodID_(get_field_ordinal(meta, "average_production")), + nDim_(meta.spatial_dimension()) +{ +} + +void +SDRSSTLRAMSNodeKernel::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_); + visc_ = fieldMgr.get_field(viscID_); + 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_); + beta_ = fieldMgr.get_field(betaID_); + prod_ = fieldMgr.get_field(prodID_); + + // Update turbulence model constants + betaStar_ = realm.get_turb_model_constant(TM_betaStar); + tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); + alphaInf_ = realm.get_turb_model_constant(TM_alphaInf); + 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); + sstLRDestruct_ = realm.get_turb_model_constant(TM_sstLRDestruct); + sstLRProd_ = realm.get_turb_model_constant(TM_sstLRProd); + sdrAmb_ = realm.get_turb_model_constant(TM_sdrAmb); +} + +KOKKOS_FUNCTION +void +SDRSSTLRAMSNodeKernel::execute( + NodeKernelTraits::LhsType& lhs, + NodeKernelTraits::RhsType& rhs, + const stk::mesh::FastMeshIndex& node) +{ + using DblType = NodeKernelTraits::DblType; + + const DblType tke = stk::math::max(tke_.get(node, 0), 1.0e-12); + const DblType sdr = sdr_.get(node, 0); + const DblType density = density_.get(node, 0); + const DblType tvisc = tvisc_.get(node, 0); + const DblType visc = visc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + const DblType fOneBlend = fOneBlend_.get(node, 0); + + DblType crossDiff = 0.0; + for (int d = 0; d < nDim_; ++d) + crossDiff += dkdx_.get(node, d) * dwdx_.get(node, d); + + // Clip negative productions, consistent with TKE + DblType Pk = stk::math::max(prod_.get(node, 0), 0.0); + + DblType chi_numer = 0.0; + for (int i = 0; i < nDim_; ++i) { + for (int j = 0; j < nDim_; ++j) { + for (int k = 0; k < nDim_; ++k) { + const auto rot_ij = 0.5 * (dudx_.get(node, i * nDim_ + j) - + dudx_.get(node, j * nDim_ + i)); + const auto rot_jk = 0.5 * (dudx_.get(node, j * nDim_ + k) - + dudx_.get(node, k * nDim_ + j)); + const auto str_ki = 0.5 * (dudx_.get(node, k * nDim_ + i) + + dudx_.get(node, i * nDim_ + k)); + chi_numer += rot_ij * rot_jk * str_ki; + } + } + } + + const DblType chi_omega = stk::math::abs( + chi_numer / stk::math::pow(0.09 * stk::math::max(sdr, 1.e-8), 3.0)); + const DblType beta = + 0.072 * (1.0 + 70.0 * chi_omega) / (1.0 + 80.0 * chi_omega); + + const DblType alpha0_star = 0.072 / 3.0; + const DblType alpha_inf = alphaInf_; + const DblType alpha0 = 1.0 / 9.0; + const DblType Rk = 6.0; + const DblType R_beta = 8.0; + const DblType Rw = 2.95; + const DblType ReT = density * tke / sdr / visc; + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + + const DblType alpha_star = (alpha0_star + ReT / Rk) / (1.0 + ReT / Rk); + const DblType alpha = + (alpha_inf / alpha_star) * ((alpha0 + ReT / Rw) / (1.0 + ReT / Rw)); + + // Blend constants for SDR + const DblType omf1 = (1.0 - fOneBlend); + const DblType betaBlend = + sstLRDestruct_ * (fOneBlend * beta + omf1 * betaTwo_) + + (1.0 - sstLRDestruct_) * (fOneBlend * betaOne_ + omf1 * betaTwo_); + const DblType gamma = + sstLRProd_ * (fOneBlend * alpha + omf1 * gammaTwo_) + + (1.0 - sstLRProd_) * (fOneBlend * gammaOne_ + omf1 * gammaTwo_); + const DblType sigmaD = 2.0 * omf1 * sigmaWTwo_; + const DblType betaStarBlend = fOneBlend * betaStarLowRe + omf1 * betaStar_; + + const DblType Dk = betaStarBlend * density * sdr * tke; + + // Clip production term and clip negative productions + Pk = stk::math::min(tkeProdLimitRatio_ * Dk, stk::math::max(Pk, 0.0)); + + // Pw includes 1/tvisc scaling; tvisc may be zero at a dirichlet low Re + // approach (clip) + const DblType Pw = gamma * Pk * sdr / stk::math::max(tke, 1.e-12); + const DblType Dw = betaBlend * density * sdr * sdr; + const DblType Sw = sigmaD * density * crossDiff / sdr; + + // SUST source term + const DblType Dwamb = betaBlend * density * sdrAmb_ * sdrAmb_; + + rhs(0) += (Pw - Dw + Dwamb + Sw) * dVol; + lhs(0, 0) += + (2.0 * betaBlend * density * sdr + stk::math::max(Sw / sdr, 0.0)) * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/SDRSSTLRNodeKernel.C b/src/node_kernels/SDRSSTLRNodeKernel.C index 1527fd77a..d0935015a 100644 --- a/src/node_kernels/SDRSSTLRNodeKernel.C +++ b/src/node_kernels/SDRSSTLRNodeKernel.C @@ -54,6 +54,7 @@ SDRSSTLRNodeKernel::setup(Realm& realm) // Update turbulence model constants betaStar_ = realm.get_turb_model_constant(TM_betaStar); tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); + alphaInf_ = realm.get_turb_model_constant(TM_alphaInf); sigmaWTwo_ = realm.get_turb_model_constant(TM_sigmaWTwo); betaOne_ = realm.get_turb_model_constant(TM_betaOne); betaTwo_ = realm.get_turb_model_constant(TM_betaTwo); @@ -115,7 +116,7 @@ SDRSSTLRNodeKernel::execute( // JAM: Changes for SWH LowRe const DblType alpha0_star = 0.072 / 3.0; - const DblType alpha_inf = 0.52; + const DblType alpha_inf = alphaInf_; const DblType alpha0 = 1.0 / 9.0; const DblType Rk = 6.0; const DblType Rw = 2.95; diff --git a/src/node_kernels/TDRKEAMSNodeKernel.C b/src/node_kernels/TDRKEAMSNodeKernel.C new file mode 100644 index 000000000..a3a39ec8b --- /dev/null +++ b/src/node_kernels/TDRKEAMSNodeKernel.C @@ -0,0 +1,97 @@ +// 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/TDRKEAMSNodeKernel.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 { + +TDRKEAMSNodeKernel::TDRKEAMSNodeKernel( + const stk::mesh::MetaData& meta, const std::string /*coordsName*/) + : NGPNodeKernel(), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + viscID_(get_field_ordinal(meta, "viscosity")), + tkeID_(get_field_ordinal(meta, "turbulent_ke")), + tdrID_(get_field_ordinal(meta, "total_dissipation_rate")), + dplusID_(get_field_ordinal(meta, "dplus_wall_function")), + wallDistID_(get_field_ordinal(meta, "minimum_distance_to_wall")), + prodID_(get_field_ordinal(meta, "average_production")), + densityID_(get_field_ordinal(meta, "density")), + nDim_(meta.spatial_dimension()) +{ +} + +void +TDRKEAMSNodeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + + tke_ = fieldMgr.get_field(tkeID_); + tdr_ = fieldMgr.get_field(tdrID_); + density_ = fieldMgr.get_field(densityID_); + visc_ = fieldMgr.get_field(viscID_); + wallDist_ = fieldMgr.get_field(wallDistID_); + dplus_ = fieldMgr.get_field(dplusID_); + prod_ = fieldMgr.get_field(prodID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + + const std::string dofName = "total_dissipation_rate"; + // relaxFac_ = realm.solutionOptions_->get_relaxation_factor(dofName); + + // Update turbulence model constants + cEpsOne_ = realm.get_turb_model_constant(TM_cEpsOne); + cEpsTwo_ = realm.get_turb_model_constant(TM_cEpsTwo); + fOne_ = realm.get_turb_model_constant(TM_fOne); +} + +KOKKOS_FUNCTION +void +TDRKEAMSNodeKernel::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 tdr = tdr_.get(node, 0); + const DblType density = density_.get(node, 0); + const DblType visc = visc_.get(node, 0); + const DblType wallDist = wallDist_.get(node, 0); + const DblType dplus = dplus_.get(node, 0); + const DblType prod = prod_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + + const DblType Re_t = + density * tke * tke / visc / stk::math::max(tdr, 1.0e-16); + const DblType fTwo = 1.0 - 0.4 / 1.8 * stk::math::exp(-Re_t * Re_t / 36.0); + + // Production term with appropriate clipping of tvisc + const DblType Pe = + cEpsOne_ * fOne_ * prod * tdr / stk::math::max(tke, 1.0e-16); + const DblType DeFac = + cEpsTwo_ * fTwo * density * tdr / stk::math::max(tke, 1.0e-16); + const DblType De = DeFac * tdr; + const DblType LeFac = 2.0 * visc * stk::math::exp(-0.5 * dplus) / + stk::math::max(wallDist * wallDist, 1.0e-16); + const DblType Le = -LeFac * tdr; + + rhs(0) += (Pe - De + Le) * dVol; + lhs(0, 0) += (2.0 * DeFac + LeFac) * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/TKEKEAMSNodeKernel.C b/src/node_kernels/TKEKEAMSNodeKernel.C new file mode 100644 index 000000000..13ccc3fa3 --- /dev/null +++ b/src/node_kernels/TKEKEAMSNodeKernel.C @@ -0,0 +1,80 @@ +// 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/TKEKEAMSNodeKernel.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 { + +TKEKEAMSNodeKernel::TKEKEAMSNodeKernel( + const stk::mesh::MetaData& meta, const std::string coordsName) + : NGPNodeKernel(), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + viscID_(get_field_ordinal(meta, "viscosity")), + tkeID_(get_field_ordinal(meta, "turbulent_ke")), + tdrID_(get_field_ordinal(meta, "total_dissipation_rate")), + prodID_(get_field_ordinal(meta, "average_production")), + densityID_(get_field_ordinal(meta, "density")), + wallDistID_(get_field_ordinal(meta, "minimum_distance_to_wall")), + nDim_(meta.spatial_dimension()) +{ +} + +void +TKEKEAMSNodeKernel::setup(Realm& realm) +{ + const auto& fieldMgr = realm.ngp_field_manager(); + + tke_ = fieldMgr.get_field(tkeID_); + tdr_ = fieldMgr.get_field(tdrID_); + density_ = fieldMgr.get_field(densityID_); + visc_ = fieldMgr.get_field(viscID_); + prod_ = fieldMgr.get_field(prodID_); + wallDist_ = fieldMgr.get_field(wallDistID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); +} + +KOKKOS_FUNCTION +void +TKEKEAMSNodeKernel::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 tdr = tdr_.get(node, 0); + const DblType density = density_.get(node, 0); + const DblType visc = visc_.get(node, 0); + const DblType prod = prod_.get(node, 0); + const DblType wallDist = wallDist_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + + DblType Dk = density * tdr; + + const DblType lFac = + 2.0 * visc / stk::math::max(wallDist * wallDist, 1.0e-16); + DblType Lk = -lFac * tke; + + rhs(0) += (prod - Dk + Lk) * dVol; + lhs(0, 0) += lFac * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/TKEKOAMSNodeKernel.C b/src/node_kernels/TKEKOAMSNodeKernel.C new file mode 100644 index 000000000..62e711b24 --- /dev/null +++ b/src/node_kernels/TKEKOAMSNodeKernel.C @@ -0,0 +1,83 @@ +// 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/TKEKOAMSNodeKernel.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 { + +TKEKOAMSNodeKernel::TKEKOAMSNodeKernel(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")), + viscID_(get_field_ordinal(meta, "viscosity")), + prodID_(get_field_ordinal(meta, "average_production")), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + nDim_(meta.spatial_dimension()) +{ +} + +void +TKEKOAMSNodeKernel::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_); + visc_ = fieldMgr.get_field(viscID_); + prod_ = fieldMgr.get_field(prodID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + + // Update turbulence model constants + betaStar_ = realm.get_turb_model_constant(TM_betaStar); + tkeProdLimitRatio_ = realm.get_turb_model_constant(TM_tkeProdLimitRatio); +} + +KOKKOS_FUNCTION +void +TKEKOAMSNodeKernel::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 visc = visc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + + DblType Pk = prod_.get(node, 0); + + const DblType ReT = density * tke / sdr / visc; + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + DblType Dk = betaStarLowRe * density * sdr * tke; + + rhs(0) += (Pk - Dk) * dVol; + lhs(0, 0) += betaStarLowRe * density * sdr * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/src/node_kernels/TKESSTAMSNodeKernel.C b/src/node_kernels/TKESSTAMSNodeKernel.C index 1aac43bc1..910cee463 100644 --- a/src/node_kernels/TKESSTAMSNodeKernel.C +++ b/src/node_kernels/TKESSTAMSNodeKernel.C @@ -51,6 +51,8 @@ TKESSTAMSNodeKernel::setup(Realm& realm) // 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 @@ -71,7 +73,11 @@ TKESSTAMSNodeKernel::execute( const NodeKernelTraits::DblType dualVolume = dualNodalVolume_.get(node, 0); - rhs(0) += (Pk - Dk) * dualVolume; + // SUST source term + const NodeKernelTraits::DblType Dkamb = + betaStar_ * rho_.get(node, 0) * sdrAmb_ * tkeAmb_; + + rhs(0) += (Pk - Dk + Dkamb) * dualVolume; lhs(0, 0) += tkeFac * dualVolume; } diff --git a/src/node_kernels/TKESSTLRAMSNodeKernel.C b/src/node_kernels/TKESSTLRAMSNodeKernel.C new file mode 100644 index 000000000..36f963f4c --- /dev/null +++ b/src/node_kernels/TKESSTLRAMSNodeKernel.C @@ -0,0 +1,102 @@ +// 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/TKESSTLRAMSNodeKernel.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 { + +TKESSTLRAMSNodeKernel::TKESSTLRAMSNodeKernel( + const stk::mesh::MetaData& meta, const std::string coordsName) + : 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")), + viscID_(get_field_ordinal(meta, "viscosity")), + dudxID_(get_field_ordinal(meta, "dudx")), + dualNodalVolumeID_(get_field_ordinal(meta, "dual_nodal_volume")), + fOneBlendID_(get_field_ordinal(meta, "sst_f_one_blending")), + prodID_(get_field_ordinal(meta, "average_production")), + nDim_(meta.spatial_dimension()) +{ +} + +void +TKESSTLRAMSNodeKernel::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_); + visc_ = fieldMgr.get_field(viscID_); + dudx_ = fieldMgr.get_field(dudxID_); + fOneBlend_ = fieldMgr.get_field(fOneBlendID_); + dualNodalVolume_ = fieldMgr.get_field(dualNodalVolumeID_); + prod_ = fieldMgr.get_field(prodID_); + + // 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 +TKESSTLRAMSNodeKernel::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 visc = visc_.get(node, 0); + const DblType dVol = dualNodalVolume_.get(node, 0); + const DblType fOneBlend = fOneBlend_.get(node, 0); + + DblType Pk = prod_.get(node, 0); + + const DblType ReT = density * tke / sdr / visc; + const DblType Rbeta = 8.0; + const DblType betaStarLowRe = + betaStar_ * (4.0 / 15.0 + stk::math::pow(ReT / Rbeta, 4.0)) / + (1.0 + stk::math::pow(ReT / Rbeta, 4.0)); + + // Blend into SST coefficient + const DblType betaStarBlend = + fOneBlend * betaStarLowRe + (1.0 - fOneBlend) * betaStar_; + + const DblType Dk = betaStarBlend * density * sdr * tke; + + // Clip production term and prevent Pk from being negative + Pk = stk::math::min(tkeProdLimitRatio_ * Dk, stk::math::max(Pk, 0.0)); + + // SUST source term + const DblType Dkamb = betaStarBlend * density * sdrAmb_ * tkeAmb_; + + rhs(0) += (Pk - Dk + Dkamb) * dVol; + lhs(0, 0) += betaStarBlend * density * sdr * dVol; +} + +} // namespace nalu +} // namespace sierra diff --git a/unit_tests/UnitTestHelperObjects.h b/unit_tests/UnitTestHelperObjects.h index bdf065a1f..b93135825 100644 --- a/unit_tests/UnitTestHelperObjects.h +++ b/unit_tests/UnitTestHelperObjects.h @@ -222,14 +222,16 @@ struct EdgeHelperObjects : public HelperObjectsBase sierra::nalu::AssembleEdgeSolverAlgorithm* edgeAlg{nullptr}; }; -struct EdgeKernelHelperObjects : public HelperObjectsBase +struct AMSEdgeKernelHelperObjects : public HelperObjectsBase { - EdgeKernelHelperObjects( + AMSEdgeKernelHelperObjects( std::shared_ptr bulk, stk::topology topo, int numDof, - stk::mesh::Part* part) - : HelperObjectsBase(bulk), + stk::mesh::Part* part, + YAML::Node yaml_node = unit_test_utils::get_default_inputs(), + YAML::Node realm_node = unit_test_utils::get_realm_default_node()) + : HelperObjectsBase(bulk, yaml_node, realm_node), linsys(new TestEdgeLinearSystem(realm, numDof, &eqSystem, topo)) { eqSystem.linsys_ = linsys; diff --git a/unit_tests/UnitTestMijTensor.C b/unit_tests/UnitTestMijTensor.C index f149674f1..59f45c49c 100644 --- a/unit_tests/UnitTestMijTensor.C +++ b/unit_tests/UnitTestMijTensor.C @@ -26,8 +26,6 @@ #include "UnitTestUtils.h" -#if !defined(KOKKOS_ENABLE_GPU) - namespace { std::vector @@ -216,4 +214,3 @@ TEST(MijTensor, hex8) { test_metric_for_topo_3D(stk::topology::HEX_8, 1.0e-10); } -#endif diff --git a/unit_tests/edge_kernels/UnitTestMomentumSSTAMSDiffEdge.C b/unit_tests/edge_kernels/UnitTestMomentumSSTAMSDiffEdge.C index de9a6a8bc..849619898 100644 --- a/unit_tests/edge_kernels/UnitTestMomentumSSTAMSDiffEdge.C +++ b/unit_tests/edge_kernels/UnitTestMomentumSSTAMSDiffEdge.C @@ -12,521 +12,146 @@ #include "UnitTestHelperObjects.h" #include "edge_kernels/MomentumSSTAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumSSTLRAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumKOAMSDiffEdgeKernel.h" +#include "edge_kernels/MomentumKEAMSDiffEdgeKernel.h" namespace { + +const std::string realmSSTAMSSettings = + "- name: unitTestRealm \n" + " use_edges: yes \n" + " \n" + " equation_systems: \n" + " name: theEqSys \n" + " max_iterations: 2 \n" + " \n" + " solver_system_specification: \n" + " velocity: solve_scalar \n" + " turbulent_ke: solve_scalar \n" + " specific_dissipation_rate: solve_scalar \n" + " pressure: solve_cont \n" + " ndtw: solve_cont \n" + " \n" + " systems: \n" + " - WallDistance: \n" + " name: myNDTW \n" + " max_iterations: 1 \n" + " convergence_tolerance: 1e-5 \n" + " \n" + " - LowMachEOM: \n" + " name: myLowMach \n" + " max_iterations: 1 \n" + " convergence_tolerance: 1e-8 \n" + " \n" + " - ShearStressTransport: \n" + " name: mySST \n" + " max_iterations: 1 \n" + " convergence_tolerance: 1e-8 \n" + " \n" + " time_step_control: \n" + " target_courant: 2.0 \n" + " time_step_change_factor: 1.2 \n" + " \n" + " solution_options: \n" + " name: myOptions \n" + " turbulence_model: sst_ams \n" + " projected_timescale_type: momentum_diag_inv \n" + " \n" + " options: \n" + " - hybrid_factor: \n" + " turbulent_ke: 1.0 \n" + " specific_dissipation_rate: 1.0 \n" + " \n" + " - alpha_upw: \n" + " velocity: 1.0 \n" + " turbulent_ke: 1.0 \n" + " specific_dissipation_rate: 1.0 \n" + " \n" + " - upw_factor: \n" + " velocity: 1.0 \n" + " turbulent_ke: 0.0 \n" + " specific_dissipation_rate: 0.0 \n"; + +// clang-format off namespace hex8_golds { -namespace ams_diff { -static constexpr double rhs[24] = { - 0.088069343129783, -0.054753698167151, 0, - 0.043902291987831, 0.051585034673576, 0, - -0.084720224280197, -0.058399243076388, 0, - -0.047251410837417, 0.061567906569962, 0, - 0.074491904516922, -0.054753698167151, 0, - 0.0389564943094, 0.051534955236037, 0, - -0.070999855021463, -0.049039131690076, 0, - -0.042448543804859, 0.05225787462119, 0, +namespace sst_ams_diff { +static constexpr double rhs[24] = {0.088069343129783, -0.054753698167151, 0, 0.043902291987831, 0.051585034673576, 0, -0.084720224280197, -0.058399243076388, 0, -0.047251410837417, 0.061567906569962, 0, 0.074491904516922, -0.054753698167151, 0, 0.0389564943094, 0.051534955236037, 0, -0.070999855021463, -0.049039131690076, 0, -0.042448543804859, 0.05225787462119, 0, }; + +static constexpr double lhs[24][24] ={ +{0.37593796365399, 0, 0, -0.1654043452011, 0, 0, -0.12783144585235, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0.42106723690579, 0, 0, -0.082702172600548, 0, 0, -0.25566289170469, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0, 0.37593796365399, 0, 0, -0.082702172600548, 0, 0, -0.12783144585235, 0, 0, 0, 0, 0, -0.1654043452011, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{-0.1654043452011, 0, 0, 0.35781821144931, 0, 0, 0, 0, 0, -0.10971169364766, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, -0.082702172600548, 0, 0, 0.38482773249642, 0, 0, 0, 0, 0, -0.21942338729532, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0, -0.082702172600548, 0, 0, 0.35781821144931, 0, 0, 0, 0, 0, -0.10971169364766, 0, 0, 0, 0, 0, -0.1654043452011, 0, 0, 0, 0, 0, 0, }, +{-0.12783144585235, 0, 0, 0, 0, 0, 0.55780460414762, 0, 0, -0.28647532993836, 0, 0, 0, 0, 0, 0, 0, 0, -0.14349782835692, 0, 0, 0, 0, 0, }, +{0, -0.25566289170469, 0, 0, 0, 0, 0, 0.54239838503079, 0, 0, -0.14323766496918, 0, 0, 0, 0, 0, 0, 0, 0, -0.14349782835692, 0, 0, 0, 0, }, +{0, 0, -0.12783144585235, 0, 0, 0, 0, 0, 0.55806476753537, 0, 0, -0.14323766496918, 0, 0, 0, 0, 0, 0, 0, 0, -0.28699565671384, 0, 0, 0, }, +{0, 0, 0, -0.10971169364766, 0, 0, -0.28647532993836, 0, 0, 0.51835059583918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12216357225317, 0, 0, }, +{0, 0, 0, 0, -0.21942338729532, 0, 0, -0.14323766496918, 0, 0, 0.48482462451767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12216357225317, 0, }, +{0, 0, 0, 0, 0, -0.10971169364766, 0, 0, -0.14323766496918, 0, 0, 0.49727650312317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.24432714450633, }, +{-0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.35806435685833, 0, 0, -0.1654043452011, 0, 0, -0.10995783905669, 0, 0, 0, 0, 0, }, +{0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38532002331447, 0, 0, -0.082702172600548, 0, 0, -0.21991567811338, 0, 0, 0, 0, }, +{0, 0, -0.1654043452011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.35806435685833, 0, 0, -0.082702172600548, 0, 0, -0.10995783905669, 0, 0, 0, }, +{0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, -0.1654043452011, 0, 0, 0.34672882483311, 0, 0, 0, 0, 0, -0.09862230703147, 0, 0, }, +{0, 0, 0, 0, -0.082702172600548, 0, 0, 0, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0.36264895926404, 0, 0, 0, 0, 0, -0.19724461406294, 0, }, +{0, 0, 0, 0, 0, -0.1654043452011, 0, 0, 0, 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0.34672882483311, 0, 0, 0, 0, 0, -0.09862230703147, }, +{0, 0, 0, 0, 0, 0, -0.14349782835692, 0, 0, 0, 0, 0, -0.10995783905669, 0, 0, 0, 0, 0, 0.49825733736442, 0, 0, -0.24480166995081, 0, 0, }, +{0, 0, 0, 0, 0, 0, 0, -0.14349782835692, 0, 0, 0, 0, 0, -0.21991567811338, 0, 0, 0, 0, 0, 0.4858143414457, 0, 0, -0.12240083497541, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, -0.28699565671384, 0, 0, 0, 0, 0, -0.10995783905669, 0, 0, 0, 0, 0, 0.51935433074594, 0, 0, -0.12240083497541, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12216357225317, 0, 0, 0, 0, 0, -0.09862230703147, 0, 0, -0.24480166995081, 0, 0, 0.46558754923545, 0, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12216357225317, 0, 0, 0, 0, 0, -0.19724461406294, 0, 0, -0.12240083497541, 0, 0, 0.44180902129151, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.24432714450633, 0, 0, 0, 0, 0, -0.09862230703147, 0, 0, -0.12240083497541, 0, 0, 0.46535028651321, }, }; -static constexpr double lhs[24][24] = { - { - 0.37593796365399, - 0, - 0, - -0.1654043452011, - 0, - 0, - -0.12783144585235, - 0, - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, - 0.42106723690579, - 0, - 0, - -0.082702172600548, - 0, - 0, - -0.25566289170469, - 0, - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, 0, 0.37593796365399, - 0, 0, -0.082702172600548, - 0, 0, -0.12783144585235, - 0, 0, 0, - 0, 0, -0.1654043452011, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - }, - { - -0.1654043452011, - 0, - 0, - 0.35781821144931, - 0, - 0, - 0, - 0, - 0, - -0.10971169364766, - 0, - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, - -0.082702172600548, - 0, - 0, - 0.38482773249642, - 0, - 0, - 0, - 0, - 0, - -0.21942338729532, - 0, - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, 0, -0.082702172600548, - 0, 0, 0.35781821144931, - 0, 0, 0, - 0, 0, -0.10971169364766, - 0, 0, 0, - 0, 0, -0.1654043452011, - 0, 0, 0, - 0, 0, 0, - }, - { - -0.12783144585235, - 0, - 0, - 0, - 0, - 0, - 0.55780460414762, - 0, - 0, - -0.28647532993836, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.14349782835692, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, - -0.25566289170469, - 0, - 0, - 0, - 0, - 0, - 0.54239838503079, - 0, - 0, - -0.14323766496918, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.14349782835692, - 0, - 0, - 0, - 0, - }, - { - 0, 0, -0.12783144585235, 0, 0, 0, 0, 0, 0.55806476753537, - 0, 0, -0.14323766496918, 0, 0, 0, 0, 0, 0, - 0, 0, -0.28699565671384, 0, 0, 0, - }, - { - 0, - 0, - 0, - -0.10971169364766, - 0, - 0, - -0.28647532993836, - 0, - 0, - 0.51835059583918, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.12216357225317, - 0, - 0, - }, - { - 0, - 0, - 0, - 0, - -0.21942338729532, - 0, - 0, - -0.14323766496918, - 0, - 0, - 0.48482462451767, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.12216357225317, - 0, - }, - { - 0, 0, 0, - 0, 0, -0.10971169364766, - 0, 0, -0.14323766496918, - 0, 0, 0.49727650312317, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, -0.24432714450633, - }, - { - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0.35806435685833, - 0, - 0, - -0.1654043452011, - 0, - 0, - -0.10995783905669, - 0, - 0, - 0, - 0, - 0, - }, - { - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0.38532002331447, - 0, - 0, - -0.082702172600548, - 0, - 0, - -0.21991567811338, - 0, - 0, - 0, - 0, - }, - { - 0, 0, -0.1654043452011, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0.35806435685833, - 0, 0, -0.082702172600548, - 0, 0, -0.10995783905669, - 0, 0, 0, - }, - { - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.1654043452011, - 0, - 0, - 0.34672882483311, - 0, - 0, - 0, - 0, - 0, - -0.09862230703147, - 0, - 0, - }, - { - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.082702172600548, - 0, - 0, - 0.36264895926404, - 0, - 0, - 0, - 0, - 0, - -0.19724461406294, - 0, - }, - { - 0, 0, 0, 0, 0, -0.1654043452011, 0, 0, 0, - 0, 0, 0, 0, 0, -0.082702172600548, 0, 0, 0.34672882483311, - 0, 0, 0, 0, 0, -0.09862230703147, - }, - { - 0, - 0, - 0, - 0, - 0, - 0, - -0.14349782835692, - 0, - 0, - 0, - 0, - 0, - -0.10995783905669, - 0, - 0, - 0, - 0, - 0, - 0.49825733736442, - 0, - 0, - -0.24480166995081, - 0, - 0, - }, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.14349782835692, - 0, - 0, - 0, - 0, - 0, - -0.21991567811338, - 0, - 0, - 0, - 0, - 0, - 0.4858143414457, - 0, - 0, - -0.12240083497541, - 0, - }, - { - 0, 0, 0, - 0, 0, 0, - 0, 0, -0.28699565671384, - 0, 0, 0, - 0, 0, -0.10995783905669, - 0, 0, 0, - 0, 0, 0.51935433074594, - 0, 0, -0.12240083497541, - }, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.12216357225317, - 0, - 0, - 0, - 0, - 0, - -0.09862230703147, - 0, - 0, - -0.24480166995081, - 0, - 0, - 0.46558754923545, - 0, - 0, - }, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -0.12216357225317, - 0, - 0, - 0, - 0, - 0, - -0.19724461406294, - 0, - 0, - -0.12240083497541, - 0, - 0, - 0.44180902129151, - 0, - }, - { - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, -0.24432714450633, - 0, 0, 0, - 0, 0, -0.09862230703147, - 0, 0, -0.12240083497541, - 0, 0, 0.46535028651321, - }, +} // namespace sst_ams_diff +namespace ke_ams_diff { +static constexpr double rhs[24] = {0.085449014298766, -0.051898932126345, 0, 0.042307327929974, 0.04649316688805, 0, -0.080043249060471, -0.056932936468986, 0, -0.047713093168269, 0.062338701707281, 0, 0.071637798107362, -0.051898932126345, 0, 0.037277437925548, 0.046325139282165, 0, -0.065799428391419, -0.047366299227838, 0, -0.043115807641491, 0.052940092072017, 0, }; + +static constexpr double lhs[24][24] ={ +{0.38976292287141, 0, 0, -0.17246171497369, 0, 0, -0.13107035041089, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0.43460241579546, 0, 0, -0.086230857486843, 0, 0, -0.26214070082177, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0, 0.38976292287141, 0, 0, -0.086230857486843, 0, 0, -0.13107035041089, 0, 0, 0, 0, 0, -0.17246171497369, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{-0.17246171497369, 0, 0, 0.3717583550199, 0, 0, 0, 0, 0, -0.11306578255937, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, }, +{0, -0.086230857486843, 0, 0, 0.39859328009243, 0, 0, 0, 0, 0, -0.22613156511874, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, }, +{0, 0, -0.086230857486843, 0, 0, 0.3717583550199, 0, 0, 0, 0, 0, -0.11306578255937, 0, 0, 0, 0, 0, -0.17246171497369, 0, 0, 0, 0, 0, 0, }, +{-0.13107035041089, 0, 0, 0, 0, 0, 0.57045386739397, 0, 0, -0.29264239396569, 0, 0, 0, 0, 0, 0, 0, 0, -0.1467411230174, 0, 0, 0, 0, 0, }, +{0, -0.26214070082177, 0, 0, 0, 0, 0, 0.55520302082201, 0, 0, -0.14632119698285, 0, 0, 0, 0, 0, 0, 0, 0, -0.1467411230174, 0, 0, 0, 0, }, +{0, 0, -0.13107035041089, 0, 0, 0, 0, 0, 0.57087379342852, 0, 0, -0.14632119698285, 0, 0, 0, 0, 0, 0, 0, 0, -0.29348224603479, 0, 0, 0, }, +{0, 0, 0, -0.11306578255937, 0, 0, -0.29264239396569, 0, 0, 0.5312301714117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12552199488664, 0, 0, }, +{0, 0, 0, 0, -0.22613156511874, 0, 0, -0.14632119698285, 0, 0, 0.49797475698823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12552199488664, 0, }, +{0, 0, 0, 0, 0, -0.11306578255937, 0, 0, -0.14632119698285, 0, 0, 0.51043096931549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.25104398977328, }, +{-0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.37217828105445, 0, 0, -0.17246171497369, 0, 0, -0.11348570859392, 0, 0, 0, 0, 0, }, +{0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.39943313216153, 0, 0, -0.086230857486843, 0, 0, -0.22697141718784, 0, 0, 0, 0, }, +{0, 0, -0.17246171497369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.37217828105445, 0, 0, -0.086230857486843, 0, 0, -0.11348570859392, 0, 0, 0, }, +{0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, -0.17246171497369, 0, 0, 0.36084580821197, 0, 0, 0, 0, 0, -0.10215323575144, 0, 0, }, +{0, 0, 0, 0, -0.086230857486843, 0, 0, 0, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0.37676818647657, 0, 0, 0, 0, 0, -0.20430647150289, 0, }, +{0, 0, 0, 0, 0, -0.17246171497369, 0, 0, 0, 0, 0, 0, 0, 0, -0.086230857486843, 0, 0, 0.36084580821197, 0, 0, 0, 0, 0, -0.10215323575144, }, +{0, 0, 0, 0, 0, 0, -0.1467411230174, 0, 0, 0, 0, 0, -0.11348570859392, 0, 0, 0, 0, 0, 0.51206418212822, 0, 0, -0.2518373505169, 0, 0, }, +{0, 0, 0, 0, 0, 0, 0, -0.1467411230174, 0, 0, 0, 0, 0, -0.22697141718784, 0, 0, 0, 0, 0, 0.49963121546369, 0, 0, -0.12591867525845, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, -0.29348224603479, 0, 0, 0, 0, 0, -0.11348570859392, 0, 0, 0, 0, 0, 0.53288662988716, 0, 0, -0.12591867525845, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12552199488664, 0, 0, 0, 0, 0, -0.10215323575144, 0, 0, -0.2518373505169, 0, 0, 0.47951258115498, 0, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.12552199488664, 0, 0, 0, 0, 0, -0.20430647150289, 0, 0, -0.12591867525845, 0, 0, 0.45574714164797, 0, }, +{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.25104398977328, 0, 0, 0, 0, 0, -0.10215323575144, 0, 0, -0.12591867525845, 0, 0, 0.47911590078317, }, }; -} // namespace ams_diff +} // namespace ke_ams_diff } // namespace hex8_golds +// clang-format on } // anonymous namespace -TEST_F(AMSKernelHex8Mesh, NGP_ams_diff) +TEST_F(AMSKernelHex8Mesh, ngp_sst_ams_diff) { if (bulk_->parallel_size() > 1) return; fill_mesh_and_init_fields(); + YAML::Node realm_node = YAML::Load(realmSSTAMSSettings); + + realm_node[0]["solution_options"]["turbulence_model"] = "sst_ams"; + // Setup solution options for default advection kernel solnOpts_.meshMotion_ = false; solnOpts_.externalMeshDeformation_ = false; @@ -536,8 +161,9 @@ TEST_F(AMSKernelHex8Mesh, NGP_ams_diff) solnOpts_.upwMap_["velocity"] = 0.0; solnOpts_.initialize_turbulence_constants(); - unit_test_utils::EdgeKernelHelperObjects helperObjs( - bulk_, stk::topology::HEX_8, 3, partVec_[0]); + unit_test_utils::AMSEdgeKernelHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0], + unit_test_utils::get_default_inputs(), realm_node[0]); helperObjs.edgeAlg->add_kernel( *bulk_, solnOpts_); @@ -548,7 +174,127 @@ TEST_F(AMSKernelHex8Mesh, NGP_ams_diff) EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); - namespace gold_values = ::hex8_golds::ams_diff; + namespace gold_values = ::hex8_golds::sst_ams_diff; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, gold_values::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<24>( + helperObjs.linsys->lhs_, gold_values::lhs, 1.0e-12); +} + +TEST_F(AMSKernelHex8Mesh, ngp_sstlr_ams_diff) +{ + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + YAML::Node realm_node = YAML::Load(realmSSTAMSSettings); + + realm_node[0]["solution_options"]["turbulence_model"] = "sstlr_ams"; + + // Setup solution options for default advection kernel + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.includeDivU_ = false; + solnOpts_.alphaMap_["velocity"] = 0.0; + solnOpts_.alphaUpwMap_["velocity"] = 0.0; + solnOpts_.upwMap_["velocity"] = 0.0; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::AMSEdgeKernelHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0], + unit_test_utils::get_default_inputs(), realm_node[0]); + + helperObjs.edgeAlg->add_kernel( + *bulk_, solnOpts_); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 24u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); + + namespace gold_values = ::hex8_golds::sst_ams_diff; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, gold_values::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<24>( + helperObjs.linsys->lhs_, gold_values::lhs, 1.0e-12); +} + +TEST_F(AMSKernelHex8Mesh, ngp_ko_ams_diff) +{ + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + YAML::Node realm_node = YAML::Load(realmSSTAMSSettings); + + realm_node[0]["solution_options"]["turbulence_model"] = "ko_ams"; + + // Setup solution options for default advection kernel + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.includeDivU_ = false; + solnOpts_.alphaMap_["velocity"] = 0.0; + solnOpts_.alphaUpwMap_["velocity"] = 0.0; + solnOpts_.upwMap_["velocity"] = 0.0; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::AMSEdgeKernelHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0], + unit_test_utils::get_default_inputs(), realm_node[0]); + + helperObjs.edgeAlg->add_kernel( + *bulk_, solnOpts_); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 24u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); + + namespace gold_values = ::hex8_golds::sst_ams_diff; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, gold_values::rhs, 1.0e-12); + unit_test_kernel_utils::expect_all_near<24>( + helperObjs.linsys->lhs_, gold_values::lhs, 1.0e-12); +} + +TEST_F(AMSKernelHex8Mesh, ngp_ke_ams_diff) +{ + if (bulk_->parallel_size() > 1) + return; + + fill_mesh_and_init_fields(); + + YAML::Node realm_node = YAML::Load(realmSSTAMSSettings); + + realm_node[0]["solution_options"]["turbulence_model"] = "ke_ams"; + + // Setup solution options for default advection kernel + solnOpts_.meshMotion_ = false; + solnOpts_.externalMeshDeformation_ = false; + solnOpts_.includeDivU_ = false; + solnOpts_.alphaMap_["velocity"] = 0.0; + solnOpts_.alphaUpwMap_["velocity"] = 0.0; + solnOpts_.upwMap_["velocity"] = 0.0; + solnOpts_.initialize_turbulence_constants(); + + unit_test_utils::AMSEdgeKernelHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0], + unit_test_utils::get_default_inputs(), realm_node[0]); + + helperObjs.edgeAlg->add_kernel( + *bulk_, solnOpts_); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 24u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); + + namespace gold_values = ::hex8_golds::ke_ams_diff; unit_test_kernel_utils::expect_all_near( helperObjs.linsys->rhs_, gold_values::rhs, 1.0e-12); unit_test_kernel_utils::expect_all_near<24>( diff --git a/unit_tests/kernels/UnitTestKernelUtils.h b/unit_tests/kernels/UnitTestKernelUtils.h index 455570ecc..260dac887 100644 --- a/unit_tests/kernels/UnitTestKernelUtils.h +++ b/unit_tests/kernels/UnitTestKernelUtils.h @@ -1108,6 +1108,8 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh stk::topology::NODE_RANK, "turbulent_ke")), sdr_(&meta_->declare_field( stk::topology::NODE_RANK, "specific_dissipation_rate")), + tdr_(&meta_->declare_field( + stk::topology::NODE_RANK, "total_dissipation_rate")), visc_(&meta_->declare_field( stk::topology::NODE_RANK, "viscosity")), tvisc_(&meta_->declare_field( @@ -1124,6 +1126,8 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh stk::topology::NODE_RANK, "rans_time_scale")), minDist_(&meta_->declare_field( stk::topology::NODE_RANK, "minimum_distance_to_wall")), + dplus_(&meta_->declare_field( + stk::topology::NODE_RANK, "dplus_wall_function")), Mij_(&meta_->declare_field( stk::topology::NODE_RANK, "metric_tensor")), fOneBlend_(&meta_->declare_field( @@ -1141,6 +1145,7 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh { stk::mesh::put_field_on_mesh(*tke_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh(*sdr_, meta_->universal_part(), 1, nullptr); + stk::mesh::put_field_on_mesh(*tdr_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh(*visc_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh(*tvisc_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh(*alpha_, meta_->universal_part(), 1, nullptr); @@ -1154,6 +1159,7 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh *avgTime_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh( *minDist_, meta_->universal_part(), 1, nullptr); + stk::mesh::put_field_on_mesh(*dplus_, meta_->universal_part(), 1, nullptr); stk::mesh::put_field_on_mesh( *Mij_, meta_->universal_part(), spatialDim_ * spatialDim_, nullptr); stk::mesh::put_field_on_mesh( @@ -1185,9 +1191,11 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh stk::mesh::field_fill(0.6, *avgProd_); stk::mesh::field_fill(1.0, *avgTime_); stk::mesh::field_fill(0.7, *minDist_); + unit_test_kernel_utils::dplus_test_function(*bulk_, *coordinates_, *dplus_); stk::mesh::field_fill(0.2, *Mij_); unit_test_kernel_utils::tke_test_function(*bulk_, *coordinates_, *tke_); unit_test_kernel_utils::sdr_test_function(*bulk_, *coordinates_, *sdr_); + unit_test_kernel_utils::tdr_test_function(*bulk_, *coordinates_, *tdr_); unit_test_kernel_utils::alpha_test_function(*bulk_, *coordinates_, *alpha_); unit_test_kernel_utils::sst_f_one_blending_test_function( *bulk_, *coordinates_, *fOneBlend_); @@ -1201,6 +1209,7 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh ScalarFieldType* tke_{nullptr}; ScalarFieldType* sdr_{nullptr}; + ScalarFieldType* tdr_{nullptr}; ScalarFieldType* visc_{nullptr}; ScalarFieldType* tvisc_{nullptr}; ScalarFieldType* alpha_{nullptr}; @@ -1209,6 +1218,7 @@ class AMSKernelHex8Mesh : public LowMachKernelHex8Mesh ScalarFieldType* avgProd_{nullptr}; ScalarFieldType* avgTime_{nullptr}; ScalarFieldType* minDist_{nullptr}; + ScalarFieldType* dplus_{nullptr}; GenericFieldType* Mij_{nullptr}; ScalarFieldType* fOneBlend_{nullptr}; TensorFieldType* dudx_{nullptr}; diff --git a/unit_tests/node_kernels/UnitTestAMSNodeKernel.C b/unit_tests/node_kernels/UnitTestAMSNodeKernel.C index 2634ce329..695311c69 100644 --- a/unit_tests/node_kernels/UnitTestAMSNodeKernel.C +++ b/unit_tests/node_kernels/UnitTestAMSNodeKernel.C @@ -12,12 +12,20 @@ #include "UnitTestHelperObjects.h" #include "node_kernels/SDRSSTAMSNodeKernel.h" +#include "node_kernels/SDRSSTLRAMSNodeKernel.h" +#include "node_kernels/SDRKOAMSNodeKernel.h" +#include "node_kernels/TDRKEAMSNodeKernel.h" #include "node_kernels/TKESSTAMSNodeKernel.h" +#include "node_kernels/TKESSTLRAMSNodeKernel.h" +#include "node_kernels/TKEKEAMSNodeKernel.h" +#include "node_kernels/TKEKOAMSNodeKernel.h" #include "node_kernels/MomentumSSTAMSForcingNodeKernel.h" +#include "node_kernels/MomentumKEAMSForcingNodeKernel.h" +#include "node_kernels/MomentumKOAMSForcingNodeKernel.h" namespace { namespace hex8_golds { -namespace tke_ams { +namespace tke_sstams { static constexpr double rhs[8] = { 0.03, 0.03, 0.011797117626563686, 0.01930061419167952, 0.03, 0.03, 0.0010727535418449535, 0.013845363192687317, @@ -105,9 +113,276 @@ static constexpr double lhs[8][8] = { 0.026827992474152702, }, }; -} // namespace tke_ams +} // namespace tke_sstams -namespace sdr_ams { +namespace tke_sstlrams { +static constexpr double rhs[8] = { + 0.03, 0.03, 0.011797117626563686, 0.01930061419167952, + 0.03, 0.03, 0.0010727535418449535, 0.013845363192687317, +}; + +static constexpr double lhs[8][8] = { + { + 0.0225, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.0225, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.0225, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.0225, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.0225, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.0225, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.02986322059335908, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.026827992474152702, + }, +}; +} // namespace tke_sstlrams +namespace tke_keams { +static constexpr double rhs[8] = { + -0.17510204081633, -0.17510204081633, -0.17514331719359, -0.17512630246215, + -0.17510204081633, -0.17510204081633, -0.25693986461058, -0.2232051067223, +}; + +static constexpr double lhs[8][8] = { + { + 5.1020408163265e-05, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 5.1020408163265e-05, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 5.1020408163265e-05, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 5.1020408163265e-05, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 5.1020408163265e-05, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 5.1020408163265e-05, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 5.1020408163265e-05, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 5.1020408163265e-05, + }, +}; +} // namespace tke_keams +namespace tke_koams { +static constexpr double rhs[8] = { + 0.03, 0.03, 0.011797117626563686, 0.01930061419167952, + 0.03, 0.03, 0.0010727535418449535, 0.013845363192687317, +}; + +static constexpr double lhs[8][8] = { + { + 0.0225, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.0225, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.0225, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.0225, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.0225, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.0225, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.02986322059335908, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.026827992474152702, + }, +}; +} // namespace tke_koams +namespace sdr_sstams { static constexpr double rhs[8] = { 0.0686, 0.0686, @@ -201,12 +476,341 @@ static constexpr double lhs[8][8] = { 0.047574531285689135, }, }; -} // namespace sdr_ams +} // namespace sdr_sstams +namespace sdr_sstlrams { +static constexpr double rhs[8] = { + -0.0084, + -0.0084, + -0.017904236132368, + -0.014739023789053, + -0.0084, + -0.00093035080516258, + -0.037544505045343, + -0.018962231920743, +}; -namespace forcing_ams { -static constexpr double rhs[24] = { - 0, - 0, +static constexpr double lhs[8][8] = { + { + 0.0414, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.0414, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.0414, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.0414, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.0414, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.037865654115188, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.054948325891781, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.046886464029246, + }, +}; +} // namespace sdr_sstlrams +namespace tdr_keams { +static constexpr double rhs[8] = { + -0.34878753871849, -0.34876380972278, -0.24834504322869, -0.28177185377029, + -0.34878753871849, -0.34876380972278, -0.53192598629727, -0.45541636695634, +}; + +static constexpr double lhs[8][8] = { + { + 0.45001876935924, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.45000690486139, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.32041554937241, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.36356567137431, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.45001876935924, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.45000690486139, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.48255368682701, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.47077492362076, + }, +}; +} // namespace tdr_keams + +namespace sdr_koams { +static constexpr double rhs[8] = { + 0.0030126084335584, 0.0030126084335584, -0.0082258869425877, + -0.0044833434297577, 0.0030126084335584, 0.0030126084335584, + -0.021583548165759, -0.01036790116732, +}; + +static constexpr double lhs[8][8] = { + { + 0.036, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0.036, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0.036, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0.036, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0.036, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0.036, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0.047781152949375, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.042924787958644, + }, +}; +} // namespace sdr_koams + +namespace forcing_sstams { +static constexpr double rhs[24] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -0.01722586002226411, + 0}; +} // namespace forcing_sstams +namespace forcing_keams { +static constexpr double rhs[24] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -0.01722586002226411, + 0}; +} // namespace forcing_keams +namespace forcing_koams { +static constexpr double rhs[24] = { + 0, + 0, 0, 0, 0, @@ -229,11 +833,11 @@ static constexpr double rhs[24] = { 0, -0.01722586002226411, 0}; -} // namespace forcing_ams +} // namespace forcing_koams } // namespace hex8_golds } // namespace -TEST_F(AMSKernelHex8Mesh, NGP_tke_ams_node) +TEST_F(AMSKernelHex8Mesh, NGP_tke_sstams_node) { // Only execute for 1 processor runs if (bulk_->parallel_size() > 1) @@ -258,14 +862,109 @@ TEST_F(AMSKernelHex8Mesh, NGP_tke_ams_node) EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); - namespace hex8_golds = hex8_golds::tke_ams; + namespace hex8_golds = hex8_golds::tke_sstams; + 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(AMSKernelHex8Mesh, NGP_tke_sstlrams_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_, solnOpts_.get_coordinates_name()); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::tke_sstlrams; + 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(AMSKernelHex8Mesh, NGP_tke_keams_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_, solnOpts_.get_coordinates_name()); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::tke_keams; + 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(AMSKernelHex8Mesh, NGP_tke_koams_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(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::tke_koams; 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(AMSKernelHex8Mesh, NGP_sdr_ams_node) +TEST_F(AMSKernelHex8Mesh, NGP_sdr_sstams_node) { // Only execute for 1 processor runs if (bulk_->parallel_size() > 1) @@ -290,14 +989,195 @@ TEST_F(AMSKernelHex8Mesh, NGP_sdr_ams_node) EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); - namespace hex8_golds = hex8_golds::sdr_ams; + namespace hex8_golds = hex8_golds::sdr_sstams; + 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(AMSKernelHex8Mesh, NGP_sdr_sstlrams_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_, solnOpts_.get_coordinates_name()); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::sdr_sstlrams; + 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(AMSKernelHex8Mesh, NGP_tdr_keams_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_, solnOpts_.get_coordinates_name()); + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::tdr_keams; + 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(AMSKernelHex8Mesh, NGP_sdr_koams_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(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 8u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 8u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 8u); + + namespace hex8_golds = hex8_golds::sdr_koams; 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(AMSKernelHex8Mesh, NGP_ams_forcing) +TEST_F(AMSKernelHex8Mesh, NGP_sstams_forcing) +{ + // 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(); + solnOpts_.eastVector_ = {1.0, 0.0, 0.0}; + solnOpts_.northVector_ = {0.0, 1.0, 0.0}; + + unit_test_utils::NodeHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0]); + + helperObjs.nodeAlg->add_kernel( + *bulk_, solnOpts_); + + sierra::nalu::TimeIntegrator timeIntegrator; + timeIntegrator.currentTime_ = 0.0; + timeIntegrator.timeStepN_ = 0.1; + timeIntegrator.timeStepNm1_ = 0.1; + timeIntegrator.gamma1_ = 1.0; + timeIntegrator.gamma2_ = -1.0; + timeIntegrator.gamma3_ = 0.0; + helperObjs.realm.timeIntegrator_ = &timeIntegrator; + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 24u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); + + namespace hex8_golds = hex8_golds::forcing_sstams; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); + // unit_test_kernel_utils::expect_all_near<24>( + // helperObjs.linsys->lhs_, 0.0, 1.0e-12); +} + +TEST_F(AMSKernelHex8Mesh, NGP_keams_forcing) +{ + // 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(); + solnOpts_.eastVector_ = {1.0, 0.0, 0.0}; + solnOpts_.northVector_ = {0.0, 1.0, 0.0}; + + unit_test_utils::NodeHelperObjects helperObjs( + bulk_, stk::topology::HEX_8, 3, partVec_[0]); + + helperObjs.nodeAlg->add_kernel( + *bulk_, solnOpts_); + + sierra::nalu::TimeIntegrator timeIntegrator; + timeIntegrator.currentTime_ = 0.0; + timeIntegrator.timeStepN_ = 0.1; + timeIntegrator.timeStepNm1_ = 0.1; + timeIntegrator.gamma1_ = 1.0; + timeIntegrator.gamma2_ = -1.0; + timeIntegrator.gamma3_ = 0.0; + helperObjs.realm.timeIntegrator_ = &timeIntegrator; + + helperObjs.execute(); + + EXPECT_EQ(helperObjs.linsys->lhs_.extent(0), 24u); + EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); + EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); + + namespace hex8_golds = hex8_golds::forcing_keams; + unit_test_kernel_utils::expect_all_near( + helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); + // unit_test_kernel_utils::expect_all_near<24>( + // helperObjs.linsys->lhs_, 0.0, 1.0e-12); +} + +TEST_F(AMSKernelHex8Mesh, NGP_koams_forcing) { // Only execute for 1 processor runs if (bulk_->parallel_size() > 1) @@ -333,7 +1213,7 @@ TEST_F(AMSKernelHex8Mesh, NGP_ams_forcing) EXPECT_EQ(helperObjs.linsys->lhs_.extent(1), 24u); EXPECT_EQ(helperObjs.linsys->rhs_.extent(0), 24u); - namespace hex8_golds = hex8_golds::forcing_ams; + namespace hex8_golds = hex8_golds::forcing_koams; unit_test_kernel_utils::expect_all_near( helperObjs.linsys->rhs_, hex8_golds::rhs, 1.0e-12); // unit_test_kernel_utils::expect_all_near<24>(