diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C index 098b4282a1b3c6659a90d9ea99856237eb2fe054..c7df352eb91e22343703902f58218e9fee335d40 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C @@ -43,14 +43,45 @@ namespace fv // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // +Foam::volScalarField& Foam::fv::atmPlantCanopyTurbSource::getOrReadField +( + const word& fieldName +) const +{ + auto* ptr = mesh_.getObjectPtr<volScalarField>(fieldName); + + if (!ptr) + { + ptr = new volScalarField + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh_ + ); + mesh_.objectRegistry::store(ptr); + } + + return *ptr; +} + + Foam::tmp<Foam::volScalarField::Internal> Foam::fv::atmPlantCanopyTurbSource::calcPlantCanopyTerm ( const volVectorField::Internal& U ) const { + const volScalarField& Cd = getOrReadField(CdName_); + const volScalarField& LAD = getOrReadField(LADname_); + // (SP:Eq. 42) - return 12.0*Foam::sqrt(Cmu_)*plantCd_()*leafAreaDensity_()*mag(U); + return 12.0*Foam::sqrt(Cmu_)*Cd()*LAD()*mag(U); } @@ -65,36 +96,15 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource ) : fv::cellSetOption(sourceName, modelType, dict, mesh), - isEpsilon_(false), - rhoName_(coeffs_.getOrDefault<word>("rho", "rho")), + isEpsilon_(true), Cmu_(Zero), C1_(Zero), C2_(Zero), - plantCd_ - ( - IOobject - ( - "plantCd", - mesh.time().timeName(), - mesh, - IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - mesh - ), - leafAreaDensity_ - ( - IOobject - ( - "leafAreaDensity", - mesh.time().timeName(), - mesh, - IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - mesh - ) + CdName_(), + LADname_() { + read(dict); + const auto* turbPtr = mesh_.findObject<turbulenceModel> ( @@ -113,9 +123,8 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource tmp<volScalarField> tepsilon = turbPtr->epsilon(); tmp<volScalarField> tomega = turbPtr->omega(); - if (tepsilon.is_reference()) + if (!tepsilon.isTmp()) { - isEpsilon_ = true; fieldNames_[0] = tepsilon().name(); const dictionary& turbDict = turbPtr->coeffDict(); @@ -123,7 +132,7 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource C1_.read("C1", turbDict); C2_.read("C2", turbDict); } - else if (tomega.is_reference()) + else if (!tomega.isTmp()) { isEpsilon_ = false; fieldNames_[0] = tomega().name(); @@ -214,4 +223,21 @@ void Foam::fv::atmPlantCanopyTurbSource::addSup } +bool Foam::fv::atmPlantCanopyTurbSource::read(const dictionary& dict) +{ + if (!fv::cellSetOption::read(dict)) + { + return false; + } + + CdName_ = dict.getOrDefault<word>("Cd", "Cd"); + LADname_ = dict.getOrDefault<word>("LAD", "LAD"); + + (void) getOrReadField(CdName_); + (void) getOrReadField(LADname_); + + return true; +} + + // ************************************************************************* // diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H index e6a053ee531cf5b9cea3cc17cef2728910847149..5d255efe326d63d02053e289033db4831071a216 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020 ENERCON GmbH - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,15 +36,16 @@ Description Corrections applied to either of the below, if exist: \verbatim - epsilon | Turbulent kinetic energy dissipation rate [m2/s3] + epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3] omega | Specific dissipation rate [1/s] \endverbatim Required fields: \verbatim - epsilon/omega | Dissipation rate OR Spec. dissipation rate [m2/s3]/[1/s] - plantCd | Plant canopy drag coefficient [-] - leafAreaDensity | Leaf area density [1/m] + Cd | Canopy drag coefficient [-] + LAD | Leaf area density [m^2/m^3] + epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3] + omega | Specific dissipation rate [1/s] \endverbatim References: @@ -61,28 +62,24 @@ Usage \verbatim atmPlantCanopyTurbSource1 { - // Mandatory entries (unmodifiable) - type atmPlantCanopyTurbSource; - - atmPlantCanopyTurbSourceCoeffs - { - // Mandatory (inherited) entries (unmodifiable) - selectionMode all; + // Mandatory entries + type atmPlantCanopyTurbSource; - // Optional entries (unmodifiable) - rho rho; - } + // Optional entries + Cd <word>; + LAD <word>; - // Optional (inherited) entries + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: atmPlantCanopyTurbSource | word | yes | - - rho | Name of density field | word | no | rho + Property | Description | Type | Reqd | Deflt + type | Type name: atmPlantCanopyTurbSource | word | yes | - + Cd | Name of operand canopy drag coefficient field | word | no | Cd + LAD | Name of operand leaf area density field | word | no | LAD \endtable The inherited entries are elaborated in: @@ -109,7 +106,7 @@ namespace fv { /*---------------------------------------------------------------------------*\ - Class atmPlantCanopyTurbSource Declaration + Class atmPlantCanopyTurbSource Declaration \*---------------------------------------------------------------------------*/ class atmPlantCanopyTurbSource @@ -121,26 +118,24 @@ class atmPlantCanopyTurbSource //- Internal flag to determine the working field is epsilon or omega Switch isEpsilon_; - //- Name of density field - const word rhoName_; - //- Required turbulence model coefficients (copied from turb model) dimensionedScalar Cmu_; dimensionedScalar C1_; dimensionedScalar C2_; + //- Name of operand canopy drag coefficient field + word CdName_; - // Fields - - //- Plant canopy drag coefficient field [-] - volScalarField plantCd_; - - //- Leaf area density field [1/m] - volScalarField leafAreaDensity_; + //- Name of operand leaf area density field + word LADname_; // Private Member Functions + //- Return requested field from the object registry + //- or read+register the field to the object registry + volScalarField& getOrReadField(const word& fieldName) const; + //- Return the modifier for plant canopy effects tmp<volScalarField::Internal> calcPlantCanopyTerm ( @@ -221,11 +216,8 @@ public: const label fieldi ); - //- Read source dictionary (effectively no-op) - virtual bool read(const dictionary& dict) - { - return true; - } + //- Read source dictionary + virtual bool read(const dictionary& dict); }; diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C index 15f448ff5735ac57a8377d8999c8b6ca2a40c5b0..158ac966478d005190c5c422b87997a49c7f6efb 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C @@ -42,6 +42,36 @@ namespace fv } +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +Foam::volScalarField& Foam::fv::atmPlantCanopyUSource::getOrReadField +( + const word& fieldName +) const +{ + auto* ptr = mesh_.getObjectPtr<volScalarField>(fieldName); + + if (!ptr) + { + ptr = new volScalarField + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh_ + ); + mesh_.objectRegistry::store(ptr); + } + + return *ptr; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource @@ -53,32 +83,11 @@ Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource ) : fv::cellSetOption(sourceName, modelType, dict, mesh), - rhoName_(coeffs_.getOrDefault<word>("rho", "rho")), - plantCd_ - ( - IOobject - ( - "plantCd", - mesh.time().timeName(), - mesh, - IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - mesh - ), - leafAreaDensity_ - ( - IOobject - ( - "leafAreaDensity", - mesh.time().timeName(), - mesh, - IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - mesh - ) + CdName_(), + LADname_() { + read(dict); + fieldNames_.resize(1, "U"); fv::option::resetApplied(); @@ -95,13 +104,17 @@ void Foam::fv::atmPlantCanopyUSource::addSup const label fieldi ) { - const volVectorField& U = eqn.psi(); - - if (V_ > VSMALL) + if (V_ < VSMALL) { - // (SP:Eq. 42) - eqn -= fvm::Sp(plantCd_*leafAreaDensity_*mag(U), U); + return; } + + const volVectorField& U = eqn.psi(); + const volScalarField& Cd = getOrReadField(CdName_); + const volScalarField& LAD = getOrReadField(LADname_); + + // (SP:Eq. 42), (BSG:Eq. 7) + eqn -= fvm::Sp(Cd*LAD*mag(U), U); } @@ -112,12 +125,16 @@ void Foam::fv::atmPlantCanopyUSource::addSup const label fieldi ) { - const volVectorField& U = eqn.psi(); - - if (V_ > VSMALL) + if (V_ < VSMALL) { - eqn -= fvm::Sp(rho*plantCd_*leafAreaDensity_*mag(U), U); + return; } + + const volVectorField& U = eqn.psi(); + const volScalarField& Cd = getOrReadField(CdName_); + const volScalarField& LAD = getOrReadField(LADname_); + + eqn -= fvm::Sp(rho*Cd*LAD*mag(U), U); } @@ -129,12 +146,33 @@ void Foam::fv::atmPlantCanopyUSource::addSup const label fieldi ) { + if (V_ < VSMALL) + { + return; + } + const volVectorField& U = eqn.psi(); + const volScalarField& Cd = getOrReadField(CdName_); + const volScalarField& LAD = getOrReadField(LADname_); + + eqn -= fvm::Sp(alpha*rho*Cd*LAD*mag(U), U); +} + - if (V_ > VSMALL) +bool Foam::fv::atmPlantCanopyUSource::read(const dictionary& dict) +{ + if (!fv::cellSetOption::read(dict)) { - eqn -= fvm::Sp(alpha*rho*plantCd_*leafAreaDensity_*mag(U), U); + return false; } + + CdName_ = dict.getOrDefault<word>("Cd", "Cd"); + LADname_ = dict.getOrDefault<word>("LAD", "LAD"); + + (void) getOrReadField(CdName_); + (void) getOrReadField(LADname_); + + return true; } diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H index 035204be7e14d70d099fa4e1aa10b28b02f3041a..842e80e6e720796c77f266ca3faf12f09ecda550 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020 ENERCON GmbH - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,7 +31,7 @@ Group grpFvOptionsSources Description - Applies sources on velocity, i.e. \c U, to incorporate effects + Applies sources on velocity (i.e. \c U) to incorporate effects of plant canopy for atmospheric boundary layer modelling. Corrections applied to: @@ -42,8 +42,8 @@ Description Required fields: \verbatim U | Velocity [m/s] - plantCd | Plant canopy drag coefficient [-] - leafAreaDensity | Leaf area density [1/m] + Cd | Plant canopy drag coefficient [-] + LAD | Leaf area density [1/m] \endverbatim References: @@ -53,6 +53,13 @@ Description Modification of two-equation models to account for plant drag. Boundary-Layer Meteorology, 121(2), 229-266. DOI:10.1007/s10546-006-9073-5 + + Governing equations (tag:BSG): + Brozovsky, J., Simonsen, A., & Gaitani, N. (2021). + Validation of a CFD model for the evaluation of urban microclimate + at high latitudes: A case study in Trondheim, Norway. + Building and Environment, 205, 108175. + DOI:10.1016/j.buildenv.2021.108175 \endverbatim Usage @@ -60,28 +67,24 @@ Usage \verbatim atmPlantCanopyUSource1 { - // Mandatory entries (unmodifiable) - type atmPlantCanopyUSource; - - atmPlantCanopyUSourceCoeffs - { - // Mandatory (inherited) entries (unmodifiable) - selectionMode all; + // Mandatory entries + type atmPlantCanopyUSource; - // Optional entries (unmodifiable) - rho rho; - } + // Optional entries + Cd <word>; + LAD <word>; - // Optional (inherited) entries + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: atmPlantCanopyUSource | word | yes | - - rho | Name of density field | word | no | rho + Property | Description | Type | Reqd | Deflt + type | Type name: atmPlantCanopyUSource | word | yes | - + Cd | Name of operand canopy drag coefficient field | word | no | Cd + LAD | Name of operand leaf area density field | word | no | LAD \endtable The inherited entries are elaborated in: @@ -108,7 +111,7 @@ namespace fv { /*---------------------------------------------------------------------------*\ - Class atmPlantCanopyUSource Declaration + Class atmPlantCanopyUSource Declaration \*---------------------------------------------------------------------------*/ class atmPlantCanopyUSource @@ -117,17 +120,18 @@ class atmPlantCanopyUSource { // Private Data - //- Name of density field - const word rhoName_; + //- Name of operand canopy drag coefficient field + word CdName_; + //- Name of operand leaf area density field + word LADname_; - // Fields - //- Plant canopy drag coefficient field [-] - volScalarField plantCd_; + // Private Member Functions - //- Leaf area density field [1/m] - volScalarField leafAreaDensity_; + //- Return requested field from the object registry + //- or read+register the field to the object registry + volScalarField& getOrReadField(const word& fieldName) const; public: @@ -180,11 +184,8 @@ public: const label fieldi ); - //- Read source dictionary (effectively no-op) - virtual bool read(const dictionary& dict) - { - return true; - } + //- Read source dictionary + virtual bool read(const dictionary& dict); }; diff --git a/src/atmosphericModels/turbulenceModels/RAS/kL/kL.C b/src/atmosphericModels/turbulenceModels/RAS/kL/kL.C index 94e393c2eef709c06046a989648344a544811998..0b06f04c14df0a864f007bab479adb1b03485c29 100644 --- a/src/atmosphericModels/turbulenceModels/RAS/kL/kL.C +++ b/src/atmosphericModels/turbulenceModels/RAS/kL/kL.C @@ -67,10 +67,8 @@ tmp<volScalarField> kL<BasicTurbulenceModel>::nutPrime() const template<class BasicTurbulenceModel> tmp<volScalarField> kL<BasicTurbulenceModel>::epsilonCanopy() const { - const auto* CdPtr = - this->mesh_.template findObject<volScalarField>("plantCd"); - const auto* LADPtr = - this->mesh_.template findObject<volScalarField>("leafAreaDensity"); + const auto* CdPtr = this->mesh_.template findObject<volScalarField>("Cd"); + const auto* LADPtr = this->mesh_.template findObject<volScalarField>("LAD"); const volVectorField& U = this->U_; if (CdPtr && LADPtr) diff --git a/src/atmosphericModels/turbulenceModels/RAS/kL/kL.H b/src/atmosphericModels/turbulenceModels/RAS/kL/kL.H index 870b38ac694171b3f9c96a22ebf39cc2199f6dd0..46caa1b5b431188196aebe41854b4eacc82cc297 100644 --- a/src/atmosphericModels/turbulenceModels/RAS/kL/kL.H +++ b/src/atmosphericModels/turbulenceModels/RAS/kL/kL.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2021 OpenCFD Ltd. + Copyright (C) 2021-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -104,8 +104,8 @@ Usage \heading Input fields (optional) \plaintable canopyHeight | Canopy height [m] - plantCd | Plant canopy drag coefficient [-] - leafAreaDensity | Leaf area density [1/m] + Cd | Plant canopy drag coefficient [-] + LAD | Leaf area density [1/m] Rt | Turbulent Richardson number [-] L | Characteristic length scale [m] \endplaintable diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files index 5f3a5d7d252a32300437b840970fb996da99725d..4f974d5d2f2d93cfde5cf0513b6a96503d59f9cd 100644 --- a/src/meshTools/Make/files +++ b/src/meshTools/Make/files @@ -224,6 +224,7 @@ $(faceZoneSources)/setToFaceZone/setToFaceZone.C $(faceZoneSources)/setAndNormalToFaceZone/setAndNormalToFaceZone.C $(faceZoneSources)/searchableSurfaceToFaceZone/searchableSurfaceToFaceZone.C $(faceZoneSources)/planeToFaceZone/planeToFaceZone.C +$(faceZoneSources)/cellToFaceZone/cellToFaceZone.C cellZoneSources = topoSet/cellZoneSources $(cellZoneSources)/topoSetCellZoneSource/topoSetCellZoneSource.C diff --git a/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.C b/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.C index b3401415a0c5d5310ea9ed40a113437b699313b3..9e88902e6c4ac7a68f9d4dbbc338703d6f546115 100644 --- a/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.C +++ b/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.C @@ -48,11 +48,12 @@ namespace Foam Foam::topoSetSource::addToUsageTable Foam::cellToFace::usage_ ( cellToFace::typeName, - "\n Usage: cellToFace <cellSet> all|both\n\n" + "\n Usage: cellToFace <cellSet> all|both|outside\n\n" " Select -all : all faces of cells in the cellSet\n" " -both: faces where both neighbours are in the cellSet\n\n" ); + const Foam::Enum < Foam::cellToFace::cellAction @@ -61,6 +62,7 @@ Foam::cellToFace::cellActionNames_ ({ { cellAction::ALL, "all" }, { cellAction::BOTH, "both" }, + { cellAction::OUTSIDE, "outside" } }); @@ -148,6 +150,65 @@ void Foam::cellToFace::combine } } } + else if (option_ == OUTSIDE) + { + // Add all faces where only one neighbour is in set. + + const label nInt = mesh_.nInternalFaces(); + const labelList& own = mesh_.faceOwner(); + const labelList& nei = mesh_.faceNeighbour(); + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + + // Check all internal faces + for (label facei = 0; facei < nInt; ++facei) + { + if (cellLabels.found(own[facei]) != cellLabels.found(nei[facei])) + { + addOrDelete(set, facei, add); + } + } + + + // Get coupled cell status + boolList neiInSet(mesh_.nBoundaryFaces(), false); + + for (const polyPatch& pp : patches) + { + if (pp.coupled()) + { + label facei = pp.start(); + forAll(pp, i) + { + neiInSet[facei-nInt] = cellLabels.found(own[facei]); + ++facei; + } + } + } + syncTools::swapBoundaryFaceList(mesh_, neiInSet); + + + // Check all boundary faces + for (const polyPatch& pp : patches) + { + label facei = pp.start(); + forAll(pp, i) + { + if (cellLabels.found(own[facei]) != neiInSet[facei-nInt]) + { + addOrDelete(set, facei, add); + } + ++facei; + } + } + } + else + { + FatalErrorInFunction + << "Selected option is not available" + << ", option: " << cellActionNames_[option_] + << exit(FatalError); + } } diff --git a/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.H b/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.H index c9ce52b0fdf40193828da9554a632ab0df61eb45..d1c5638a597043c357a99e9bca83eb15fc339b48 100644 --- a/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.H +++ b/src/meshTools/topoSet/faceSources/cellToFace/cellToFace.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,8 +33,8 @@ Description Operands: \table Operand | Type | Location - input | cellSet(s) | $FOAM_CASE/constant/polyMesh/sets/\<set\> - output | faceSet | $FOAM_CASE/constant/polyMesh/sets/\<set\> + input | cellSet(s) | constant/polyMesh/sets/\<set\> + output | faceSet | constant/polyMesh/sets/\<set\> \endtable Usage @@ -68,7 +68,7 @@ Usage where the entries mean: \table - Property | Description | Type | Req'd | Dflt + Property | Description | Type | Reqd | Deflt name | Name of faceSet | word | yes | - type | Type name: faceSet | word | yes | - action | Action applied on faces - see below | word | yes | - @@ -87,18 +87,20 @@ Usage \verbatim all | All faces of cells in the cellSet both | Faces where both neighbours are in the cellSet + outside | Faces with only one neighbour in the cellSet \endverbatim Options for the conditional mandatory entries: \verbatim - Entry | Description | Type | Req'd | Dflt - sets | Names of input cellSets | wordList | cond'l | - - set | Name of input cellSet | word | cond'l | - + Entry | Description | Type | Reqd | Deflt + sets | Names of input cellSets | wordList | choice | - + set | Name of input cellSet | word | choice | - \endverbatim Note - The order of precedence among the conditional mandatory entries from the + - The order of precedence among the conditional mandatory entries from the highest to the lowest is \c sets, and \c set. + - The \c outside option applies to the cellSets individually. See also - Foam::topoSetSource @@ -109,8 +111,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef cellToFace_H -#define cellToFace_H +#ifndef Foam_cellToFace_H +#define Foam_cellToFace_H #include "topoSetFaceSource.H" #include "Enum.H" @@ -121,7 +123,7 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class cellToFace Declaration + Class cellToFace Declaration \*---------------------------------------------------------------------------*/ class cellToFace @@ -133,7 +135,8 @@ public: enum cellAction { ALL, - BOTH + BOTH, + OUTSIDE }; diff --git a/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.C b/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.C new file mode 100644 index 0000000000000000000000000000000000000000..ed6a4c3041d34307478fc5f68da26cf4726d8b94 --- /dev/null +++ b/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.C @@ -0,0 +1,287 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "cellToFaceZone.H" +#include "polyMesh.H" +#include "faceZoneSet.H" +#include "cellSet.H" +#include "syncTools.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(cellToFaceZone, 0); + addToRunTimeSelectionTable(topoSetSource, cellToFaceZone, word); + addToRunTimeSelectionTable(topoSetSource, cellToFaceZone, istream); + + addToRunTimeSelectionTable(topoSetFaceZoneSource, cellToFaceZone, word); + addToRunTimeSelectionTable(topoSetFaceZoneSource, cellToFaceZone, istream); +} + + +Foam::topoSetSource::addToUsageTable Foam::cellToFaceZone::usage_ +( + cellToFaceZone::typeName, + "\n Usage: cellToFaceZone <slaveCellSet>\n\n" + " Select all outside faces in the cellSet." + " Orientated so slave side is in cellSet.\n\n" +); + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::cellToFaceZone::selectFaces +( + const cellSet& cSet, + bitSet& selectedFace, + bitSet& doFlip +) const +{ + selectedFace.setSize(mesh_.nFaces()); + selectedFace = false; + + doFlip.setSize(mesh_.nFaces()); + doFlip = false; + + + // Add all faces whose both neighbours are in set. + + const label nInt = mesh_.nInternalFaces(); + const labelList& own = mesh_.faceOwner(); + const labelList& nei = mesh_.faceNeighbour(); + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + + // Check all internal faces + for (label facei = 0; facei < nInt; ++facei) + { + const bool ownFound = cSet.found(own[facei]); + const bool neiFound = cSet.found(nei[facei]); + + if (ownFound && !neiFound) + { + selectedFace.set(facei); + doFlip.set(facei, flip_); + } + else if (!ownFound && neiFound) + { + selectedFace.set(facei); + doFlip.set(facei, !flip_); + } + } + + // Get coupled cell status + boolList neiInSet(mesh_.nBoundaryFaces(), false); + + for (const polyPatch& pp : patches) + { + if (pp.coupled()) + { + label facei = pp.start(); + forAll(pp, i) + { + neiInSet[facei-nInt] = cSet.found(own[facei]); + ++facei; + } + } + } + syncTools::swapBoundaryFaceList(mesh_, neiInSet); + + + // Check all boundary faces + for (const polyPatch& pp : patches) + { + label facei = pp.start(); + forAll(pp, i) + { + const bool ownFound = cSet.found(own[facei]); + const bool neiFound = neiInSet[facei-nInt]; + + if (ownFound && !neiFound) + { + selectedFace.set(facei); + doFlip.set(facei, flip_); + } + else if (!ownFound && neiFound) + { + selectedFace.set(facei); + doFlip.set(facei, !flip_); + } + ++facei; + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cellToFaceZone::cellToFaceZone +( + const polyMesh& mesh, + const word& setName, + const bool flip +) +: + topoSetFaceZoneSource(mesh), + names_(one{}, setName), + flip_(flip) +{} + + +Foam::cellToFaceZone::cellToFaceZone +( + const polyMesh& mesh, + const dictionary& dict +) +: + topoSetFaceZoneSource(mesh), + names_(), + flip_(dict.getOrDefault("flip", false)) +{ + // Look for 'sets' or 'set' + if (!dict.readIfPresent("sets", names_)) + { + names_.resize(1); + dict.readEntry("set", names_.first()); + } +} + + +Foam::cellToFaceZone::cellToFaceZone +( + const polyMesh& mesh, + Istream& is +) +: + topoSetFaceZoneSource(mesh), + names_(one{}, word(checkIs(is))), + flip_(false) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::cellToFaceZone::applyToSet +( + const topoSetSource::setAction action, + topoSet& set +) const +{ + if (!isA<faceZoneSet>(set)) + { + WarningInFunction + << "Operation only allowed on a faceZoneSet." << endl; + return; + } + else + { + faceZoneSet& zoneSet = refCast<faceZoneSet>(set); + + if (action == topoSetSource::ADD || action == topoSetSource::NEW) + { + if (verbose_) + { + if (flip_) + { + Info<< " Adding all faces on outside of cellSet " + << flatOutput(names_) + << "; orientation pointing into cellSet" << endl; + } + else + { + Info<< " Adding all faces on outside of cellSet " + << flatOutput(names_) + << "; orientation pointing away from cellSet" << endl; + } + } + + bitSet selectedFace(mesh_.nFaces()); + bitSet doFlip(mesh_.nFaces()); + for (const word& setName : names_) + { + // Load the sets + cellSet cSet(mesh_, setName); + // Select outside faces + selectFaces(cSet, selectedFace, doFlip); + } + + // Start off from copy + DynamicList<label> newAddressing(zoneSet.addressing()); + DynamicList<bool> newFlipMap(zoneSet.flipMap()); + + for (const label facei : selectedFace) + { + if (!zoneSet.found(facei)) + { + newAddressing.append(facei); + newFlipMap.append(doFlip[facei]); + } + } + + zoneSet.addressing().transfer(newAddressing); + zoneSet.flipMap().transfer(newFlipMap); + zoneSet.updateSet(); + } + else if (action == topoSetSource::SUBTRACT) + { + if (verbose_) + { + Info<< " Removing all faces on outside of cellSet " + << flatOutput(names_) + << " ..." << endl; + } + + bitSet selectedFace(mesh_.nFaces()); + bitSet doFlip(mesh_.nFaces()); + for (const word& setName : names_) + { + // Load the sets + cellSet cSet(mesh_, setName); + // Select outside faces + selectFaces(cSet, selectedFace, doFlip); + } + + // Start off empty + DynamicList<label> newAddressing(zoneSet.addressing().size()); + DynamicList<bool> newFlipMap(zoneSet.flipMap().size()); + + for (const label facei : selectedFace) + { + newAddressing.append(facei); + newFlipMap.append(doFlip[facei]); + } + zoneSet.addressing().transfer(newAddressing); + zoneSet.flipMap().transfer(newFlipMap); + zoneSet.updateSet(); + } + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.H b/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.H new file mode 100644 index 0000000000000000000000000000000000000000..338d8f19e320c788dfbfb265e2a55f3dcba60ac0 --- /dev/null +++ b/src/meshTools/topoSet/faceZoneSources/cellToFaceZone/cellToFaceZone.H @@ -0,0 +1,190 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::cellToFaceZone + +Description + A \c topoSetSource to select faces with only one + neighbour (i.e. outside) in a specified \c cellSet. + + This is just a shortcut for + - extracting outside faces as a \c faceSet (\c cellToFace with \c outside). + - using \c setsToFaceZone to convert \c faceSet + and \c cellSet to oriented \c faceZone. + + Operands: + \table + Operand | Type | Location + input | cellSet(s) | constant/polyMesh/sets/\<set\> + output | faceZone | constant/polyMesh/faceZones + \endtable + +Usage + Minimal example by using \c system/topoSetDict.actions: + \verbatim + { + // Mandatory entries + name <name>; + type faceZoneSet; + action <action>; + source cellToFaceZone; + + // Select either of the below + + // Option-1 + sets + ( + <word> + <word> + ... + ); + + // Option-2 + set <word>; + + // Optional entries + flip <bool>; + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + name | Name of faceZone | word | yes | - + type | Type name: faceZoneSet | word | yes | - + action | Action applied on faces - see below | word | yes | - + source | Source name: cellToFaceZone | word | yes | - + set(s) | Name of input cellSet(s) containing the slave cells <!-- + --> | word | yes | - + flip | Flag to select master/slave cells | bool | no | false + \endtable + + Options for the \c action entry: + \verbatim + new | Create a new faceZone from selected faces + add | Add selected faces of a faceZoneSet into this faceZone + subtract | Remove selected faces of a faceZoneSet from this faceZone + \endverbatim + +Notes + - \c flip=true sets the orientation of faces + pointing into the \c cellSet, and vice versa. + +SourceFiles + cellToFaceZone.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_cellToFaceZone_H +#define Foam_cellToFaceZone_H + +#include "topoSetFaceZoneSource.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class cellSet; + +/*---------------------------------------------------------------------------*\ + Class cellToFaceZone Declaration +\*---------------------------------------------------------------------------*/ + +class cellToFaceZone +: + public topoSetFaceZoneSource +{ + // Private Data + + //- Add usage string + static addToUsageTable usage_; + + //- Names of cellSets to use + wordList names_; + + //- Whether cellSet is slave cells or master cells + const bool flip_; + + + // Private Member Functions + + //- Select outside faces of cellSet + void selectFaces + ( + const cellSet& cSet, + bitSet& selectedFace, + bitSet& doFlip + ) const; + + +public: + + //- Runtime type information + TypeName("cellToFaceZone"); + + + // Constructors + + //- Construct from components + cellToFaceZone + ( + const polyMesh& mesh, + const word& cellSetName, + const bool flip + ); + + //- Construct from dictionary + cellToFaceZone(const polyMesh& mesh, const dictionary& dict); + + //- Construct from Istream + cellToFaceZone(const polyMesh& mesh, Istream& is); + + + //- Destructor + virtual ~cellToFaceZone() = default; + + + // Member Functions + + virtual void applyToSet + ( + const topoSetSource::setAction action, + topoSet& set + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/thermophysicalModels/radiation/Make/files b/src/thermophysicalModels/radiation/Make/files index acd357afac61656868e98476b0ba57d3d3b540e2..08c27f94bd543ef5fe8c62d9e86df7bab900e069 100644 --- a/src/thermophysicalModels/radiation/Make/files +++ b/src/thermophysicalModels/radiation/Make/files @@ -12,6 +12,7 @@ radiationModels/opaqueSolid/opaqueSolid.C radiationModels/solarLoad/solarLoad.C radiationModels/solarLoad/faceShading/faceShading.C radiationModels/solarLoad/faceReflecting/faceReflecting.C +radiationModels/solarLoad/solarLoadBase.C /* Scatter model */ submodels/scatterModel/scatterModel/scatterModel.C diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C index ee2cf3a33074aa1c212b58fdbe448b7d76aeb334..fb670bc53eefab0c01b84330578aef45a03dd8f5 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C @@ -31,6 +31,7 @@ License #include "boundaryRadiationProperties.H" #include "cyclicAMIPolyPatch.H" #include "volFields.H" +#include "surfaceFields.H" #include "distributedTriSurfaceMesh.H" #include "OBJstream.H" @@ -43,153 +44,65 @@ namespace Foam // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::faceShading::writeRays -( - const fileName& fName, - const DynamicField<point>& endCf, - const pointField& myFc -) -{ - OBJstream os(fName); - - Pout<< "Dumping rays to " << os.name() << endl; - - forAll(myFc, facei) - { - os.writeLine(myFc[facei], endCf[facei]); - } -} - - -Foam::triSurface Foam::faceShading::triangulate -( - const labelHashSet& includePatches, - const List<labelHashSet>& includeAllFacesPerPatch -) +void Foam::faceShading::calculate() { - const polyBoundaryMesh& bMesh = mesh_.boundaryMesh(); - - // Storage for surfaceMesh. Size estimate. - DynamicList<labelledTri> triangles(mesh_.nBoundaryFaces()); - - label newPatchI = 0; - - for (const label patchI : includePatches) - { - const polyPatch& patch = bMesh[patchI]; - const pointField& points = patch.points(); - - label nTriTotal = 0; - - if (includeAllFacesPerPatch[patchI].size()) - { - for (const label patchFaceI : includeAllFacesPerPatch[patchI]) - { - const face& f = patch[patchFaceI]; - - faceList triFaces(f.nTriangles(points)); - - label nTri = 0; + const auto& pbm = mesh_.boundaryMesh(); - f.triangles(points, nTri, triFaces); - - for (const face& f : triFaces) - { - triangles.append - ( - labelledTri(f[0], f[1], f[2], newPatchI) - ); - nTriTotal++; - } - } - newPatchI++; - } - } - - triangles.shrink(); - - // Create globally numbered tri surface - triSurface rawSurface(triangles, mesh_.points()); - - // Create locally numbered tri surface - triSurface surface + const bitSet isOpaqueFace ( - rawSurface.localFaces(), - rawSurface.localPoints() + selectOpaqueFaces + ( + radiation::boundaryRadiationProperties::New(mesh_), + patchIDs_, + zoneIDs_ + ) ); - // Add patch names to surface - surface.patches().setSize(newPatchI); - - newPatchI = 0; - - for (const label patchI : includePatches) - { - const polyPatch& patch = bMesh[patchI]; - - if (includeAllFacesPerPatch[patchI].size()) - { - surface.patches()[newPatchI].name() = patch.name(); - surface.patches()[newPatchI].geometricType() = patch.type(); - - newPatchI++; - } - } - - return surface; -} - - -void Foam::faceShading::calculate() -{ - const radiation::boundaryRadiationProperties& boundaryRadiation = - radiation::boundaryRadiationProperties::New(mesh_); - - label nFaces = 0; //total number of direct hit faces - - const polyBoundaryMesh& patches = mesh_.boundaryMesh(); - - DynamicList<point> dynCf(nFaces); - DynamicList<label> dynFacesI; - - forAll(patches, patchI) - { - const polyPatch& pp = patches[patchI]; - const vectorField::subField cf = pp.faceCentres(); - - if (!pp.coupled() && !isA<cyclicAMIPolyPatch>(pp)) - { - const tmp<scalarField> tt = - boundaryRadiation.transmissivity(patchI); - const scalarField& t = tt(); - const vectorField& n = pp.faceNormals(); + // Find faces potentially hit by solar rays + // - correct normal + // - transmissivity 0 + labelList hitFacesIds; + bitSet hitFacesFlips; + selectFaces + ( + true, // use normal to do first filtering + isOpaqueFace, + patchIDs_, + zoneIDs_, - forAll(n, faceI) - { - const vector nf(n[faceI]); - if (((direction_ & nf) > 0) && (t[faceI] == 0.0)) - { - dynFacesI.append(faceI + pp.start()); - dynCf.append(cf[faceI]); - nFaces++; - } - } - } - } + hitFacesIds, + hitFacesFlips + ); Info<< "Number of 'potential' direct hits : " - << returnReduce(nFaces, sumOp<label>()) << endl; - - labelList hitFacesIds(nFaces); - hitFacesIds.transfer(dynFacesI); + << returnReduce(hitFacesIds.size(), sumOp<label>()) << endl; - pointField Cfs(hitFacesIds.size()); - Cfs.transfer(dynCf); // * * * * * * * * * * * * * * * // Create distributedTriSurfaceMesh Random rndGen(653213); + // Find potential obstructions. Include all faces that might potentially + // block (so ignore normal) + labelList blockingFacesIds; + bitSet blockingFacesFlips; + selectFaces + ( + false, // use normal to do first filtering + isOpaqueFace, + patchIDs_, + zoneIDs_, + + blockingFacesIds, + blockingFacesFlips + ); + + const triSurface localSurface = triangulate + ( + blockingFacesIds, + blockingFacesFlips + ); + // Determine mesh bounding boxes: List<treeBoundBox> meshBb ( @@ -210,36 +123,6 @@ void Foam::faceShading::calculate() ); dict.add("mergeDistance", SMALL); - labelHashSet includePatches; - List<labelHashSet> includeAllFacesPerPatch(patches.size()); - - forAll(patches, patchI) - { - const polyPatch& pp = patches[patchI]; - if (!pp.coupled() && !isA<cyclicAMIPolyPatch>(pp)) - { - includePatches.insert(patchI); - - const tmp<scalarField> tt = - boundaryRadiation.transmissivity(patchI); - const scalarField& tau = tt(); - - forAll(pp, faceI) - { - if (tau[faceI] == 0.0) - { - includeAllFacesPerPatch[patchI].insert(faceI); - } - } - } - } - - triSurface localSurface = triangulate - ( - includePatches, - includeAllFacesPerPatch - ); - distributedTriSurfaceMesh surfacesMesh ( IOobject @@ -264,36 +147,28 @@ void Foam::faceShading::calculate() returnReduce(5.0*mesh_.bounds().mag(), maxOp<scalar>()); // Calculate index of faces which have a direct hit (local) - DynamicList<label> rayStartFace(nFaces + 0.01*nFaces); // Shoot Rays // * * * * * * * * * * * * * * * * { - DynamicField<point> start(nFaces); + DynamicField<point> start(hitFacesIds.size()); DynamicField<point> end(start.size()); DynamicList<label> startIndex(start.size()); - label i = 0; - do - { - for (; i < Cfs.size(); i++) - { - const point& fc = Cfs[i]; - - const label myFaceId = hitFacesIds[i]; + const pointField& faceCentres = mesh_.faceCentres(); - const vector d(direction_*maxBounding); + const vector d(direction_*maxBounding); - start.append(fc - 0.001*d); - - startIndex.append(myFaceId); - - end.append(fc - d); - - } + forAll(hitFacesIds, i) + { + const label facei = hitFacesIds[i]; + const point& fc = faceCentres[facei]; - } while (returnReduceOr(i < Cfs.size())); + start.append(fc - 0.001*d); + startIndex.append(facei); + end.append(fc - d); + } List<pointIndexHit> hitInfo(startIndex.size()); surfacesMesh.findLine(start, end, hitInfo); @@ -301,11 +176,23 @@ void Foam::faceShading::calculate() // Collect the rays which has 'only one not wall' obstacle between // start and end. // If the ray hit itself get stored in dRayIs + + label nVisible = 0; + forAll(hitInfo, rayI) + { + if (!hitInfo[rayI].hit()) + { + nVisible++; + } + } + rayStartFaces_.setSize(nVisible); + nVisible = 0; + forAll(hitInfo, rayI) { if (!hitInfo[rayI].hit()) { - rayStartFace.append(startIndex[rayI]); + rayStartFaces_[nVisible++] = startIndex[rayI]; } } @@ -325,36 +212,39 @@ void Foam::faceShading::calculate() end.clear(); } - rayStartFaces_.transfer(rayStartFace); - if (debug) { - tmp<volScalarField> thitFaces + auto thitFaces = tmp<surfaceScalarField>::New ( - new volScalarField + IOobject ( - IOobject - ( - "hitFaces", - mesh_.time().timeName(), - mesh_, - IOobject::NO_READ, - IOobject::NO_WRITE - ), + "hitFaces", + mesh_.time().timeName(), mesh_, - dimensionedScalar(dimless, Zero) - ) + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + mesh_, + dimensionedScalar(dimless, Zero) ); - volScalarField& hitFaces = thitFaces.ref(); - volScalarField::Boundary& hitFacesBf = hitFaces.boundaryFieldRef(); + surfaceScalarField& hitFaces = thitFaces.ref(); + surfaceScalarField::Boundary& hitFacesBf = hitFaces.boundaryFieldRef(); hitFacesBf = 0.0; - for (const label faceI : rayStartFaces_) + for (const label facei : rayStartFaces_) { - label patchID = patches.whichPatch(faceI); - const polyPatch& pp = patches[patchID]; - hitFacesBf[patchID][faceI - pp.start()] = 1.0; + const label patchID = pbm.whichPatch(facei); + if (patchID == -1) + { + hitFaces[facei] = 1.0; + } + else + { + const polyPatch& pp = pbm[patchID]; + hitFacesBf[patchID][facei - pp.start()] = 1.0; + } } hitFaces.write(); } @@ -364,28 +254,290 @@ void Foam::faceShading::calculate() } +Foam::triSurface Foam::faceShading::triangulate +( + const labelUList& faceIDs, + const bitSet& flipMap +) const +{ + if (faceIDs.size() != flipMap.size()) + { + FatalErrorInFunction << "Size problem :" + << "faceIDs:" << faceIDs.size() + << "flipMap:" << flipMap.size() + << exit(FatalError); + } + + const auto& points = mesh_.points(); + const auto& faces = mesh_.faces(); + const auto& bMesh = mesh_.boundaryMesh(); + const auto& fzs = mesh_.faceZones(); + + // Patching of surface: + // - non-processor patches + // - faceZones + // Note: check for faceZones on boundary? Who has priority? + geometricSurfacePatchList surfPatches(bMesh.nNonProcessor()+fzs.size()); + labelList patchID(mesh_.nFaces(), -1); + { + label newPatchi = 0; + for (label patchi = 0; patchi < bMesh.nNonProcessor(); ++patchi) + { + const auto& pp = bMesh[patchi]; + + surfPatches[newPatchi] = geometricSurfacePatch + ( + pp.name(), + newPatchi, + pp.type() + ); + SubList<label> + ( + patchID, + pp.size(), + pp.start() + ) = newPatchi; + + newPatchi++; + } + for (const auto& fz : fzs) + { + surfPatches[newPatchi] = geometricSurfacePatch + ( + fz.name(), + newPatchi, + fz.type() + ); + UIndirectList<label>(patchID, fz) = newPatchi; + + newPatchi++; + } + } + + + // Storage for surfaceMesh. Size estimate. + DynamicList<labelledTri> triangles(2*faceIDs.size()); + + // Work array + faceList triFaces; + + forAll(faceIDs, i) + { + const label facei = faceIDs[i]; + const bool flip = flipMap[i]; + const label patchi = patchID[facei]; + const face& f = faces[facei]; + + // Triangulate face + triFaces.setSize(f.nTriangles(points)); + label nTri = 0; + f.triangles(points, nTri, triFaces); + + for (const face& f : triFaces) + { + if (!flip) + { + triangles.append(labelledTri(f[0], f[1], f[2], patchi)); + } + else + { + triangles.append(labelledTri(f[0], f[2], f[1], patchi)); + } + } + } + + 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().transfer(surfPatches); + + return surface; +} + + +Foam::bitSet Foam::faceShading::selectOpaqueFaces +( + const radiation::boundaryRadiationProperties& boundaryRadiation, + const labelUList& patchIDs, + const labelUList& zoneIDs +) const +{ + const auto& pbm = mesh_.boundaryMesh(); + + bitSet isOpaqueFace(mesh_.nFaces(), false); + + // Check selected patches + for (const label patchi : patchIDs) + { + const auto& pp = pbm[patchi]; + tmp<scalarField> tt = boundaryRadiation.transmissivity(patchi); + const scalarField& t = tt.cref(); + + forAll(t, i) + { + isOpaqueFace[i + pp.start()] = (t[i] == 0.0); + } + } + + // Check selected faceZones + const auto& fzs = mesh_.faceZones(); + + for (const label zonei : zoneIDs) + { + const auto& fz = fzs[zonei]; + + //- Note: slice mesh face centres preferentially + tmp<scalarField> tt = boundaryRadiation.zoneTransmissivity + ( + zonei, + fz + ); + const scalarField& t = tt.cref(); + + forAll(t, i) + { + isOpaqueFace[fz[i]] = (t[i] == 0.0); + } + } + + return isOpaqueFace; +} + + +void Foam::faceShading::selectFaces +( + const bool useNormal, + const bitSet& isCandidateFace, + const labelUList& patchIDs, + const labelUList& zoneIDs, + + labelList& faceIDs, + bitSet& flipMap +) const +{ + const auto& pbm = mesh_.boundaryMesh(); + + bitSet isSelected(mesh_.nFaces()); + DynamicList<label> dynFaces(mesh_.nBoundaryFaces()); + bitSet isFaceFlipped(mesh_.nFaces()); + + // Add patches + for (const label patchi : patchIDs) + { + const auto& pp = pbm[patchi]; + const vectorField& n = pp.faceNormals(); + + forAll(n, i) + { + const label meshFacei = i + pp.start(); + if + ( + isCandidateFace[meshFacei] + && ( + !useNormal + || ((direction_ & n[i]) > 0) + ) + ) + { + isSelected.set(meshFacei); + isFaceFlipped[meshFacei] = false; + dynFaces.append(meshFacei); + } + } + } + + + // Add faceZones + const auto& fzs = mesh_.faceZones(); + + for (const label zonei : zoneIDs) + { + const auto& fz = fzs[zonei]; + const primitiveFacePatch& pp = fz(); + const vectorField& n = pp.faceNormals(); + + forAll(n, i) + { + const label meshFacei = fz[i]; + + if + ( + !isSelected[meshFacei] + && isCandidateFace[meshFacei] + && ( + !useNormal + || ((direction_ & n[i]) > 0) + ) + ) + { + isSelected.set(meshFacei); + dynFaces.append(meshFacei); + isFaceFlipped[meshFacei] = fz.flipMap()[i]; + } + } + } + faceIDs = std::move(dynFaces); + flipMap = bitSet(isFaceFlipped, faceIDs); +} + + +void Foam::faceShading::writeRays +( + const fileName& fName, + const DynamicField<point>& endCf, + const pointField& myFc +) +{ + OBJstream os(fName); + + Pout<< "Dumping rays to " << os.name() << endl; + + forAll(myFc, facei) + { + os.writeLine(myFc[facei], endCf[facei]); + } +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::faceShading::faceShading ( const fvMesh& mesh, - const vector dir, - const labelList& hitFaceList + const vector& dir ) : mesh_(mesh), + patchIDs_(nonCoupledPatches(mesh)), + zoneIDs_(0), direction_(dir), - rayStartFaces_(hitFaceList) -{} + rayStartFaces_(0) +{ + calculate(); +} Foam::faceShading::faceShading ( const fvMesh& mesh, - const vector dir + const labelList& patchIDs, + const labelList& zoneIDs, + const vector& dir ) : mesh_(mesh), + patchIDs_(patchIDs), + zoneIDs_(zoneIDs), direction_(dir), rayStartFaces_(0) { @@ -395,6 +547,23 @@ Foam::faceShading::faceShading // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +Foam::labelList Foam::faceShading::nonCoupledPatches(const polyMesh& mesh) +{ + const auto& pbm = mesh.boundaryMesh(); + + DynamicList<label> ncPatches; + forAll(pbm, patchi) + { + const polyPatch& pp = pbm[patchi]; + if (!pp.coupled() && !isA<cyclicAMIPolyPatch>(pp)) + { + ncPatches.append(patchi); + } + } + return ncPatches; +} + + void Foam::faceShading::correct() { calculate(); diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.H b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.H index 1374ec362c12242cd4c5f58415be46fe6ed4326e..6ef7b1574ff8d0939852739fee7775bdd04d927e 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.H +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2015 OpenFOAM Foundation - Copyright (C) 2017-2018 OpenCFD Ltd. + Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,6 +28,7 @@ Class Foam::faceShading Description + Helper class to calculate visible faces for global, sun-like illumination. faceShading uses the transmissivity value in the boundaryRadiationProperties in order to evaluate which faces are "hit" by the "direction" vector. @@ -41,31 +42,36 @@ SourceFiles #ifndef faceShading_H #define faceShading_H -#include "fvMesh.H" -#include "Time.H" -#include "meshTools.H" +#include "boundaryRadiationProperties.H" #include "DynamicField.H" -#include "labelIOList.H" -#include "wallPolyPatch.H" -#include "triSurfaceTools.H" - +#include "triSurface.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { +// Forward Declarations +class fvMesh; +class polyMesh; + /*---------------------------------------------------------------------------*\ Class faceShading Declaration \*---------------------------------------------------------------------------*/ class faceShading { - // Private data + // Private Data //- Reference to mesh const fvMesh& mesh_; + //- Patches to check for visibility + const labelList patchIDs_; + + //- FaceZones to check for visibility + const labelList zoneIDs_; + //- Direction vector direction_; @@ -73,18 +79,42 @@ class faceShading labelList rayStartFaces_; - // Private members + // Private Member Functions //- Calculate ray start faces void calculate(); - - //- Construct a triSurface from patches and faces on global local index + //- Construct a triSurface from selected faces on patches or faceZones. + // Resulting surface has regioning with mesh patches first, faceZones + // second. triSurface triangulate ( - const labelHashSet& includePatches, - const List<labelHashSet>& includeAllFaces - ); + const labelUList& faceIDs, + const bitSet& flipMap + ) const; + + //- Find opaque faces by looking at the radiation properties. + bitSet selectOpaqueFaces + ( + const radiation::boundaryRadiationProperties& boundaryRadiation, + const labelUList& patchIDs, + const labelUList& zoneIDs + ) const; + + //- Pick up candidate faces that might be blocking visibility for + // other faces: + // - if transmissivity is 0 + // - (optional) if pointing wrong way + void selectFaces + ( + const bool useNormal, + const bitSet& isCandidateFace, + const labelUList& patchIDs, + const labelUList& zoneIDs, + + labelList& faceIDs, + bitSet& flipMap + ) const; //- Write rays void writeRays @@ -109,19 +139,25 @@ public: // Constructors - //- Construct from components + //- Helper: return all uncoupled patches + static labelList nonCoupledPatches(const polyMesh& mesh); + + //- Construct from mesh and vector to 'sun'. All uncoupled patches + // are checked for visibility. faceZones are ignored. faceShading ( const fvMesh& mesh, - const vector dir, - const labelList& hitFaceList + const vector& dir ); - //- Construct from mesh and vector + //- Construct from mesh and vector to 'sun' and selected patches + // and faceZones. faceShading ( const fvMesh& mesh, - const vector + const labelList& patchIDs, + const labelList& zoneIDs, + const vector& dir ); @@ -133,7 +169,7 @@ public: // Access - //- const access to direction + //- Const access to direction const vector direction() const { return direction_; @@ -145,7 +181,7 @@ public: return direction_; } - //- Access to rayStartFaces + //- Const access to rayStartFaces const labelList& rayStartFaces() const { return rayStartFaces_; diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.C index aaf4011c9b2d0842bbc08d1442f8267c194e27be..1b897d7a61e15392dfdd59edc42f993021c3ae12 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.C +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.C @@ -82,28 +82,28 @@ void Foam::radiation::solarLoad::updateReflectedRays { if (includePatches[patchID]) { - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { qrBf[patchID] += - reflectedFaces_->qreflective(bandI).boundaryField()[patchID]; + reflectedFaces_->qreflective(bandi).boundaryField()[patchID]; } } else { const scalarField& sf = mesh_.magSf().boundaryField()[patchID]; - const labelUList& cellIs = patches[patchID].faceCells(); + const labelUList& cellis = patches[patchID].faceCells(); - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - forAll(cellIs, i) + forAll(cellis, i) { - const label cellI = cellIs[i]; + const label celli = cellis[i]; - Ru_[cellI] += + Ru_[celli] += ( - reflectedFaces_->qreflective(bandI). + reflectedFaces_->qreflective(bandi). boundaryField()[patchID][i] * sf[i] - )/V[cellI]; + )/V[celli]; } } } @@ -115,8 +115,30 @@ bool Foam::radiation::solarLoad::updateHitFaces() { if (!hitFaces_) { - hitFaces_.reset(new faceShading(mesh_, solarCalc_.direction())); - return true; + const boundaryRadiationProperties& boundaryRadiation = + boundaryRadiationProperties::New(mesh_); + + const labelList activeFaceZoneIds(boundaryRadiation.faceZoneIds()); + + if (!activeFaceZoneIds.size()) + { + hitFaces_.reset(new faceShading(mesh_, solarCalc_.direction())); + } + else + { + hitFaces_.reset + ( + new faceShading + ( + mesh_, + faceShading::nonCoupledPatches(mesh_), + activeFaceZoneIds, + solarCalc_.direction() + ) + ); + } + + return true; } else { @@ -163,10 +185,10 @@ void Foam::radiation::solarLoad::updateAbsorptivity for (const label patchID : includePatches) { absorptivity_[patchID].setSize(nBands_); - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - absorptivity_[patchID][bandI] = - boundaryRadiation.absorptivity(patchID, bandI); + absorptivity_[patchID][bandi] = + boundaryRadiation.absorptivity(patchID, bandi); } } } @@ -185,29 +207,37 @@ void Foam::radiation::solarLoad::updateDirectHitRadiation // Reset qr and qrPrimary qrBf = 0.0; - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { volScalarField::Boundary& qprimaryBf = - qprimaryRad_[bandI].boundaryFieldRef(); + qprimaryRad_[bandi].boundaryFieldRef(); qprimaryBf = 0.0; forAll(hitFacesId, i) { - const label faceI = hitFacesId[i]; - const label patchID = patches.whichPatch(faceI); + const label facei = hitFacesId[i]; + const label patchID = patches.whichPatch(facei); + + if (patchID == -1) + { + continue; + } + const polyPatch& pp = patches[patchID]; - const label localFaceI = faceI - pp.start(); - const vector qPrim = - solarCalc_.directSolarRad()*solarCalc_.direction(); + const label localFaceI = facei - pp.start(); + const vector qPrim + ( + solarCalc_.directSolarRad()*solarCalc_.direction() + ); const vectorField& n = pp.faceNormals(); { qprimaryBf[patchID][localFaceI] += (qPrim & n[localFaceI]) - * spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[localFaceI]; + * spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[localFaceI]; } if (includeMappedPatchBasePatches[patchID]) @@ -217,13 +247,13 @@ void Foam::radiation::solarLoad::updateDirectHitRadiation else { const vectorField& sf = mesh_.Sf().boundaryField()[patchID]; - const label cellI = pp.faceCells()[localFaceI]; + const label celli = pp.faceCells()[localFaceI]; - Ru_[cellI] += + Ru_[celli] += (qPrim & sf[localFaceI]) - * spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[localFaceI] - / V[cellI]; + * spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[localFaceI] + / V[celli]; } } } @@ -251,71 +281,36 @@ void Foam::radiation::solarLoad::updateSkyDiffusiveRadiation const scalarField& sf = mesh_.magSf().boundaryField()[patchID]; const vectorField n = pp.faceNormals(); - const labelList& cellIds = pp.faceCells(); + const labelList& cellids = pp.faceCells(); - forAll(n, faceI) - { - const scalar cosEpsilon(verticalDir_ & -n[faceI]); - - scalar Ed(0.0); - scalar Er(0.0); - const scalar cosTheta(solarCalc_.direction() & -n[faceI]); + // Calculate diffusive radiance + // contribution from sky and ground + tmp<scalarField> tdiffuseSolarRad = + solarCalc_.diffuseSolarRad(n); + const scalarField& diffuseSolarRad = tdiffuseSolarRad.cref(); - { - // Above the horizon - if (cosEpsilon == 0.0) - { - // Vertical walls - scalar Y(0); - - if (cosTheta > -0.2) - { - Y = 0.55+0.437*cosTheta + 0.313*sqr(cosTheta); - } - else - { - Y = 0.45; - } - - Ed = solarCalc_.C()*Y*solarCalc_.directSolarRad(); - } - else - { - //Other than vertical walls - Ed = - solarCalc_.C() - * solarCalc_.directSolarRad() - * (1.0 + cosEpsilon)/2.0; - } - - // Ground reflected - Er = - solarCalc_.directSolarRad() - * (solarCalc_.C() + Foam::sin(solarCalc_.beta())) - * solarCalc_.groundReflectivity() - * (1.0 - cosEpsilon)/2.0; - } - - const label cellI = cellIds[faceI]; + forAll(n, facei) + { + const label celli = cellids[facei]; if (includeMappedPatchBasePatches[patchID]) { - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - qrBf[patchID][faceI] += - (Ed + Er) - * spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[faceI]; + qrBf[patchID][facei] += + diffuseSolarRad[facei] + * spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[facei]; } } else { - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - Ru_[cellI] += - (Ed + Er) - * spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[faceI] - * sf[faceI]/V[cellI]; + Ru_[celli] += + diffuseSolarRad[facei] + * spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[facei] + * sf[facei]/V[celli]; } } } @@ -331,30 +326,30 @@ void Foam::radiation::solarLoad::updateSkyDiffusiveRadiation const polyPatch& pp = patches[patchID]; const scalarField& sf = mesh_.magSf().boundaryField()[patchID]; - const labelList& cellIds = pp.faceCells(); - forAll(pp, faceI) + const labelList& cellids = pp.faceCells(); + forAll(pp, facei) { - const label cellI = cellIds[faceI]; + const label celli = cellids[facei]; if (includeMappedPatchBasePatches[patchID]) { - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - qrBf[patchID][faceI] += + qrBf[patchID][facei] += solarCalc_.diffuseSolarRad() - * spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[faceI]; + * spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[facei]; } } else { - for (label bandI = 0; bandI < nBands_; ++bandI) + for (label bandi = 0; bandi < nBands_; ++bandi) { - Ru_[cellI] += + Ru_[celli] += ( - spectralDistribution_[bandI] - * absorptivity_[patchID][bandI]()[faceI] + spectralDistribution_[bandi] + * absorptivity_[patchID][bandi]()[facei] * solarCalc_.diffuseSolarRad() - )*sf[faceI]/V[cellI]; + )*sf[facei]/V[celli]; } } } @@ -387,16 +382,16 @@ void Foam::radiation::solarLoad::initialise(const dictionary& coeffs) qprimaryRad_.setSize(nBands_); - forAll(qprimaryRad_, bandI) + forAll(qprimaryRad_, bandi) { qprimaryRad_.set ( - bandI, + bandi, new volScalarField ( IOobject ( - "qprimaryRad_" + Foam::name(bandI) , + "qprimaryRad_" + Foam::name(bandi) , mesh_.time().timeName(), mesh_, IOobject::NO_READ, @@ -408,21 +403,12 @@ void Foam::radiation::solarLoad::initialise(const dictionary& coeffs) ); } - if (coeffs.readIfPresent("gridUp", verticalDir_)) - { - verticalDir_.normalise(); - } - else - { - const uniformDimensionedVectorField& g = - meshObjects::gravity::New(mesh_.time()); - verticalDir_ = (-g/mag(g)).value(); - } - coeffs.readIfPresent("solidCoupled", solidCoupled_); coeffs.readIfPresent("wallCoupled", wallCoupled_); coeffs.readIfPresent("updateAbsorptivity", updateAbsorptivity_); coeffs.readEntry("useReflectedRays", useReflectedRays_); + + (void) updateHitFaces(); } /* @@ -516,11 +502,11 @@ void Foam::radiation::solarLoad::calculateQdiff // Weight emissivity by spectral distribution scalarField e(pp.size(), 0.0); - for (label bandI = 0; bandI < nBands_; bandI++) + for (label bandi = 0; bandi < nBands_; bandi++) { const tmp<scalarField> te = - spectralDistribution_[bandI] - *boundaryRadiation.diffReflectivity(patchID, bandI); + spectralDistribution_[bandi] + *boundaryRadiation.diffReflectivity(patchID, bandi); e += te(); } @@ -543,15 +529,15 @@ void Foam::radiation::solarLoad::calculateQdiff scalar fullArea = 0.0; forAll(fineFaces, j) { - label faceI = fineFaces[j]; - label globalFaceI = faceI + pp.start(); + label facei = fineFaces[j]; + label globalFaceI = facei + pp.start(); if (hitFacesId.found(globalFaceI)) { - fullArea += sf[faceI]; + fullArea += sf[facei]; } - Eave[coarseI] += (e[faceI]*sf[faceI])/fineArea; - Tave[coarseI] += (pow4(Tf[faceI])*sf[faceI])/fineArea; + Eave[coarseI] += (e[facei]*sf[facei])/fineArea; + Tave[coarseI] += (pow4(Tf[facei])*sf[facei])/fineArea; } localCoarsePartialArea[compactI++] = fullArea/fineArea; } @@ -616,11 +602,11 @@ void Foam::radiation::solarLoad::calculateQdiff scalarField a(ppf.size(), Zero); - for (label bandI = 0; bandI < nBands_; bandI++) + for (label bandi = 0; bandi < nBands_; bandi++) { const tmp<scalarField> ta = - spectralDistribution_[bandI] - * absorptivity_[patchID][bandI](); + spectralDistribution_[bandi] + * absorptivity_[patchID][bandi](); a += ta(); } @@ -635,8 +621,8 @@ void Foam::radiation::solarLoad::calculateQdiff scalar aAve = 0.0; forAll(fineFaces, j) { - label faceI = fineFaces[j]; - aAve += (a[faceI]*sf[faceI])/fineArea; + label facei = fineFaces[j]; + aAve += (a[facei]*sf[facei])/fineArea; } const scalarList& vf = FmyProc[locaFaceI]; @@ -689,8 +675,8 @@ void Foam::radiation::solarLoad::calculateQdiff const labelList& fineFaces = coarseToFine_[i][coarseFaceID]; forAll(fineFaces, k) { - label faceI = fineFaces[k]; - qrp[faceI] = localqDiffusive[compactId]; + label facei = fineFaces[k]; + qrp[facei] = localqDiffusive[compactId]; } compactId ++; } @@ -711,12 +697,12 @@ void Foam::radiation::solarLoad::calculateQdiff else { const polyPatch& pp = patches[patchID]; - const labelList& cellIds = pp.faceCells(); + const labelList& cellids = pp.faceCells(); const scalarField& sf = mesh_.magSf().boundaryField()[patchID]; - forAll(pp, faceI) + forAll(pp, facei) { - const label cellI = cellIds[faceI]; - Ru_[cellI] += qSecond[faceI]*sf[faceI]/V[cellI]; + const label celli = cellids[facei]; + Ru_[celli] += qSecond[facei]*sf[facei]/V[celli]; } } } @@ -728,6 +714,7 @@ void Foam::radiation::solarLoad::calculateQdiff Foam::radiation::solarLoad::solarLoad(const volScalarField& T) : radiationModel(typeName, T), + solarLoadBase(mesh_), solarCalc_(coeffs_, mesh_), dict_(coeffs_), qr_ @@ -762,7 +749,6 @@ Foam::radiation::solarLoad::solarLoad(const volScalarField& T) spectralDistribution_(), spectralDistributions_(), qprimaryRad_(0), - verticalDir_(Zero), nBands_(0), updateTimeIndex_(0), solidCoupled_(true), @@ -782,6 +768,7 @@ Foam::radiation::solarLoad::solarLoad ) : radiationModel(typeName, dict, T), + solarLoadBase(mesh_), solarCalc_(dict, mesh_), dict_(dict), qr_ @@ -816,7 +803,6 @@ Foam::radiation::solarLoad::solarLoad spectralDistribution_(), spectralDistributions_(), qprimaryRad_(0), - verticalDir_(Zero), nBands_(0), updateTimeIndex_(0), solidCoupled_(true), @@ -879,7 +865,7 @@ void Foam::radiation::solarLoad::calculate() const bool timeDependentLoad = solarCalc_.sunLoadModel() == solarCalculator::mSunLoadTimeDependent; - if (facesChanged || timeDependentLoad) + if (firstIter_ || facesChanged || timeDependentLoad) { // Reset Ru Ru_ = dimensionedScalar("Ru", dimMass/dimLength/pow3(dimTime), Zero); @@ -953,4 +939,18 @@ Foam::radiation::solarLoad::Ru() const } +const Foam::solarCalculator& +Foam::radiation::solarLoad::solarCalculatorRef() const +{ + return solarCalc_; +} + + +const Foam::faceShading& +Foam::radiation::solarLoad::faceShadingRef() const +{ + return hitFaces_(); +} + + // ************************************************************************* // diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.H b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.H index f657fac0bda4ba1c66439336107d396d349b8f4a..2ccb31c3d8d4b101c3dc0d0eccb1afa1f74e6dce 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.H +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoad.H @@ -99,6 +99,7 @@ SourceFiles #define radiation_solarLoad_H #include "radiationModel.H" +#include "solarLoadBase.H" #include "volFields.H" #include "faceShading.H" #include "faceReflecting.H" @@ -118,7 +119,8 @@ namespace radiation class solarLoad : - public radiationModel + public radiationModel, + public solarLoadBase { // Private Data @@ -153,9 +155,6 @@ class solarLoad //- Primary solar radiative heat flux per band [W/m2] PtrList<volScalarField> qprimaryRad_; - //- Vertical direction (default is g vector) - vector verticalDir_; - //- Number of bands label nBands_; @@ -262,6 +261,12 @@ public: { return qprimaryRad_[bandI]; } + + //- Return const reference to the solar calculator + virtual const solarCalculator& solarCalculatorRef() const; + + //- Return const reference to the face shading calculator + virtual const faceShading& faceShadingRef() const; }; diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.C new file mode 100644 index 0000000000000000000000000000000000000000..617e2778fbb510ef24f078c8cc0eba008dfa808f --- /dev/null +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.C @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "solarLoadBase.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace radiation +{ + defineTypeNameAndDebug(solarLoadBase, 0); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::radiation::solarLoadBase::solarLoadBase +( + const fvMesh& mesh +) +: + regIOobject + ( + IOobject + ( + solarLoadBase::typeName, + mesh.polyMesh::instance(), + mesh + ) + ) +{} + + +// ************************************************************************* // diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.H b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.H new file mode 100644 index 0000000000000000000000000000000000000000..5398c5a8b777f140ed2979212e0f8b9781bfb92f --- /dev/null +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/solarLoadBase.H @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 <http://www.gnu.org/licenses/>. + +Class + Foam::radiation::solarLoadBase + +Group + grpRadiationModels + +Description + Base class for solarLoad models. + +\*---------------------------------------------------------------------------*/ + +#ifndef radiation_solarLoadBase_H +#define radiation_solarLoadBase_H + +#include "regIOobject.H" +#include "fvMesh.H" +#include "solarCalculator.H" +#include "faceShading.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace radiation +{ + +/*---------------------------------------------------------------------------*\ + Class solarLoadBase Declaration +\*---------------------------------------------------------------------------*/ + +class solarLoadBase +: + public regIOobject +{ +public: + + //- Runtime type information + TypeName("solarLoadBase"); + + + // Constructors + + //- Construct + solarLoadBase(const fvMesh& mesh); + + + //- Destructor + virtual ~solarLoadBase() = default; + + + // Member Functions + + // Access + + //- Return const reference to the solar calculator + virtual const solarCalculator& solarCalculatorRef() const = 0; + + //- Return const reference to the face shading calculator + virtual const faceShading& faceShadingRef() const = 0; + + + // IO + + bool writeData(Foam::Ostream&) const + { + return true; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace radiation +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.C b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.C index c409ec246701e7709c827f61815471e3cf5a5801..35129a36430a5a2f20793f9aba43a8bbc0ed4b71 100644 --- a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.C +++ b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.C @@ -52,7 +52,8 @@ Foam::radiation::boundaryRadiationProperties::boundaryRadiationProperties Foam::GeometricMeshObject, boundaryRadiationProperties >(mesh), - radBoundaryPropertiesPtrList_(mesh.boundary().size()) + radBoundaryPropertiesPtrList_(mesh.boundary().size()), + radZonePropertiesPtrList_(mesh.faceZones().size()) { IOobject boundaryIO ( @@ -75,30 +76,110 @@ Foam::radiation::boundaryRadiationProperties::boundaryRadiationProperties // Model number of bands label nBands = radiation.nBands(); + // Load in dictionary const IOdictionary radiationDict(boundaryIO); - forAll(mesh.boundary(), patchi) - { - const polyPatch& pp = mesh.boundaryMesh()[patchi]; - const dictionary* subDictPtr = radiationDict.findDict(pp.name()); + wordHashSet matchedEntries; - if (subDictPtr) + // Match patches + { + const auto& pbm = mesh.boundaryMesh(); + for (const auto& pp : pbm) { - const dictionary& dict = *subDictPtr; + const label patchi = pp.index(); + + const auto* ePtr = radiationDict.findEntry(pp.name()); + + if (ePtr->isDict()) + { + radBoundaryPropertiesPtrList_.set + ( + patchi, + boundaryRadiationPropertiesPatch::New(ePtr->dict(), pp) + ); + + matchedEntries.insert(pp.name()); + + if + ( + nBands + != radBoundaryPropertiesPtrList_[patchi].nBands() + ) + { + FatalErrorInFunction + << "Radiation bands : " << nBands << nl + << "Bands on patch : " << patchi << " is " + << radBoundaryPropertiesPtrList_[patchi].nBands() + << abort(FatalError); + } + } + } + } + - radBoundaryPropertiesPtrList_[patchi].reset - ( - boundaryRadiationPropertiesPatch::New(dict, pp) - ); + // Match faceZones if any dictionary entries have not been used for + // patch matching. + // + // Note: radiation properties are hardcoded to take patch reference. + // Supply patch0 for now. + { + const auto& dummyRef = mesh.boundaryMesh()[0]; + + const auto& fzs = mesh.faceZones(); - if (nBands != radBoundaryPropertiesPtrList_[patchi]->nBands()) + for (const auto& fz : fzs) + { + const label zonei = fz.index(); + + if (!matchedEntries.found(fz.name())) { - FatalErrorInFunction - << "Radiation bands : " << nBands << nl - << "Bands on patch : " << patchi << " is " - << radBoundaryPropertiesPtrList_[patchi]->nBands() - << abort(FatalError); + // Note: avoid wildcard matches. Assume user explicitly + // provided information for faceZones. + const auto* ePtr = radiationDict.findEntry + ( + fz.name(), + keyType::LITERAL + ); + + // Skip face zones that are not used in boundary radiation + if (!ePtr) + { + continue; + } + + if (ePtr->isDict()) + { + const dictionary& dict = ePtr->dict(); + + radZonePropertiesPtrList_.set + ( + zonei, + boundaryRadiationPropertiesPatch::New + ( + dict, + dummyRef + ) + ); + + matchedEntries.insert(fz.name()); + + if + ( + nBands + != radZonePropertiesPtrList_[zonei].nBands() + ) + { + FatalErrorInFunction + << "Radiation bands : " << nBands << nl + << "Bands on zone : " << zonei << " is " + << radBoundaryPropertiesPtrList_ + [ + zonei + ].nBands() + << abort(FatalError); + } + } } } } @@ -117,9 +198,9 @@ Foam::radiation::boundaryRadiationProperties::emissivity scalarField* T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->e + return radBoundaryPropertiesPtrList_[patchi].e ( bandi, incomingDirection, @@ -140,17 +221,17 @@ Foam::radiation::boundaryRadiationProperties::emissivity Foam::scalar Foam::radiation::boundaryRadiationProperties::faceEmissivity ( const label patchi, - const label faceI, + const label facei, const label bandi, vector incomingDirection, scalar T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->e + return radBoundaryPropertiesPtrList_[patchi].e ( - faceI, + facei, bandi, incomingDirection, T @@ -176,9 +257,9 @@ Foam::radiation::boundaryRadiationProperties::absorptivity scalarField* T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->a + return radBoundaryPropertiesPtrList_[patchi].a ( bandi, incomingDirection, @@ -199,17 +280,17 @@ Foam::radiation::boundaryRadiationProperties::absorptivity Foam::scalar Foam::radiation::boundaryRadiationProperties::faceAbsorptivity ( const label patchi, - const label faceI, + const label facei, const label bandi, vector incomingDirection, scalar T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->a + return radBoundaryPropertiesPtrList_[patchi].a ( - faceI, + facei, bandi, incomingDirection, T @@ -235,9 +316,9 @@ Foam::radiation::boundaryRadiationProperties::transmissivity scalarField* T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->t + return radBoundaryPropertiesPtrList_[patchi].t ( bandi, incomingDirection, @@ -258,17 +339,17 @@ Foam::radiation::boundaryRadiationProperties::transmissivity Foam::scalar Foam::radiation::boundaryRadiationProperties::faceTransmissivity ( const label patchi, - const label faceI, + const label facei, const label bandi, vector incomingDirection, scalar T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->t + return radBoundaryPropertiesPtrList_[patchi].t ( - faceI, + facei, bandi, incomingDirection, T @@ -285,6 +366,43 @@ Foam::scalar Foam::radiation::boundaryRadiationProperties::faceTransmissivity } +Foam::tmp<Foam::scalarField> +Foam::radiation::boundaryRadiationProperties::zoneTransmissivity +( + const label zonei, + const labelUList& faceIDs, + const label bandi, + vector incomingDirection, + scalar T +) const +{ + if (radZonePropertiesPtrList_.set(zonei)) + { + auto tfld = tmp<scalarField>::New(faceIDs.size()); + auto& fld = tfld.ref(); + forAll(fld, i) + { + fld[i] = radZonePropertiesPtrList_[zonei].t + ( + faceIDs[i], + bandi, + incomingDirection, + T + ); + } + return tfld; + } + + FatalErrorInFunction + << "Zone : " << mesh().faceZones()[zonei].name() + << " is not found in the boundaryRadiationProperties. " + << "Please add it" + << exit(FatalError); + + return tmp<scalarField>::New(); +} + + Foam::tmp<Foam::scalarField> Foam::radiation::boundaryRadiationProperties::diffReflectivity ( @@ -294,9 +412,9 @@ Foam::radiation::boundaryRadiationProperties::diffReflectivity scalarField* T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->rDiff + return radBoundaryPropertiesPtrList_[patchi].rDiff ( bandi, incomingDirection, @@ -317,17 +435,17 @@ Foam::radiation::boundaryRadiationProperties::diffReflectivity Foam::scalar Foam::radiation::boundaryRadiationProperties::faceDiffReflectivity ( const label patchi, - const label faceI, + const label facei, const label bandi, vector incomingDirection, scalar T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->rDiff + return radBoundaryPropertiesPtrList_[patchi].rDiff ( - faceI, + facei, bandi, incomingDirection, T @@ -353,9 +471,9 @@ Foam::radiation::boundaryRadiationProperties::specReflectivity scalarField* T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->rSpec + return radBoundaryPropertiesPtrList_[patchi].rSpec ( bandi, incomingDirection, @@ -376,17 +494,17 @@ Foam::radiation::boundaryRadiationProperties::specReflectivity Foam::scalar Foam::radiation::boundaryRadiationProperties::faceSpecReflectivity ( const label patchi, - const label faceI, + const label facei, const label bandi, vector incomingDirection, scalar T ) const { - if (radBoundaryPropertiesPtrList_[patchi]) + if (radBoundaryPropertiesPtrList_.set(patchi)) { - return radBoundaryPropertiesPtrList_[patchi]->rSpec + return radBoundaryPropertiesPtrList_[patchi].rSpec ( - faceI, + facei, bandi, incomingDirection, T diff --git a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.H b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.H index 0e65a40e341aa14ccab306b04f1db1fadb1688c3..69dd3973d5b4d2640222e149043adfc330a202a2 100644 --- a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.H +++ b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationProperties.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2015-2018 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -63,12 +63,16 @@ class boundaryRadiationProperties boundaryRadiationProperties > { - // Private data + // Private Data - //- Ptr list of boundaryRadiationProperties - List<autoPtr<boundaryRadiationPropertiesPatch>> + //- Per patch the boundaryRadiationProperties + PtrList<boundaryRadiationPropertiesPatch> radBoundaryPropertiesPtrList_; + //- Per (face)zone the boundaryRadiationProperties + PtrList<boundaryRadiationPropertiesPatch> + radZonePropertiesPtrList_; + public: @@ -84,6 +88,22 @@ public: // Member Functions + //- Return identifiers of face zones activated for boundary radiation + const labelList faceZoneIds() const + { + DynamicList<label> ncZones; + + forAll(radZonePropertiesPtrList_, i) + { + if (radZonePropertiesPtrList_.test(i)) + { + ncZones.append(i); + } + } + + return ncZones; + } + //- Access boundary emissivity on patch tmp<scalarField> emissivity ( @@ -141,6 +161,20 @@ public: scalar T = 0 ) const; + // Specialisations for faceZones + + //- Access transmissivity on set of (internal) faces. Zone name only + // used to lookup the properties in boundaryRadiationProperties + tmp<scalarField> zoneTransmissivity + ( + const label zoneI, + const labelUList& faceIDs, // internal faces + const label bandI = 0, + vector incomingDirection = Zero, + scalar T = 0 + ) const; + + //- Access boundary diffuse reflectivity on patch tmp<scalarField> diffReflectivity ( diff --git a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.H b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.H index dc9a057da431c74e3fa363fe75eb0e9d496bfa37..afb1078a43a343705e223363ccc46808e2b28063 100644 --- a/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.H +++ b/src/thermophysicalModels/radiation/submodels/boundaryRadiationProperties/boundaryRadiationPropertiesPatch.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2015-2018 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -56,9 +56,7 @@ namespace radiation class boundaryRadiationPropertiesPatch { -private: - - // Private data + // Private Data //- Dictionary const dictionary dict_; @@ -67,7 +65,7 @@ private: const polyPatch& patch_; - // Private functions + // Private Member Functions //- Return nbr patch index label nbrPatchIndex() const; @@ -128,7 +126,7 @@ public: virtual ~boundaryRadiationPropertiesPatch() = default; - // Member functions + // Member Functions //- Return absorptionEmissionModel const wallAbsorptionEmissionModel& absorptionEmission() const; diff --git a/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.C b/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.C index e14c88bb813d92f442fc3b739166b30a3e24ad73..9cf0a65f6ba2bfaa81e393224db32facad4fe0de 100644 --- a/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.C +++ b/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2015-2021 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -333,4 +333,60 @@ void Foam::solarCalculator::correctDiffuseSolarRad() } +Foam::tmp<Foam::scalarField> Foam::solarCalculator::diffuseSolarRad +( + const vectorField& n +) const +{ + auto tload = tmp<scalarField>::New(n.size()); + auto& load = tload.ref(); + + forAll(n, facei) + { + const scalar cosEpsilon(gridUp_ & -n[facei]); + + scalar Ed = 0; + scalar Er = 0; + const scalar cosTheta(direction_ & -n[facei]); + + // Above the horizon + if (cosEpsilon == 0.0) + { + // Vertical walls + scalar Y = 0; + + if (cosTheta > -0.2) + { + Y = 0.55+0.437*cosTheta + 0.313*sqr(cosTheta); + } + else + { + Y = 0.45; + } + + Ed = C_*Y*directSolarRad_; + } + else + { + //Other than vertical walls + Ed = + C_ + * directSolarRad_ + * 0.5*(1.0 + cosEpsilon); + } + + // Ground reflected + Er = + directSolarRad_ + * (C_ + Foam::sin(beta_)) + * groundReflectivity_ + * 0.5*(1.0 - cosEpsilon); + + load[facei] = Ed + Er; + } + + return tload; +} + + // ************************************************************************* // diff --git a/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.H b/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.H index 0ed978ea713d5f41eba30acad5188e994edf806a..e82528d7ef39aa002540a017e057d0b4e924340f 100644 --- a/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.H +++ b/src/thermophysicalModels/radiation/submodels/solarCalculator/solarCalculator.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2015-2021 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -395,6 +395,11 @@ public: //- Correct diffuse solar irradiation void correctDiffuseSolarRad(); + //- Return the diffusive solar irradiation + //- for sunLoadModel = fairWeather + //- or for sunLoadModel = theoreticalMaximum + tmp<scalarField> diffuseSolarRad(const vectorField& n) const; + // Access diff --git a/tutorials/incompressible/pisoFoam/RAS/cavity/system/topoSetDict b/tutorials/incompressible/pisoFoam/RAS/cavity/system/topoSetDict index 801eafd409ce9243ff4dfc1791cc97c2a3249959..e20111f1e33e7566f38a388505f4abef6551855d 100644 --- a/tutorials/incompressible/pisoFoam/RAS/cavity/system/topoSetDict +++ b/tutorials/incompressible/pisoFoam/RAS/cavity/system/topoSetDict @@ -303,6 +303,15 @@ actions set cylinder1; } + { + name faceCell1c; + type faceSet; + action new; + source cellToFace; + option outside; + set cylinder1; + } + { name faceCylinder1; type faceSet; @@ -430,6 +439,15 @@ actions // flip true; // } + { + name cellToFaceZone1; + type faceZoneSet; + action new; + source cellToFaceZone; + set cylinder1; + flip true; + } + { name pointBox1; type pointSet; diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/plantCd b/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/Cd similarity index 97% rename from tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/plantCd rename to tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/Cd index 937ded772dac0f8396444ae7a3a327b8a6ca6467..60ea92267704891cb1d0d65717478c807f54dfef 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/plantCd +++ b/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/Cd @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class volScalarField; - object plantCd; + object Cd; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/leafAreaDensity b/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/LAD similarity index 97% rename from tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/leafAreaDensity rename to tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/LAD index 3b7b597b54c7d6efa5f27106c55ce763837eb27a..c6f2009fae11faad7791490fb03fc82c6556fa3d 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/leafAreaDensity +++ b/tutorials/verificationAndValidation/atmosphericModels/atmFlatTerrain/precursor/setups.orig/common/0.orig/LAD @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class volScalarField; - object leafAreaDensity; + object LAD; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/plantCd b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/Cd similarity index 100% rename from tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/plantCd rename to tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/Cd diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/leafAreaDensity b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/LAD similarity index 97% rename from tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/leafAreaDensity rename to tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/LAD index 3a65f8347cc5a2b2ae3b8fd95292a1dde84e4b5a..48b1a763066910d85ce3d6440d79ff3010d61ccc 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/leafAreaDensity +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/common/0.orig/LAD @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class volScalarField; - object leafAreaDensity; + object LAD; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/neutral/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/neutral/system/setFieldsDict index 725d7d2cbd54ce1991a55b73aaa8a09285087de1..4752c8f1a5efadc71d1e6b729bfe30aa5dff6077 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/neutral/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/neutral/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } ); diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyStable/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyStable/system/setFieldsDict index 2b64fb1997275b874c5692ccbe5306fad9ff95a5..aa8aecfb3fefdce0d007f199ce228c0a8135cc6d 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyStable/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyStable/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } ); diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyUnstable/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyUnstable/system/setFieldsDict index 49e7e54314fbf9ab96f2740b127638c36ecbbbf6..906afbfdccbbd2c403043dc107910e7ee7e55c1a 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyUnstable/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/slightlyUnstable/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } ); diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/stable/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/stable/system/setFieldsDict index 10593c0cac5b7c8cf6d33c0e489ab138102ce2a0..07a4f536e3703441ad6dfa9b86224132045675e4 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/stable/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/stable/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } ); diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/unstable/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/unstable/system/setFieldsDict index ed88dd4404ca19bb1ed8f308a5f0c4a3d7933cbd..54debfbeb78cbba21c7208213b304acb8e09ffb4 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/unstable/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/unstable/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } ); diff --git a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/veryStable/system/setFieldsDict b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/veryStable/system/setFieldsDict index a9a5a0cb5c125fdee1c025d43b28595d15091651..0d41b0c5085172d60f2ddbb53af539b66184851f 100644 --- a/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/veryStable/system/setFieldsDict +++ b/tutorials/verificationAndValidation/atmosphericModels/atmForestStability/setups.orig/veryStable/system/setFieldsDict @@ -17,8 +17,8 @@ FoamFile defaultFieldValues ( volScalarFieldValue qPlant 0 - volScalarFieldValue plantCd 0 - volScalarFieldValue leafAreaDensity 0 + volScalarFieldValue Cd 0 + volScalarFieldValue LAD 0 ); regions @@ -37,8 +37,8 @@ regions box (0 0 0) (200 200 18.2192); fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } @@ -47,8 +47,8 @@ regions patch bottom; fieldValues ( - volScalarFieldValue plantCd 0.2 - volScalarFieldValue leafAreaDensity 0.14 + volScalarFieldValue Cd 0.2 + volScalarFieldValue LAD 0.14 ); } );