From f37942b388b18d33af09d01f66449d3fda5367d3 Mon Sep 17 00:00:00 2001 From: mattijs Date: Thu, 28 Feb 2019 17:04:46 +0000 Subject: [PATCH] ENH: potentialFoam: add region functionality. Fixes #1223. Also implements combination of -region and -dry-run --- .../basic/potentialFoam/potentialFoam.C | 1 + .../basic/potentialFoam/potentialFoam.C.orig | 254 ++++++++++++++++++ src/OpenFOAM/include/createMesh.H | 26 +- .../simplifiedDynamicFvMesh.C | 4 +- .../simplifiedDynamicFvMesh.H | 7 +- .../simplifiedDynamicFvMeshTemplates.C | 7 +- .../columnFvMesh/columnFvMesh.C | 43 ++- .../columnFvMesh/columnFvMesh.H | 20 +- 8 files changed, 332 insertions(+), 30 deletions(-) create mode 100644 applications/solvers/basic/potentialFoam/potentialFoam.C.orig diff --git a/applications/solvers/basic/potentialFoam/potentialFoam.C b/applications/solvers/basic/potentialFoam/potentialFoam.C index e2e8702280..cdada0c353 100644 --- a/applications/solvers/basic/potentialFoam/potentialFoam.C +++ b/applications/solvers/basic/potentialFoam/potentialFoam.C @@ -132,6 +132,7 @@ int main(int argc, char *argv[]) "Execute functionObjects" ); + #include "addRegionOption.H" #include "addCheckCaseOptions.H" #include "setRootCaseLists.H" #include "createTime.H" diff --git a/applications/solvers/basic/potentialFoam/potentialFoam.C.orig b/applications/solvers/basic/potentialFoam/potentialFoam.C.orig new file mode 100644 index 0000000000..ec1c198493 --- /dev/null +++ b/applications/solvers/basic/potentialFoam/potentialFoam.C.orig @@ -0,0 +1,254 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +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 . + +Application + potentialFoam + +Group + grpBasicSolvers + +Description + Potential flow solver which solves for the velocity potential, to + calculate the flux-field, from which the velocity field is obtained by + reconstructing the flux. + + \heading Solver details + The potential flow solution is typically employed to generate initial fields + for full Navier-Stokes codes. The flow is evolved using the equation: + + \f[ + \laplacian \Phi = \div(\vec{U}) + \f] + + Where: + \vartable + \Phi | Velocity potential [m2/s] + \vec{U} | Velocity [m/s] + \endvartable + + The corresponding pressure field could be calculated from the divergence + of the Euler equation: + + \f[ + \laplacian p + \div(\div(\vec{U}\otimes\vec{U})) = 0 + \f] + + but this generates excessive pressure variation in regions of large + velocity gradient normal to the flow direction. A better option is to + calculate the pressure field corresponding to velocity variation along the + stream-lines: + + \f[ + \laplacian p + \div(\vec{F}\cdot\div(\vec{U}\otimes\vec{U})) = 0 + \f] + where the flow direction tensor \f$\vec{F}\f$ is obtained from + \f[ + \vec{F} = \hat{\vec{U}}\otimes\hat{\vec{U}} + \f] + + \heading Required fields + \plaintable + U | Velocity [m/s] + \endplaintable + + \heading Optional fields + \plaintable + p | Kinematic pressure [m2/s2] + Phi | Velocity potential [m2/s] + | Generated from p (if present) or U if not present + \endplaintable + + \heading Options + \plaintable + -writep | write the Euler pressure + -writePhi | Write the final velocity potential + -initialiseUBCs | Update the velocity boundaries before solving for Phi + \endplaintable + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "pisoControl.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "Potential flow solver which solves for the velocity potential" + ); + + argList::addOption + ( + "pName", + "pName", + "Name of the pressure field" + ); + + argList::addBoolOption + ( + "initialiseUBCs", + "Initialise U boundary conditions" + ); + + argList::addBoolOption + ( + "writePhi", + "Write the final velocity potential field" + ); + + argList::addBoolOption + ( + "writep", + "Calculate and write the Euler pressure field" + ); + + argList::addBoolOption + ( + "withFunctionObjects", + "Execute functionObjects" + ); + + #include "addCheckCaseOptions.H" + #include "setRootCaseLists.H" + #include "createTime.H" + #include "createMesh.H" + + pisoControl potentialFlow(mesh, "potentialFlow"); + + #include "createFields.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info<< nl << "Calculating potential flow" << endl; + + // Since solver contains no time loop it would never execute + // function objects so do it ourselves + runTime.functionObjects().start(); + + MRF.makeRelative(phi); + adjustPhi(phi, U, p); + + // Non-orthogonal velocity potential corrector loop + while (potentialFlow.correctNonOrthogonal()) + { + fvScalarMatrix PhiEqn + ( + fvm::laplacian(dimensionedScalar("1", dimless, 1), Phi) + == + fvc::div(phi) + ); + + PhiEqn.setReference(PhiRefCell, PhiRefValue); + PhiEqn.solve(); + + if (potentialFlow.finalNonOrthogonalIter()) + { + phi -= PhiEqn.flux(); + } + } + + MRF.makeAbsolute(phi); + + Info<< "Continuity error = " + << mag(fvc::div(phi))().weightedAverage(mesh.V()).value() + << endl; + + U = fvc::reconstruct(phi); + U.correctBoundaryConditions(); + + Info<< "Interpolated velocity error = " + << (sqrt(sum(sqr(fvc::flux(U) - phi)))/sum(mesh.magSf())).value() + << endl; + + // Write U and phi + U.write(); + phi.write(); + + // Optionally write Phi + if (args.found("writePhi")) + { + Phi.write(); + } + + // Calculate the pressure field from the Euler equation + if (args.found("writep")) + { + Info<< nl << "Calculating approximate pressure field" << endl; + + label pRefCell = 0; + scalar pRefValue = 0.0; + setRefCell + ( + p, + potentialFlow.dict(), + pRefCell, + pRefValue + ); + + // Calculate the flow-direction filter tensor + volScalarField magSqrU(magSqr(U)); + volSymmTensorField F(sqr(U)/(magSqrU + SMALL*average(magSqrU))); + + // Calculate the divergence of the flow-direction filtered div(U*U) + // Filtering with the flow-direction generates a more reasonable + // pressure distribution in regions of high velocity gradient in the + // direction of the flow + volScalarField divDivUU + ( + fvc::div + ( + F & fvc::div(phi, U), + "div(div(phi,U))" + ) + ); + + // Solve a Poisson equation for the approximate pressure + while (potentialFlow.correctNonOrthogonal()) + { + fvScalarMatrix pEqn + ( + fvm::laplacian(p) + divDivUU + ); + + pEqn.setReference(pRefCell, pRefValue); + pEqn.solve(); + } + + p.write(); + } + + runTime.functionObjects().end(); + + runTime.printExecutionTime(Info); + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/include/createMesh.H b/src/OpenFOAM/include/createMesh.H index 06d07591b2..da6fbbccd9 100644 --- a/src/OpenFOAM/include/createMesh.H +++ b/src/OpenFOAM/include/createMesh.H @@ -1,4 +1,5 @@ Foam::autoPtr meshPtr(nullptr); +Foam::word regionName = Foam::fvMesh::defaultRegion; if (args.found("dry-run") || args.found("dry-run-write")) { @@ -6,10 +7,16 @@ if (args.found("dry-run") || args.found("dry-run-write")) << "Operating in 'dry-run' mode: case will run for 1 time step. " << "All checks assumed OK on a clean exit" << Foam::endl; + // Allow region in combination with dry-run + args.readIfPresent("region", regionName); + Foam::FieldBase::allowConstructFromLargerSize = true; // Create a simplified 1D mesh and attempt to re-create boundary conditions - meshPtr.reset(new Foam::simplifiedMeshes::columnFvMesh(runTime)); + meshPtr.reset + ( + new Foam::simplifiedMeshes::columnFvMesh(runTime, regionName) + ); // Stop after 1 iteration of the simplified mesh @@ -30,9 +37,18 @@ if (args.found("dry-run") || args.found("dry-run-write")) } else { - Foam::Info - << "Create mesh for time = " - << runTime.timeName() << Foam::nl << Foam::endl; + if (args.readIfPresent("region", regionName)) + { + Foam::Info + << "Create mesh " << regionName << " for time = " + << runTime.timeName() << Foam::nl << Foam::endl; + } + else + { + Foam::Info + << "Create mesh for time = " + << runTime.timeName() << Foam::nl << Foam::endl; + } meshPtr.reset ( @@ -40,7 +56,7 @@ else ( Foam::IOobject ( - Foam::fvMesh::defaultRegion, + regionName, runTime.timeName(), runTime, Foam::IOobject::MUST_READ diff --git a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.C b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.C index 31a0ea8ab4..df47e836be 100644 --- a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.C +++ b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.C @@ -67,14 +67,14 @@ Foam::simplifiedMeshes::simplifiedDynamicFvMeshBase::New if (cstrIter.found()) { Info<< "Selecting simplified mesh model " << modelType << endl; - return autoPtr(cstrIter()(io.time())); + return autoPtr(cstrIter()(io.time(), io.name())); } } Info<< "Selecting simplified mesh model " << staticFvMesh::typeName << endl; return autoPtr ( - new SimplifiedDynamicFvMesh(io.time()) + new SimplifiedDynamicFvMesh(io.time(), io.name()) ); } diff --git a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.H b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.H index f8ac3c722d..4925fd1e12 100644 --- a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.H +++ b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMesh.H @@ -67,9 +67,10 @@ public: dynamicFvMesh, time, ( - const Time& runTime + const Time& runTime, + const word& regionName ), - (runTime) + (runTime, regionName) ); @@ -101,7 +102,7 @@ public: ClassNameNoDebug(DynamicMeshType::typeName_.c_str()); //- Constructor - SimplifiedDynamicFvMesh(const Time& runTime); + SimplifiedDynamicFvMesh(const Time& runTime, const word& regionName); //- Update the mesh for both mesh motion and topology change virtual bool update() diff --git a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMeshTemplates.C b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMeshTemplates.C index 37209b20bd..ac9429597f 100644 --- a/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMeshTemplates.C +++ b/src/dynamicFvMesh/simplifiedDynamicFvMesh/simplifiedDynamicFvMeshTemplates.C @@ -29,16 +29,17 @@ template Foam::simplifiedMeshes::SimplifiedDynamicFvMesh:: SimplifiedDynamicFvMesh ( - const Time& runTime + const Time& runTime, + const word& regionName ) : simplifiedDynamicFvMeshBase(), - columnFvMeshInfo(runTime), + columnFvMeshInfo(runTime, regionName), DynamicMeshType ( IOobject ( - fvMesh::defaultRegion, + regionName, runTime.constant(), runTime, IOobject::NO_READ, // Do not read any existing mesh diff --git a/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.C b/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.C index 36f7283e0e..bcca22f366 100644 --- a/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.C +++ b/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.C @@ -62,7 +62,7 @@ bool Foam::simplifiedMeshes::columnFvMeshInfo::setPatchEntries ( "boundary", localInstance_, - polyMesh::meshSubDir, + regionPrefix_ + polyMesh::meshSubDir, runTime, IOobject::MUST_READ, IOobject::NO_WRITE, @@ -97,7 +97,12 @@ bool Foam::simplifiedMeshes::columnFvMeshInfo::setPatchEntries else { // No boundary file - try reading from a field - IOobjectList objects(runTime, runTime.timeName()); + IOobjectList objects + ( + runTime, + runTime.timeName(), + (regionName_ == fvMesh::defaultRegion ? "" : regionName_) + ); if (objects.empty()) { @@ -202,7 +207,7 @@ void Foam::simplifiedMeshes::columnFvMeshInfo::initialise(const Time& runTime) ( "points", localInstance_, - polyMesh::meshSubDir, + regionPrefix_ + polyMesh::meshSubDir, runTime, IOobject::MUST_READ, IOobject::NO_WRITE, @@ -371,12 +376,7 @@ void Foam::simplifiedMeshes::columnFvMeshInfo::addLocalPatches if (debug) { - Pout<< "patches:" << nl << endl; - forAll(patches, patchi) - { - Pout<< "patch: " << patches[patchi]->name() << nl - << *patches[patchi] << endl; - } + Pout<< "patches:" << nl << mesh.boundaryMesh() << endl; } } @@ -400,13 +400,24 @@ void Foam::simplifiedMeshes::columnFvMeshInfo::initialiseZones(fvMesh& mesh) // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::simplifiedMeshes::columnFvMeshInfo::columnFvMeshInfo(const Time& runTime) +Foam::simplifiedMeshes::columnFvMeshInfo::columnFvMeshInfo +( + const Time& runTime, + const word& regionName +) : + regionName_(regionName), + regionPrefix_ + ( + regionName_ == fvMesh::defaultRegion + ? "" + : regionName_ + '/' + ), localInstance_ ( runTime.findInstance ( - polyMesh::meshSubDir, + regionPrefix_ + polyMesh::meshSubDir, "boundary", IOobject::READ_IF_PRESENT ) @@ -428,14 +439,18 @@ Foam::simplifiedMeshes::columnFvMeshInfo::columnFvMeshInfo(const Time& runTime) } -Foam::simplifiedMeshes::columnFvMesh::columnFvMesh(const Time& runTime) +Foam::simplifiedMeshes::columnFvMesh::columnFvMesh +( + const Time& runTime, + const word& regionName +) : - columnFvMeshInfo(runTime), + columnFvMeshInfo(runTime, regionName), simplifiedFvMesh ( IOobject ( - fvMesh::defaultRegion, + regionName, runTime.constant(), runTime, IOobject::NO_READ, // Do not read any existing mesh diff --git a/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.H b/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.H index 01b65bdd9f..6347b5c8ed 100644 --- a/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.H +++ b/src/finiteVolume/fvMesh/simplifiedFvMesh/columnFvMesh/columnFvMesh.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -73,6 +73,12 @@ protected: // Protected data + //- Region of existing mesh + const word regionName_; + + //- Additional prefix for region. Empty if default region + const fileName regionPrefix_; + //- Location of existing mesh (if present) const word localInstance_; @@ -118,7 +124,11 @@ public: ClassName("columnFvMeshInfo"); // Constructor - columnFvMeshInfo(const Time& runTime); + columnFvMeshInfo + ( + const Time& runTime, + const word& regionName + ); }; @@ -134,7 +144,11 @@ public: TypeName("columnFvMesh"); //- Constructor - columnFvMesh(const Time& runTime); + columnFvMesh + ( + const Time& runTime, + const word& regionName = fvMesh::defaultRegion + ); };