From a5d6778281be7b1ae64957a5a035e58e842cb681 Mon Sep 17 00:00:00 2001 From: Henry Weller Date: Tue, 20 Mar 2018 22:26:07 +0000 Subject: [PATCH] atmosphericModels: Added Lopes da Costa porosity and turbulence models Specialized variants of the power law porosity and k epsilon turbulence models developed to simulate atmospheric flow over forested and non-forested complex terrain. Class Foam::powerLawLopesdaCosta Description Variant of the power law porosity model with spatially varying drag coefficient given by: \f[ S = -\rho C_d \Sigma |U|^{(C_1 - 1)} U \f] where \vartable \Sigma | Porosity surface area per unit volume C_d | Model linear coefficient C_1 | Model exponent coefficient \endvartable Reference: \verbatim Costa, J. C. P. L. D. (2007). Atmospheric flow over forested and non-forested complex terrain. \endverbatim Class Foam::RASModels::kEpsilonLopesdaCosta Description Variant of the standard k-epsilon turbulence model with additional source terms to handle the changes in turbulence in porous regions represented by the powerLawLopesdaCosta porosity model. Reference: \verbatim Costa, J. C. P. L. D. (2007). Atmospheric flow over forested and non-forested complex terrain. \endverbatim The default model coefficients are \verbatim kEpsilonLopesdaCostaCoeffs { Cmu 0.09; C1 1.44; C2 1.92; sigmak 1.0; sigmaEps 1.3; } \endverbatim Tutorial case to follow. --- src/Allwmake | 1 + src/atmosphericModels/Make/files | 3 + .../atmosphericTurbulentTransportModels.C | 35 ++ .../atmBoundaryLayer/atmBoundaryLayer.H | 2 +- .../kEpsilonLopesdaCosta.C | 477 ++++++++++++++++++ .../kEpsilonLopesdaCosta.H | 245 +++++++++ .../powerLawLopesdaCosta.C | 419 +++++++++++++++ .../powerLawLopesdaCosta.H | 229 +++++++++ .../powerLawLopesdaCostaTemplates.C | 87 ++++ .../porosityModel/porosityModel.H | 5 +- .../porosityModel/porosityModelI.H | 8 +- .../explicitPorositySource.C | 9 +- .../explicitPorositySource.H | 7 +- .../triSurfaceTools/triSurfaceTools.C | 92 +++- .../triSurfaceTools/triSurfaceTools.H | 13 +- 15 files changed, 1617 insertions(+), 15 deletions(-) create mode 100644 src/atmosphericModels/atmosphericTurbulentTransportModels.C create mode 100644 src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.C create mode 100644 src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.H create mode 100644 src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.C create mode 100644 src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.H create mode 100644 src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCostaTemplates.C diff --git a/src/Allwmake b/src/Allwmake index 4b82b2324..3f7a0f8d6 100755 --- a/src/Allwmake +++ b/src/Allwmake @@ -81,6 +81,7 @@ wmake $targetType rigidBodyDynamics wmake $targetType rigidBodyMeshMotion wmake $targetType waves wmake $targetType semiPermeableBaffle +wmake $targetType atmosphericModels #------------------------------------------------------------------------------ diff --git a/src/atmosphericModels/Make/files b/src/atmosphericModels/Make/files index a5a1c27f2..644149f55 100644 --- a/src/atmosphericModels/Make/files +++ b/src/atmosphericModels/Make/files @@ -4,4 +4,7 @@ derivedFvPatchFields/atmBoundaryLayerInletK/atmBoundaryLayerInletKFvPatchScalarF derivedFvPatchFields/atmBoundaryLayerInletEpsilon/atmBoundaryLayerInletEpsilonFvPatchScalarField.C derivedFvPatchFields/nutkAtmRoughWallFunction/nutkAtmRoughWallFunctionFvPatchScalarField.C +atmosphericTurbulentTransportModels.C +porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.C + LIB = $(FOAM_LIBBIN)/libatmosphericModels diff --git a/src/atmosphericModels/atmosphericTurbulentTransportModels.C b/src/atmosphericModels/atmosphericTurbulentTransportModels.C new file mode 100644 index 000000000..cf31e0c25 --- /dev/null +++ b/src/atmosphericModels/atmosphericTurbulentTransportModels.C @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "turbulentTransportModels.H" + +// -------------------------------------------------------------------------- // +// RAS models +// -------------------------------------------------------------------------- // + +#include "kEpsilonLopesdaCosta.H" +makeRASModel(kEpsilonLopesdaCosta); + +// ************************************************************************* // diff --git a/src/atmosphericModels/derivedFvPatchFields/atmBoundaryLayer/atmBoundaryLayer.H b/src/atmosphericModels/derivedFvPatchFields/atmBoundaryLayer/atmBoundaryLayer.H index 8fddacb22..99d063240 100644 --- a/src/atmosphericModels/derivedFvPatchFields/atmBoundaryLayer/atmBoundaryLayer.H +++ b/src/atmosphericModels/derivedFvPatchFields/atmBoundaryLayer/atmBoundaryLayer.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2014-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2014-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.C b/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.C new file mode 100644 index 000000000..805d0ca16 --- /dev/null +++ b/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.C @@ -0,0 +1,477 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "kEpsilonLopesdaCosta.H" +#include "fvOptions.H" +#include "explicitPorositySource.H" +#include "bound.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace RASModels +{ + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template +void kEpsilonLopesdaCosta::setPorosityCoefficient +( + volScalarField::Internal& C, + const porosityModels::powerLawLopesdaCosta& pm +) +{ + if (pm.dict().found(C.name())) + { + const labelList& cellZoneIDs = pm.cellZoneIDs(); + + const scalar Cpm = readScalar(pm.dict().lookup(C.name())); + + forAll(cellZoneIDs, zonei) + { + const labelList& cells = + this->mesh_.cellZones()[cellZoneIDs[zonei]]; + + forAll(cells, i) + { + const label celli = cells[i]; + C[celli] = Cpm; + } + } + } +} + + +template +void kEpsilonLopesdaCosta::setCdSigma +( + volScalarField::Internal& C, + const porosityModels::powerLawLopesdaCosta& pm +) +{ + if (pm.dict().found(C.name())) + { + const labelList& cellZoneIDs = pm.cellZoneIDs(); + const scalarField& Sigma = pm.Sigma(); + + const scalar Cpm = readScalar(pm.dict().lookup(C.name())); + + forAll(cellZoneIDs, zonei) + { + const labelList& cells = + this->mesh_.cellZones()[cellZoneIDs[zonei]]; + + forAll(cells, i) + { + const label celli = cells[i]; + C[celli] = Cpm*Sigma[celli]; + } + } + } +} + + +template +void kEpsilonLopesdaCosta::setPorosityCoefficients() +{ + fv::options::optionList& fvOptions(fv::options::New(this->mesh_)); + + forAll(fvOptions, i) + { + if (isA(fvOptions[i])) + { + const fv::explicitPorositySource& eps = + refCast(fvOptions[i]); + + if (isA(eps.model())) + { + const porosityModels::powerLawLopesdaCosta& pm = + refCast + ( + eps.model() + ); + + setPorosityCoefficient(Cmu_, pm); + setPorosityCoefficient(C1_, pm); + setPorosityCoefficient(C2_, pm); + setPorosityCoefficient(sigmak_, pm); + setPorosityCoefficient(sigmaEps_, pm); + + setCdSigma(CdSigma_, pm); + setPorosityCoefficient(betap_, pm); + setPorosityCoefficient(betad_, pm); + setPorosityCoefficient(C4_, pm); + setPorosityCoefficient(C5_, pm); + } + } + } +} + + +template +void kEpsilonLopesdaCosta::correctNut() +{ + this->nut_ = Cmu_*sqr(k_)/epsilon_; + this->nut_.correctBoundaryConditions(); + fv::options::New(this->mesh_).correct(this->nut_); + + BasicTurbulenceModel::correctNut(); +} + + +template +tmp kEpsilonLopesdaCosta::kSource +( + const volScalarField::Internal& magU, + const volScalarField::Internal& magU3 +) const +{ + return fvm::Su(CdSigma_*(betap_*magU3 - betad_*magU*k_()), k_); +} + + +template +tmp +kEpsilonLopesdaCosta::epsilonSource +( + const volScalarField::Internal& magU, + const volScalarField::Internal& magU3 +) const +{ + return fvm::Su + ( + CdSigma_ + *(C4_*betap_*epsilon_()/k_()*magU3 - C5_*betad_*magU*epsilon_()), + epsilon_ + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +kEpsilonLopesdaCosta::kEpsilonLopesdaCosta +( + const alphaField& alpha, + const rhoField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const transportModel& transport, + const word& propertiesName, + const word& type +) +: + eddyViscosity> + ( + type, + alpha, + rho, + U, + alphaRhoPhi, + phi, + transport, + propertiesName + ), + + Cmu_ + ( + IOobject + ( + "Cmu", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensioned::lookupOrAddToDict + ( + "Cmu", + this->coeffDict_, + 0.09 + ) + ), + C1_ + ( + IOobject + ( + "C1", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensioned::lookupOrAddToDict + ( + "C1", + this->coeffDict_, + 1.44 + ) + ), + C2_ + ( + IOobject + ( + "C2", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensioned::lookupOrAddToDict + ( + "C2", + this->coeffDict_, + 1.92 + ) + ), + sigmak_ + ( + IOobject + ( + "sigmak", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensioned::lookupOrAddToDict + ( + "sigmak", + this->coeffDict_, + 1.0 + ) + ), + sigmaEps_ + ( + IOobject + ( + "sigmaEps", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensioned::lookupOrAddToDict + ( + "sigmaEps", + this->coeffDict_, + 1.3 + ) + ), + + CdSigma_ + ( + IOobject + ( + "CdSigma", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensionedScalar("CdSigma", dimless/dimLength, 0) + ), + betap_ + ( + IOobject + ( + "betap", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensionedScalar("betap", dimless, 0) + ), + betad_ + ( + IOobject + ( + "betad", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensionedScalar("betad", dimless, 0) + ), + C4_ + ( + IOobject + ( + "C4", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensionedScalar("C4", dimless, 0) + ), + C5_ + ( + IOobject + ( + "C5", + this->runTime_.timeName(), + this->mesh_ + ), + this->mesh_, + dimensionedScalar("C5", dimless, 0) + ), + + k_ + ( + IOobject + ( + IOobject::groupName("k", alphaRhoPhi.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + this->mesh_ + ), + epsilon_ + ( + IOobject + ( + IOobject::groupName("epsilon", alphaRhoPhi.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + this->mesh_ + ) +{ + bound(k_, this->kMin_); + bound(epsilon_, this->epsilonMin_); + + if (type == typeName) + { + this->printCoeffs(type); + } + + setPorosityCoefficients(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +bool kEpsilonLopesdaCosta::read() +{ + if (eddyViscosity>::read()) + { + return true; + } + else + { + return false; + } +} + + +template +void kEpsilonLopesdaCosta::correct() +{ + if (!this->turbulence_) + { + return; + } + + // Local references + const alphaField& alpha = this->alpha_; + const rhoField& rho = this->rho_; + const surfaceScalarField& alphaRhoPhi = this->alphaRhoPhi_; + const volVectorField& U = this->U_; + volScalarField& nut = this->nut_; + fv::options& fvOptions(fv::options::New(this->mesh_)); + + eddyViscosity>::correct(); + + volScalarField::Internal divU + ( + fvc::div(fvc::absolute(this->phi(), U))().v() + ); + + tmp tgradU = fvc::grad(U); + volScalarField::Internal G + ( + this->GName(), + nut.v()*(dev(twoSymm(tgradU().v())) && tgradU().v()) + ); + tgradU.clear(); + + // Update epsilon and G at the wall + epsilon_.boundaryFieldRef().updateCoeffs(); + + volScalarField::Internal magU(mag(U)); + volScalarField::Internal magU3(pow3(magU)); + + // Dissipation equation + tmp epsEqn + ( + fvm::ddt(alpha, rho, epsilon_) + + fvm::div(alphaRhoPhi, epsilon_) + - fvm::laplacian(alpha*rho*DepsilonEff(), epsilon_) + == + C1_*alpha()*rho()*G*epsilon_()/k_() + - fvm::SuSp(((2.0/3.0)*C1_)*alpha()*rho()*divU, epsilon_) + - fvm::Sp(C2_*alpha()*rho()*epsilon_()/k_(), epsilon_) + + epsilonSource(magU, magU3) + + fvOptions(alpha, rho, epsilon_) + ); + + epsEqn.ref().relax(); + fvOptions.constrain(epsEqn.ref()); + epsEqn.ref().boundaryManipulate(epsilon_.boundaryFieldRef()); + solve(epsEqn); + fvOptions.correct(epsilon_); + bound(epsilon_, this->epsilonMin_); + + // Turbulent kinetic energy equation + tmp kEqn + ( + fvm::ddt(alpha, rho, k_) + + fvm::div(alphaRhoPhi, k_) + - fvm::laplacian(alpha*rho*DkEff(), k_) + == + alpha()*rho()*G + - fvm::SuSp((2.0/3.0)*alpha()*rho()*divU, k_) + - fvm::Sp(alpha()*rho()*epsilon_()/k_(), k_) + + kSource(magU, magU3) + + fvOptions(alpha, rho, k_) + ); + + kEqn.ref().relax(); + fvOptions.constrain(kEqn.ref()); + solve(kEqn); + fvOptions.correct(k_); + bound(k_, this->kMin_); + + correctNut(); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace RASModels +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.H b/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.H new file mode 100644 index 000000000..b72992d9a --- /dev/null +++ b/src/atmosphericModels/kEpsilonLopesdaCosta/kEpsilonLopesdaCosta.H @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::RASModels::kEpsilonLopesdaCosta + +Group + grpRASTurbulence + +Description + Variant of the standard k-epsilon turbulence model with additional source + terms to handle the changes in turbulence in porous regions represented by + the powerLawLopesdaCosta porosity model. + + Reference: + \verbatim + Costa, J. C. P. L. D. (2007). + Atmospheric flow over forested and non-forested complex terrain. + \endverbatim + + The default model coefficients are + \verbatim + kEpsilonLopesdaCostaCoeffs + { + Cmu 0.09; + C1 1.44; + C2 1.92; + sigmak 1.0; + sigmaEps 1.3; + } + \endverbatim + +See also + Foam::RASModels::kEpsilon + Foam::porosityModels::powerLawLopesdaCosta + +SourceFiles + kEpsilonLopesdaCosta.C + +\*---------------------------------------------------------------------------*/ + +#ifndef kEpsilonLopesdaCosta_H +#define kEpsilonLopesdaCosta_H + +#include "RASModel.H" +#include "eddyViscosity.H" +#include "powerLawLopesdaCosta.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace RASModels +{ + +/*---------------------------------------------------------------------------*\ + Class kEpsilonLopesdaCosta Declaration +\*---------------------------------------------------------------------------*/ + +template +class kEpsilonLopesdaCosta +: + public eddyViscosity> +{ + // Private Member Functions + + // Disallow default bitwise copy construct and assignment + kEpsilonLopesdaCosta(const kEpsilonLopesdaCosta&); + void operator=(const kEpsilonLopesdaCosta&); + + +protected: + + // Protected data + + // Standard model coefficients + + volScalarField Cmu_; + volScalarField::Internal C1_; + volScalarField::Internal C2_; + volScalarField sigmak_; + volScalarField sigmaEps_; + + // Lopes da Costa porosity coefficients + + volScalarField::Internal CdSigma_; + volScalarField::Internal betap_; + volScalarField::Internal betad_; + volScalarField::Internal C4_; + volScalarField::Internal C5_; + + + // Fields + + volScalarField k_; + volScalarField epsilon_; + + + // Protected Member Functions + + void setPorosityCoefficient + ( + volScalarField::Internal& C, + const porosityModels::powerLawLopesdaCosta& pm + ); + + void setCdSigma + ( + volScalarField::Internal& C, + const porosityModels::powerLawLopesdaCosta& pm + ); + + void setPorosityCoefficients(); + + virtual void correctNut(); + + virtual tmp kSource + ( + const volScalarField::Internal& magU, + const volScalarField::Internal& magU3 + ) const; + + virtual tmp epsilonSource + ( + const volScalarField::Internal& magU, + const volScalarField::Internal& magU3 + ) const; + + +public: + + typedef typename BasicTurbulenceModel::alphaField alphaField; + typedef typename BasicTurbulenceModel::rhoField rhoField; + typedef typename BasicTurbulenceModel::transportModel transportModel; + + + //- Runtime type information + TypeName("kEpsilonLopesdaCosta"); + + + // Constructors + + //- Construct from components + kEpsilonLopesdaCosta + ( + const alphaField& alpha, + const rhoField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const transportModel& transport, + const word& propertiesName = turbulenceModel::propertiesName, + const word& type = typeName + ); + + + //- Destructor + virtual ~kEpsilonLopesdaCosta() + {} + + + // Member Functions + + //- Re-read model coefficients if they have changed + virtual bool read(); + + //- Return the effective diffusivity for k + tmp DkEff() const + { + return tmp + ( + new volScalarField + ( + "DkEff", + (this->nut_/sigmak_ + this->nu()) + ) + ); + } + + //- Return the effective diffusivity for epsilon + tmp DepsilonEff() const + { + return tmp + ( + new volScalarField + ( + "DepsilonEff", + (this->nut_/sigmaEps_ + this->nu()) + ) + ); + } + + //- Return the turbulence kinetic energy + virtual tmp k() const + { + return k_; + } + + //- Return the turbulence kinetic energy dissipation rate + virtual tmp epsilon() const + { + return epsilon_; + } + + //- Solve the turbulence equations and correct the turbulence viscosity + virtual void correct(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace RASModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "kEpsilonLopesdaCosta.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.C b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.C new file mode 100644 index 000000000..e5d13f50e --- /dev/null +++ b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.C @@ -0,0 +1,419 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "addToRunTimeSelectionTable.H" +#include "powerLawLopesdaCosta.H" +#include "geometricOneField.H" +#include "fvMatrices.H" +#include "triSurfaceMesh.H" +#include "triSurfaceTools.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + namespace porosityModels + { + defineTypeNameAndDebug(powerLawLopesdaCosta, 0); + addToRunTimeSelectionTable(porosityModel, powerLawLopesdaCosta, mesh); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::porosityModels::powerLawLopesdaCostaZone::powerLawLopesdaCostaZone +( + const word& name, + const word& modelType, + const fvMesh& mesh, + const dictionary& dict +) +: + zoneName_(name + ":porousZone") +{ + dictionary coeffs(dict.optionalSubDict(modelType + "Coeffs")); + + // Vertical direction within porous region + vector zDir(coeffs.lookup("zDir")); + + // Span of the search for the cells in the porous region + scalar searchSpan(readScalar(coeffs.lookup("searchSpan"))); + + // Top surface file name defining the extent of the porous region + word topSurfaceFileName(coeffs.lookup("topSurface")); + + // List of the ground patches defining the lower surface + // of the porous region + List groundPatches(coeffs.lookup("groundPatches")); + + // Functional form of the porosity surface area per unit volume as a + // function of the normalized vertical position + autoPtr> SigmaFunc + ( + Function1::New("Sigma", dict) + ); + + // Searchable triSurface for the top of the porous region + triSurfaceMesh searchSurf + ( + IOobject + ( + topSurfaceFileName, + mesh.time().constant(), + "triSurface", + mesh.time() + ) + ); + + // Limit the porous cell search to those within the lateral and vertical + // extent of the top surface + + boundBox surfBounds(searchSurf.points()); + boundBox searchBounds + ( + surfBounds.min() - searchSpan*zDir, surfBounds.max() + ); + + const pointField& C = mesh.cellCentres(); + + // List of cells within the porous region + labelList porousCells(C.size()); + label porousCelli = 0; + + forAll(C, celli) + { + if (searchBounds.contains(C[celli])) + { + porousCells[porousCelli++] = celli; + } + } + + porousCells.setSize(porousCelli); + + pointField start(porousCelli); + pointField end(porousCelli); + + forAll(porousCells, porousCelli) + { + start[porousCelli] = C[porousCells[porousCelli]]; + end[porousCelli] = start[porousCelli] + searchSpan*zDir; + } + + // Field of distance between the cell centre and the corresponding point + // on the porous region top surface + scalarField zTop(porousCelli); + + // Search the porous cells for those with a corresponding point on the + // porous region top surface + List hitInfo; + searchSurf.findLine(start, end, hitInfo); + + porousCelli = 0; + + forAll(porousCells, celli) + { + const pointIndexHit& hit = hitInfo[celli]; + + if (hit.hit()) + { + porousCells[porousCelli] = porousCells[celli]; + + zTop[porousCelli] = + (hit.hitPoint() - C[porousCells[porousCelli]]) & zDir; + + porousCelli++; + } + } + + // Resize the porous cells list and height field + porousCells.setSize(porousCelli); + zTop.setSize(porousCelli); + + // Create a triSurface for the ground patch(s) + triSurface groundSurface + ( + triSurfaceTools::triangulate + ( + mesh.boundaryMesh(), + mesh.boundaryMesh().patchSet(groundPatches), + searchBounds + ) + ); + + // Combine the ground triSurfaces across all processors + if (Pstream::parRun()) + { + List> groundSurfaceProcTris(Pstream::nProcs()); + List groundSurfaceProcPoints(Pstream::nProcs()); + + groundSurfaceProcTris[Pstream::myProcNo()] = groundSurface; + groundSurfaceProcPoints[Pstream::myProcNo()] = groundSurface.points(); + + Pstream::gatherList(groundSurfaceProcTris); + Pstream::scatterList(groundSurfaceProcTris); + Pstream::gatherList(groundSurfaceProcPoints); + Pstream::scatterList(groundSurfaceProcPoints); + + label nTris = 0; + forAll(groundSurfaceProcTris, i) + { + nTris += groundSurfaceProcTris[i].size(); + } + + List groundSurfaceTris(nTris); + label trii = 0; + label offset = 0; + forAll(groundSurfaceProcTris, i) + { + forAll(groundSurfaceProcTris[i], j) + { + groundSurfaceTris[trii] = groundSurfaceProcTris[i][j]; + groundSurfaceTris[trii][0] += offset; + groundSurfaceTris[trii][1] += offset; + groundSurfaceTris[trii][2] += offset; + trii++; + } + offset += groundSurfaceProcPoints[i].size(); + } + + label nPoints = 0; + forAll(groundSurfaceProcPoints, i) + { + nPoints += groundSurfaceProcPoints[i].size(); + } + + pointField groundSurfacePoints(nPoints); + + label pointi = 0; + forAll(groundSurfaceProcPoints, i) + { + forAll(groundSurfaceProcPoints[i], j) + { + groundSurfacePoints[pointi++] = groundSurfaceProcPoints[i][j]; + } + } + + groundSurface = triSurface(groundSurfaceTris, groundSurfacePoints); + } + + // Create a searchable triSurface for the ground + triSurfaceSearch groundSearch(groundSurface); + + // Search the porous cells for the corresponding point on the ground + + start.setSize(porousCelli); + end.setSize(porousCelli); + + forAll(porousCells, porousCelli) + { + start[porousCelli] = C[porousCells[porousCelli]]; + end[porousCelli] = start[porousCelli] - searchSpan*zDir; + } + + groundSearch.findLine(start, end, hitInfo); + + scalarField zBottom(porousCelli); + + forAll(porousCells, porousCelli) + { + const pointIndexHit& hit = hitInfo[porousCelli]; + + if (hit.hit()) + { + zBottom[porousCelli] = + (C[porousCells[porousCelli]] - hit.hitPoint()) & zDir; + } + } + + // Create the normalized height field + scalarField zNorm(zBottom/(zBottom + zTop)); + + // Create the porosity surface area per unit volume zone field + Sigma_ = SigmaFunc->value(zNorm); + + // Create the porous region cellZone and add to the mesh cellZones + + cellZoneMesh& cellZones = const_cast(mesh.cellZones()); + + label zoneID = cellZones.findZoneID(zoneName_); + + if (zoneID == -1) + { + zoneID = cellZones.size(); + cellZones.setSize(zoneID + 1); + + cellZones.set + ( + zoneID, + new cellZone + ( + zoneName_, + porousCells, + zoneID, + cellZones + ) + ); + } + else + { + FatalErrorInFunction + << "Unable to create porous cellZone " << zoneName_ + << ": zone already exists" + << abort(FatalError); + } +} + + +Foam::porosityModels::powerLawLopesdaCosta::powerLawLopesdaCosta +( + const word& name, + const word& modelType, + const fvMesh& mesh, + const dictionary& dict, + const word& dummyCellZoneName +) +: + powerLawLopesdaCostaZone(name, modelType, mesh, dict), + porosityModel + ( + name, + modelType, + mesh, + dict, + powerLawLopesdaCostaZone::zoneName_ + ), + Cd_(readScalar(coeffs_.lookup("Cd"))), + C1_(readScalar(coeffs_.lookup("C1"))), + rhoName_(coeffs_.lookupOrDefault("rho", "rho")) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::porosityModels::powerLawLopesdaCosta::~powerLawLopesdaCosta() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::scalarField& +Foam::porosityModels::powerLawLopesdaCostaZone::Sigma() const +{ + return Sigma_; +} + + +void Foam::porosityModels::powerLawLopesdaCosta::calcTransformModelData() +{} + + +void Foam::porosityModels::powerLawLopesdaCosta::calcForce +( + const volVectorField& U, + const volScalarField& rho, + const volScalarField& mu, + vectorField& force +) const +{ + scalarField Udiag(U.size(), 0.0); + const scalarField& V = mesh_.V(); + + apply(Udiag, V, rho, U); + + force = Udiag*U; +} + + +void Foam::porosityModels::powerLawLopesdaCosta::correct +( + fvVectorMatrix& UEqn +) const +{ + const vectorField& U = UEqn.psi(); + const scalarField& V = mesh_.V(); + scalarField& Udiag = UEqn.diag(); + + if (UEqn.dimensions() == dimForce) + { + const volScalarField& rho = + mesh_.lookupObject(rhoName_); + + apply(Udiag, V, rho, U); + } + else + { + apply(Udiag, V, geometricOneField(), U); + } +} + + +void Foam::porosityModels::powerLawLopesdaCosta::correct +( + fvVectorMatrix& UEqn, + const volScalarField& rho, + const volScalarField& mu +) const +{ + const vectorField& U = UEqn.psi(); + const scalarField& V = mesh_.V(); + scalarField& Udiag = UEqn.diag(); + + apply(Udiag, V, rho, U); +} + + +void Foam::porosityModels::powerLawLopesdaCosta::correct +( + const fvVectorMatrix& UEqn, + volTensorField& AU +) const +{ + const vectorField& U = UEqn.psi(); + + if (UEqn.dimensions() == dimForce) + { + const volScalarField& rho = + mesh_.lookupObject(rhoName_); + + apply(AU, rho, U); + } + else + { + apply(AU, geometricOneField(), U); + } +} + + +bool Foam::porosityModels::powerLawLopesdaCosta::writeData(Ostream& os) const +{ + os << indent << name_ << endl; + dict_.write(os); + + return true; +} + + +// ************************************************************************* // diff --git a/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.H b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.H new file mode 100644 index 000000000..f19677c80 --- /dev/null +++ b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCosta.H @@ -0,0 +1,229 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::powerLawLopesdaCosta + +Description + Variant of the power law porosity model with spatially varying + drag coefficient + + given by: + + \f[ + S = -\rho C_d \Sigma |U|^{(C_1 - 1)} U + \f] + + where + \vartable + \Sigma | Porosity surface area per unit volume + C_d | Model linear coefficient + C_1 | Model exponent coefficient + \endvartable + + Reference: + \verbatim + Costa, J. C. P. L. D. (2007). + Atmospheric flow over forested and non-forested complex terrain. + \endverbatim + +See also + Foam::RASModels::kEpsilonLopesdaCosta + +SourceFiles + powerLawLopesdaCosta.C + powerLawLopesdaCostaTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef powerLawLopesdaCosta_H +#define powerLawLopesdaCosta_H + +#include "porosityModel.H" +#include "Function1.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace porosityModels +{ + +/*---------------------------------------------------------------------------*\ + Class powerLawLopesdaCostaZone Declaration +\*---------------------------------------------------------------------------*/ + +class powerLawLopesdaCostaZone +{ +protected: + + // Protected data + + //- Automatically generated zone name for this porous zone + const word zoneName_; + + //- Porosity surface area per unit volume zone field + scalarField Sigma_; + + +public: + + //- Constructor + powerLawLopesdaCostaZone + ( + const word& name, + const word& modelType, + const fvMesh& mesh, + const dictionary& dict + ); + + // Member Functions + + //- Return the porosity surface area per unit volume zone field + const scalarField& Sigma() const; +}; + + +/*---------------------------------------------------------------------------*\ + Class powerLawLopesdaCosta Declaration +\*---------------------------------------------------------------------------*/ + +class powerLawLopesdaCosta +: + public powerLawLopesdaCostaZone, + public porosityModel +{ + // Private data + + //- Cd coefficient + scalar Cd_; + + //- C1 coefficient + scalar C1_; + + //- Name of density field + word rhoName_; + + + // Private Member Functions + + //- Apply resistance + template + void apply + ( + scalarField& Udiag, + const scalarField& V, + const RhoFieldType& rho, + const vectorField& U + ) const; + + //- Apply resistance + template + void apply + ( + tensorField& AU, + const RhoFieldType& rho, + const vectorField& U + ) const; + + //- Disallow default bitwise copy construct + powerLawLopesdaCosta(const powerLawLopesdaCosta&); + + //- Disallow default bitwise assignment + void operator=(const powerLawLopesdaCosta&); + + +public: + + //- Runtime type information + TypeName("powerLawLopesdaCosta"); + + //- Constructor + powerLawLopesdaCosta + ( + const word& name, + const word& modelType, + const fvMesh& mesh, + const dictionary& dict, + const word& cellZoneName + ); + + //- Destructor + virtual ~powerLawLopesdaCosta(); + + + // Member Functions + + //- Transform the model data wrt mesh changes + virtual void calcTransformModelData(); + + //- Calculate the porosity force + virtual void calcForce + ( + const volVectorField& U, + const volScalarField& rho, + const volScalarField& mu, + vectorField& force + ) const; + + //- Add resistance + virtual void correct(fvVectorMatrix& UEqn) const; + + //- Add resistance + virtual void correct + ( + fvVectorMatrix& UEqn, + const volScalarField& rho, + const volScalarField& mu + ) const; + + //- Add resistance + virtual void correct + ( + const fvVectorMatrix& UEqn, + volTensorField& AU + ) const; + + + // I-O + + //- Write + bool writeData(Ostream& os) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace porosityModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "powerLawLopesdaCostaTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCostaTemplates.C b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCostaTemplates.C new file mode 100644 index 000000000..be9142d19 --- /dev/null +++ b/src/atmosphericModels/porosityModels/powerLawLopesdaCosta/powerLawLopesdaCostaTemplates.C @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "volFields.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template +void Foam::porosityModels::powerLawLopesdaCosta::apply +( + scalarField& Udiag, + const scalarField& V, + const RhoFieldType& rho, + const vectorField& U +) const +{ + const scalar C1m1b2 = (C1_ - 1.0)/2.0; + + forAll(cellZoneIDs_, zonei) + { + const labelList& cells = mesh_.cellZones()[cellZoneIDs_[zonei]]; + + forAll(cells, i) + { + const label celli = cells[i]; + + Udiag[celli] += + V[celli]*rho[celli] + *Cd_*Sigma_[i]*pow(magSqr(U[celli]), C1m1b2); + } + } +} + + +template +void Foam::porosityModels::powerLawLopesdaCosta::apply +( + tensorField& AU, + const RhoFieldType& rho, + const vectorField& U +) const +{ + const scalar C1m1b2 = (C1_ - 1.0)/2.0; + + forAll(cellZoneIDs_, zonei) + { + const labelList& cells = mesh_.cellZones()[cellZoneIDs_[zonei]]; + + forAll(cells, i) + { + const label celli = cells[i]; + + AU[celli] = + AU[celli] + + I + *( + 0.5*rho[celli]*Cd_*Sigma_[i] + *pow(magSqr(U[celli]), C1m1b2) + ); + } + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModel.H b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModel.H index c3f5b838d..9fe3ce15d 100644 --- a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModel.H +++ b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModel.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2012-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -223,6 +223,9 @@ public: //- Return const access to the cell zone IDs inline const labelList& cellZoneIDs() const; + //- Return dictionary used for model construction + const dictionary& dict() const; + //- Transform the model data wrt mesh changes virtual void transformModelData(); diff --git a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelI.H b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelI.H index 63f28091b..ecf384a27 100644 --- a/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelI.H +++ b/src/finiteVolume/cfdTools/general/porosityModel/porosityModel/porosityModelI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2013 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2012-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -35,6 +35,12 @@ inline bool Foam::porosityModel::active() const } +inline const Foam::dictionary& Foam::porosityModel::dict() const +{ + return dict_; +} + + inline const Foam::labelList& Foam::porosityModel::cellZoneIDs() const { return cellZoneIDs_; diff --git a/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.C b/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.C index 8b8c37762..a90b1903b 100644 --- a/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.C +++ b/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2012-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -61,13 +61,6 @@ Foam::fv::explicitPorositySource::explicitPorositySource { read(dict); - if (selectionMode_ != smCellZone) - { - FatalErrorInFunction - << "selection mode is " << selectionModeTypeNames_[selectionMode_] - << exit(FatalError); - } - porosityPtr_.reset ( porosityModel::New diff --git a/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.H b/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.H index 6bbb32b35..1c5b43980 100644 --- a/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.H +++ b/src/fvOptions/sources/derived/explicitPorositySource/explicitPorositySource.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2012-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -131,6 +131,11 @@ public: // Member Functions + const porosityModel& model() const + { + return porosityPtr_(); + } + // Add explicit and implicit contributions //- Add implicit contribution to momentum equation diff --git a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C index efaf48bbd..c0378da1d 100644 --- a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C +++ b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.C @@ -32,7 +32,6 @@ License #include "plane.H" #include "geompack.H" - // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // const Foam::label Foam::triSurfaceTools::ANYEDGE = -1; @@ -2328,7 +2327,6 @@ Foam::triSurfaceTools::sideType Foam::triSurfaceTools::surfaceSide } -// triangulation of boundaryMesh Foam::triSurface Foam::triSurfaceTools::triangulate ( const polyBoundaryMesh& bMesh, @@ -2415,6 +2413,96 @@ Foam::triSurface Foam::triSurfaceTools::triangulate } +Foam::triSurface Foam::triSurfaceTools::triangulate +( + const polyBoundaryMesh& bMesh, + const labelHashSet& includePatches, + const boundBox& bBox, + const bool verbose +) +{ + const polyMesh& mesh = bMesh.mesh(); + + // Storage for surfaceMesh. Size estimate. + DynamicList triangles + ( + mesh.nFaces() - mesh.nInternalFaces() + ); + + label newPatchi = 0; + + forAllConstIter(labelHashSet, includePatches, iter) + { + const label patchi = iter.key(); + const polyPatch& patch = bMesh[patchi]; + const pointField& points = patch.points(); + + label nTriTotal = 0; + + forAll(patch, patchFacei) + { + const face& f = patch[patchFacei]; + + if (bBox.containsAny(points, f)) + { + faceList triFaces(f.nTriangles(points)); + + label nTri = 0; + + f.triangles(points, nTri, triFaces); + + forAll(triFaces, triFacei) + { + const face& f = triFaces[triFacei]; + + triangles.append(labelledTri(f[0], f[1], f[2], newPatchi)); + + nTriTotal++; + } + } + } + + if (verbose) + { + Pout<< patch.name() << " : generated " << nTriTotal + << " triangles from " << patch.size() << " faces with" + << " new patchid " << newPatchi << endl; + } + + newPatchi++; + } + triangles.shrink(); + + // Create globally numbered tri surface + triSurface rawSurface(triangles, mesh.points()); + + // Create locally numbered tri surface + triSurface surface + ( + rawSurface.localFaces(), + rawSurface.localPoints() + ); + + // Add patch names to surface + surface.patches().setSize(newPatchi); + + newPatchi = 0; + + forAllConstIter(labelHashSet, includePatches, iter) + { + const label patchi = iter.key(); + const polyPatch& patch = bMesh[patchi]; + + surface.patches()[newPatchi].name() = patch.name(); + surface.patches()[newPatchi].geometricType() = patch.type(); + + newPatchi++; + } + + return surface; +} + + // triangulation of boundaryMesh Foam::triSurface Foam::triSurfaceTools::triangulateFaceCentre ( diff --git a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.H b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.H index 1b4578b6f..c49d98efd 100644 --- a/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.H +++ b/src/meshTools/triSurface/triSurfaceTools/triSurfaceTools.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -55,6 +55,7 @@ class edge; class labelledTri; class polyBoundaryMesh; class plane; +class boundBox; /*---------------------------------------------------------------------------*\ Class triSurfaceTools Declaration @@ -473,6 +474,16 @@ public: const bool verbose = false ); + + static triSurface triangulate + ( + const polyBoundaryMesh& bMesh, + const labelHashSet& includePatches, + const boundBox& bBox, + const bool verbose = false + ); + + //- Face-centre triangulation of (selected patches of) boundaryMesh. // Needs // polyMesh (or polyBoundaryMesh) since only at this level are the