.. _program_listing_file_explicitLawsOfTheWall_EquilibriumODEExplicitLawOfTheWall_EquilibriumODEExplicitLawOfTheWall.C: Program Listing for File EquilibriumODEExplicitLawOfTheWall.C ============================================================= |exhale_lsh| :ref:`Return to documentation for file ` (``explicitLawsOfTheWall/EquilibriumODEExplicitLawOfTheWall/EquilibriumODEExplicitLawOfTheWall.C``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /*---------------------------------------------------------------------------* \ License This file is part of libWallModelledLES. libWallModelledLES is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libWallModelledLES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with libWallModelledLES. If not, see . \*---------------------------------------------------------------------------*/ #include "EquilibriumODEExplicitLawOfTheWall.H" #include "dictionary.H" #include "error.H" #include "addToRunTimeSelectionTable.H" #include "scalarListIOList.H" #include "SingleCellSampler.H" #include #include "helpers.H" #include "AdaptiveIntegrator.hpp" #include typedef std::function IntegrandFunc; Foam::scalar get_B(const Foam::scalar kappa, const Foam::scalar Aplus); #if !defined(DOXYGEN_SHOULD_SKIP_THIS) namespace Foam { defineTypeNameAndDebug(EquilibriumODEExplicitLawOfTheWall, 0); addToRunTimeSelectionTable(ExplicitLawOfTheWall, EquilibriumODEExplicitLawOfTheWall, Dictionary); addToRunTimeSelectionTable(ExplicitLawOfTheWall, EquilibriumODEExplicitLawOfTheWall, TypeAndDictionary); } #endif // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::EquilibriumODEExplicitLawOfTheWall::EquilibriumODEExplicitLawOfTheWall ( const scalar kappa, const scalar Aplus ) : ExplicitLawOfTheWall(), kappa_(kappa), Aplus_(Aplus), B_(get_B(kappa_, Aplus_)), approximant_("auto"), p_(0), s_(0), nGaussians_(0), mu_{0, 0, 0}, sigma_{0, 0, 0}, xi_{0, 0, 0} { constDict_.add("kappa", kappa); constDict_.add("Aplus", Aplus); setApproximantCoeffs(approximant_); constDict_.add("approximant", approximant_); if (debug) { printCoeffs(); } } Foam::EquilibriumODEExplicitLawOfTheWall::EquilibriumODEExplicitLawOfTheWall ( const dictionary & dict ) : ExplicitLawOfTheWall(dict), kappa_(constDict_.lookupOrAddDefault("kappa", 0.41)), Aplus_(constDict_.lookupOrAddDefault("Aplus", 17)), B_(get_B(kappa_, Aplus_)), approximant_(constDict_.lookupOrAddDefault("approximant", "auto")), p_(0), s_(0), nGaussians_(0), mu_{0, 0, 0}, sigma_{0, 0, 0}, xi_{0, 0, 0} { setApproximantCoeffs(approximant_); constDict_.set("approximant", approximant_); if (debug) { printCoeffs(); } } Foam::EquilibriumODEExplicitLawOfTheWall::EquilibriumODEExplicitLawOfTheWall ( const word & lawName, const dictionary & dict ) : EquilibriumODEExplicitLawOfTheWall(dict) { } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // bool Foam::EquilibriumODEExplicitLawOfTheWall::approxEqual ( const scalar a, const scalar b ) { return mag(a - b) < 1e-6; } void Foam::EquilibriumODEExplicitLawOfTheWall::setApproximantCoeffs ( const word& approximant ) { word selected(approximant); if (selected == "auto") { if (approxEqual(kappa_, 0.387) && approxEqual(Aplus_, 15.2516)) { selected = "highRe"; } else if (approxEqual(kappa_, 0.41) && approxEqual(Aplus_, 17)) { selected = "classical"; } else { selected = "global"; } } if (selected == "highRe") { nGaussians_ = 3; mu_[0] = 2.747578886341323; sigma_[0] = 2.986331718406963; xi_[0] = 0.14158434859130883; mu_[1] = 3.217234942007338; sigma_[1] = 0.5812144329347989; xi_[1] = 0.053147124312226554; mu_[2] = 4.155551202580644; sigma_[2] = 0.945720164071122; xi_[2] = -0.03125681152478188; p_ = 1.1907235645597454; s_ = 218.72498935725267; } else if (selected == "classical") { nGaussians_ = 3; mu_[0] = 2.712195304468856; sigma_[0] = 1.153331759918931; xi_[0] = 0.04253708716912398; mu_[1] = 2.785538268044812; sigma_[1] = 3.1614868745529012; xi_[1] = 0.13731053348456193; mu_[2] = 2.547620704489551; sigma_[2] = 0.6124242434703746; xi_[2] = 0.012277142724028153; p_ = 1.2029211749614945; s_ = 247.0697345675632; } else if (selected == "global") { nGaussians_ = 1; mu_[0] = 3.498902867914008*kappa_ + 0.13030217331542102*Aplus_ - 0.9085784915858164; sigma_[0] = -1.2191000776979632*kappa_ - 0.02844761945101745*Aplus_ + 1.5494923375953826; xi_[0] = -0.39993239380818907*kappa_ - 0.0072855142653190505*Aplus_ + 0.3209799815846869; mu_[1] = 0; sigma_[1] = 0; xi_[1] = 0; mu_[2] = 0; sigma_[2] = 0; xi_[2] = 0; p_ = 0.22127889108172996*kappa_ + 0.0052185898765612845*Aplus_ + 1.0616974939891426; s_ = -130.48555166521916*kappa_ + 7.964453719974989*Aplus_ + 10.6631049793274; } else { FatalErrorInFunction << "Unknown EquilibriumODE explicit approximant " << selected << nl << "Valid options are auto, highRe, classical and global." << abort(FatalError); } approximant_ = selected; } Foam::scalar Foam::EquilibriumODEExplicitLawOfTheWall::CaiSagautUPlus ( const scalar Re ) const { const scalar f = exp(-Re / s_); const scalar E = exp(kappa_ * B_); scalar uPlus = Foam::pow(f, p_) * Foam::sqrt(Re); uPlus += Foam::pow(1 - f, p_) / kappa_ * boost::math::lambert_w0(kappa_*E*Re); return uPlus; } Foam::scalar Foam::EquilibriumODEExplicitLawOfTheWall::deltaUPlus ( const scalar log10Re ) const { scalar delta = 0; for (label i = 0; i < nGaussians_; i++) { delta += Helpers::gaussian(mu_[i], sigma_[i], xi_[i], log10Re); } return delta; } void Foam::EquilibriumODEExplicitLawOfTheWall::printCoeffs() const { Info<< nl << "EquilibriumODEExplicit law of the wall" << nl; Info<< token::BEGIN_BLOCK << incrIndent << nl; Info<< indent << "kappa" << indent << kappa_ << nl; Info<< indent << "Aplus" << indent << Aplus_ << nl; Info<< indent << "approximant" << indent << approximant_ << nl; Info<< token::END_BLOCK << nl << nl; } Foam::scalar Foam::EquilibriumODEExplicitLawOfTheWall::uTau ( const SingleCellSampler & sampler, label index, scalar nu ) const { const scalarListIOList & U = sampler.db().lookupObject("U"); const scalar u = mag(vector(U[index][0], U[index][1], U[index][2])); const scalar y = sampler.h()[index]; const scalar re = u * y / nu; const scalar uPlus = CaiSagautUPlus(re) + deltaUPlus(Foam::log10(re)); return u / uPlus; } Foam::scalar get_B(const Foam::scalar kappa, const Foam::scalar Aplus) { IntegrandFunc nut_func = [kappa, Aplus](const Foam::scalar yPlus) { return kappa * yPlus * Foam::sqr(1 - Foam::exp(-yPlus / Aplus)); }; IntegrandFunc integrand = [nut_func](const Foam::scalar yPlus) { return 1.0 / (1.0 + nut_func(yPlus)); }; Foam::scalar yPlus = 100000; AdaptiveIntegrator quad; Foam::scalar up = quad.integrate(integrand, 0.0, yPlus, 1e-3); return up - 1/kappa * Foam::log(yPlus); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //