diff --git a/src/regionFaModels/Make/files b/src/regionFaModels/Make/files index cd0717dbd83b2fc4ffd6e125939af84db33f3251..375a0c49d386c1d214c7ba7a06b6e03acb005c41 100644 --- a/src/regionFaModels/Make/files +++ b/src/regionFaModels/Make/files @@ -42,5 +42,6 @@ liquidFilm/kinematicThinFilm/kinematicThinFilm.C derivedFvPatchFields/filmShell/velocityFilmShellFvPatchVectorField.C functionObjects/setTimeStep/setTimeStepFaRegionsFunctionObject.C +functionObjects/surfaceCourantNumber/surfaceCourantNumber.C LIB = $(FOAM_LIBBIN)/libregionFaModels diff --git a/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.C b/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.C new file mode 100644 index 0000000000000000000000000000000000000000..49c7dc76c485b5b79409755a88af6d688856595f --- /dev/null +++ b/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.C @@ -0,0 +1,227 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2024 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 "surfaceCourantNumber.H" +#include "fvMesh.H" +#include "faMesh.H" +#include "areaFields.H" +#include "edgeFields.H" +#include "facEdgeIntegrate.H" +#include "zeroGradientFaPatchFields.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + defineTypeNameAndDebug(surfaceCourantNumber, 0); + addToRunTimeSelectionTable(functionObject, surfaceCourantNumber, dictionary); +} +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::functionObjects::surfaceCourantNumber::writeFileHeader(Ostream& os) +{ + writeHeader(os, "Surface Courant Number"); + + writeCommented(os, "Time"); + writeTabbed(os, "min"); + writeTabbed(os, "max"); + writeTabbed(os, "mean"); + os << endl; + + writtenHeader_ = true; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::functionObjects::surfaceCourantNumber::surfaceCourantNumber +( + const word& name, + const Time& runTime, + const dictionary& dict +) +: + fvMeshFunctionObject(name, runTime, dict), + writeFile(mesh_, name, typeName, dict), + resultName_("surfaceCo"), + phisName_("phis"), + rhoName_("rho") +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionObjects::surfaceCourantNumber::read(const dictionary& dict) +{ + if (!fvMeshFunctionObject::read(dict) || !writeFile::read(dict)) + { + return false; + } + + dict.readIfPresent("result", resultName_); + dict.readIfPresent("phis", phisName_); + dict.readIfPresent("rho", rhoName_); + + // Registry containing all finite-area meshes on the polyMesh + const auto* faRegistryPtr = faMesh::registry(mesh_); + + if (!faRegistryPtr) + { + FatalIOErrorInFunction(dict) + << "No finite-area object registry is available." + << abort(FatalIOError); + } + + word areaName; + + if (!dict.readIfPresent("area", areaName)) + { + wordList available = faRegistryPtr->sortedNames<faMesh>(); + if (!available.empty()) + { + areaName = available.front(); + } + } + + if (areaName.empty()) + { + FatalIOErrorInFunction(dict) + << "No name for finite-area mesh is available." + << abort(FatalIOError); + } + + faMeshPtr_ = std::shared_ptr<const faMesh> + ( + faRegistryPtr->cfindObject<faMesh>(areaName), + [](const faMesh*) { /* no-op deleter to avoid double deletion */ } + ); + + return true; +} + + +bool Foam::functionObjects::surfaceCourantNumber::execute() +{ + if (!faMeshPtr_->foundObject<edgeScalarField>(phisName_)) + { + WarningInFunction + << "No edge flux field is available. " + << "Name of provided edge flux field (phi): " << phisName_ + << endl; + + return false; + } + + const auto& phis = faMeshPtr_->lookupObject<edgeScalarField>(phisName_); + + tmp<areaScalarField::Internal> tCo = + (0.5*faMeshPtr_->time().deltaT()) + *fac::edgeSum(mag(phis))()() + /faMeshPtr_->S(); + + areaScalarField::Internal Co = tCo.ref(); + + if (Co.dimensions() == dimDensity) + { + Co /= faMeshPtr_->lookupObject<areaScalarField>(rhoName_); + } + + auto* resultPtr = faMeshPtr_->getObjectPtr<areaScalarField>(resultName_); + + if (!resultPtr) + { + resultPtr = new areaScalarField + ( + IOobject + ( + resultName_, + faMeshPtr_->time().timeName(), + *faMeshPtr_, + IOobjectOption() + ), + *faMeshPtr_, + dimensionedScalar(dimless, Zero), + faPatchFieldBase::zeroGradientType() + ); + regIOobject::store(resultPtr); + } + auto& result = *resultPtr; + + result.internalFieldRef() = tCo; + result.correctBoundaryConditions(); + + + const scalarMinMax limits(gMinMax(result)); + const scalar mean = gAverage(result); + + Log << "Surface Courant number: " + << "mean: " << mean + << " max: " << limits.max() + << endl; + + if (writeToFile()) + { + if (!writtenHeader_) writeFileHeader(file()); + + writeCurrentTime(file()); + file() + << token::TAB << limits.min() + << token::TAB << limits.max() + << token::TAB << mean + << endl; + } + + return true; +} + + +bool Foam::functionObjects::surfaceCourantNumber::write() +{ + const auto* result = faMeshPtr_->cfindObject<areaScalarField>(resultName_); + + if (!result) + { + return false; + } + + Log << type() << " " << name() << " write: " << result->name() << endl; + + result->write(); + + return true; +} + + +// ************************************************************************* // diff --git a/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.H b/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.H new file mode 100644 index 0000000000000000000000000000000000000000..8c64a01b627b1684ecb21fb6a55b65705d14b1c5 --- /dev/null +++ b/src/regionFaModels/functionObjects/surfaceCourantNumber/surfaceCourantNumber.H @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2024 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::functionObjects::surfaceCourantNumber + +Description + Computes the surface Courant number field at finite-area face centres. + + Operands: + \table + Operand | Type | Location + input | - | - + output file | dat <!-- + --> | postProcessing/\<FO\>/\<time\>/\<file\> + output field | areaScalarField | \<time\>/\<outField\> + \endtable + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + surfaceCourantNumber1 + { + // Mandatory entries + type surfaceCourantNumber; + libs (regionFaModels); + + // Optional entries + area <word>; + result <word>; + phis <word>; + rho <word>; + + // Inherited entries + ... + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + type | Type name: surfaceCourantNumber | word | yes | - + libs | Library name: regionFaModels | word | yes | - + area | Name of finite-area region | word | no | region0 + result | Name of result field | word | no | surfaceCo + phis | Name of edge flux field | word | no | phis + rho | Name of density field | word | no | rho + \endtable + + The inherited entries are elaborated in: + - \link fvMeshFunctionObject.H \endlink + - \link writeFile.H \endlink + +Note + - The \c surfaceCourantNumber calculates the Courant number at face centers, + rather than at edge centers. + +SourceFiles + surfaceCourantNumber.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionObjects_surfaceCourantNumber_H +#define functionObjects_surfaceCourantNumber_H + +#include "fvMeshFunctionObject.H" +#include "writeFile.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class faMesh; + +namespace functionObjects +{ + +/*---------------------------------------------------------------------------*\ + Class surfaceCourantNumber Declaration +\*---------------------------------------------------------------------------*/ + +class surfaceCourantNumber +: + public fvMeshFunctionObject, + public writeFile +{ + // Private Data + + //- Name of result field + word resultName_; + + //- Name of edge flux field + word phisName_; + + //- Name of density field + word rhoName_; + + //- Reference to finite-area object registry + std::shared_ptr<const faMesh> faMeshPtr_; + + + // Private Member Functions + + //- Output file header information + virtual void writeFileHeader(Ostream& os); + + +public: + + //- Runtime type information + TypeName("surfaceCourantNumber"); + + + // Constructors + + //- Construct from Time and dictionary + surfaceCourantNumber + ( + const word& name, + const Time& runTime, + const dictionary& dict + ); + + + //- Destructor + virtual ~surfaceCourantNumber() = default; + + + // Member Functions + + //- Read the surfaceCourantNumber data + virtual bool read(const dictionary&); + + //- Calculate the Courant number field and return true if successful + virtual bool execute(); + + //- Write the result field + virtual bool write(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionObjects +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/FOsurfaceCourantNumber b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/FOsurfaceCourantNumber new file mode 100644 index 0000000000000000000000000000000000000000..aa255d634cc555748fdf0a7abf4ad7515470176b --- /dev/null +++ b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/FOsurfaceCourantNumber @@ -0,0 +1,38 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v2406 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ + +surfaceCourantNumber1 +{ + // Mandatory entries + type surfaceCourantNumber; + libs (regionFaModels); + + // Optional entries + area region0; + result surfaceCourantNumberField; + rho rho; + phis phis; + + // Inherited entries + writePrecision 6; + writeToFile true; + useUserTime true; + + region region0; + enabled true; + log true; + timeStart 0; + timeEnd 1000; + executeControl timeStep; + executeInterval 1; + writeControl writeTime; + writeInterval -1; +} + + +// ************************************************************************* // diff --git a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict index 70074e2c4af941e8eab61c7aad5dcad49090fea4..02c1b5c8b59d5852b32512b6e49cb2d95299a41f 100644 --- a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict +++ b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/controlDict @@ -50,5 +50,9 @@ maxCo 5; maxDeltaT 0.1; +functions +{ + #include "FOsurfaceCourantNumber" +} // ************************************************************************* //