Commit 84270ed6 authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: new PDRblockMesh mesh generation utility (issue #1216)

- While a rectilinear mesh can be created with blockMesh, not every mesh
  created with blockMesh will satisfy the requirements for being a
  rectilinear mesh.

  This alternative to blockMesh uses a single block that is aligned
  with the xy-z directions and specifications of the control points,
  mesh divisions and expansion ratios. For example,

    x
    {
        points  ( -13.28 -0.10 6.0 19.19 );
        nCells  (  10  12 10 );
        ratios  ( 0.2   1  5 );
    }

    y { ... }
    z { ... }

  With only one block, the boundary patch definition is simple and the
  canonical face number is used directly. For example,

    inlet
    {
        type    patch;
        faces   ( 0 );
    }
    outlet
    {
        type    patch;
        faces   ( 1 );
    }

    sides
    {
        type    patch;
        faces   ( 2 3 );
    }

    ...

- After a mesh is defined, it is trivial to retrieve mesh-related
  information such as cell-volume, cell-centres for any i-j-k location
  without an actual polyMesh.

STYLE: remove -noFunctionObjects from blockMesh

- no time loop, so function objects cannot be triggered anyhow.
parent 94a3d024
Test-PDRblockMesh.C
EXE = $(FOAM_USER_APPBIN)/Test-PDRblockMesh
EXE_INC = \
-DFULLDEBUG \
-I$(LIB_SRC)/mesh/blockMesh/lnInclude
EXE_LIBS = \
-lblockMesh
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Test accessors for PDRblock
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "PDRblock.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::noFunctionObjects();
argList::addOption
(
"dict",
"file",
"Alternative dictionary for the PDRblockMesh description"
);
#include "setRootCase.H"
#include "createTime.H"
const word dictName("PDRblockMeshDict");
#include "setSystemRunTimeDictionaryIO.H"
Info<< "Reading " << dictName << nl << endl;
IOdictionary meshDict(dictIO);
PDRblock mesh(meshDict, true);
// Write summary
Info<< "----------------" << nl
<< "Mesh Information" << nl
<< "----------------" << nl
<< " " << "bounds: " << mesh.bounds() << nl
<< " " << "nPoints: " << mesh.nPoints()
<< " " << (mesh.sizes() + labelVector::one) << nl
<< " " << "nCells: " << mesh.nCells()
<< " " << mesh.sizes() << nl
<< " " << "nFaces: " << mesh.nFaces() << nl
<< " " << "nInternalFaces: " << mesh.nInternalFaces() << nl;
Info<< "----------------" << nl
<< "Addressing" << nl
<< "----------------" << nl
<< " " << "volume: " << mesh.bounds().volume() << nl
<< " " << "avg-vol: "<< (mesh.bounds().volume() / mesh.nCells()) << nl;
Info<< nl << "Check sizes: " << mesh.bounds().span() << nl;
for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
{
// Three different ways of getting the same information
// not all are equally efficient
scalar totalWidth = 0;
// Using location
forAll(mesh.grid()[cmpt], i)
{
totalWidth += mesh.grid()[cmpt].width(i);
}
Info<< vector::componentNames[cmpt] << " min/max "
<< minMax(mesh.grid()[cmpt])
<< ' ' << mesh.grid()[cmpt].first()
<< ' ' << mesh.grid()[cmpt].last()
<< " " << mesh.grid()[cmpt].size() << " cells" << nl;
// Use global (i,j,k) accessors, with mid-mesh for other directions
const label nx = mesh.sizes().x() / (cmpt == vector::X ? 1 : 2);
const label ny = mesh.sizes().y() / (cmpt == vector::Y ? 1 : 2);
const label nz = mesh.sizes().z() / (cmpt == vector::Z ? 1 : 2);
scalar totalSpan = 0;
scalar totalDelta = 0;
switch (cmpt)
{
case vector::X:
{
for (label i=0; i < nx; ++i)
{
totalSpan += mesh.span(i, ny, nz).x();
totalDelta += mesh.dx(i);
}
}
break;
case vector::Y:
{
for (label j=0; j < ny; ++j)
{
totalSpan += mesh.span(nx, j, nz).y();
totalDelta += mesh.dy(j);
}
}
break;
case vector::Z:
{
for (label k=0; k < nz; ++k)
{
totalSpan += mesh.span(nx, ny, k).z();
totalDelta += mesh.dz(k);
}
}
break;
}
Info<< " width = " << totalWidth << " delta = " << totalDelta
<< " span = " << totalSpan << nl;
}
{
const labelVector mid = mesh.sizes() / 2;
Info<< nl << "Mid-mesh information at " << mid << nl
<< " centre = " << mesh.C(mid) << nl
<< " volume = " << mesh.V(mid) << nl
<< " length = " << mesh.width(mid) << nl;
}
Info<< nl;
// Fatal with FULLDEBUG
{
const bool throwingError = FatalError.throwExceptions();
const label nx = mesh.sizes().x();
const label ny = mesh.sizes().y();
const label nz = mesh.sizes().z();
// Here we get error in x-y-z order
try
{
mesh.checkIndex(nx, ny, nz);
}
catch (const Foam::error& err)
{
Info<< nl << "Expected: Caught accesor error\n "
<< err.message().c_str() << nl;
}
// No order for the error since it is called parameter-wise
try
{
Info<< "centre at mesh(nx, ny, nz) = "
<< mesh.C(mesh.sizes()) << nl;
}
catch (const Foam::error& err)
{
Info<< nl << "Expected: Caught accesor error\n "
<< err.message().c_str() << nl;
}
// Sizing error
try
{
mesh.checkSizes(labelVector(nx+1, ny, nz));
}
catch (const Foam::error& err)
{
Info<< nl << "Expected: Caught sizing error\n "
<< err.message().c_str() << nl;
}
try
{
mesh.checkSizes(labelMax/4);
}
catch (const Foam::error& err)
{
Info<< nl << "Expected: Caught sizing error\n "
<< err.message().c_str() << nl;
}
FatalError.throwExceptions(throwingError);
}
Info<< "\nEnd\n" << nl;
return 0;
}
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object PDRblockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Point scaling (optional)
scale 1.0;
x
{
points ( -13.28 -0.10 6.0 19.19 );
nCells ( 10 12 10 );
ratios ( -5.16 1 5.16 );
}
y
{
points ( -12.98 0 5.50 18.48 );
nCells ( 10 11 10 );
ratios ( -5.16 1 5.16 );
}
z
{
points ( 0.00 4.80 17.26 );
nCells ( 10 10 );
ratios ( 1 5.16 );
}
defaultPatch
{
name walls;
type wall;
}
// Faces: 0=x-min, 1=x-max, 2=y-min, 3=y-max, 4=z-min, 5=z-max
boundary
(
outer
{
type patch;
faces ( 0 1 2 3 5 );
}
mergingFaces
{
type wall;
faces ();
}
blockedFaces
{
type wall;
faces ();
}
ground
{
type wall;
faces ( 4 );
}
);
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
libs ("libblockMesh.so");
application PDRblockMesh;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0;
deltaT 0;
writeControl timeStep;
writeInterval 1;
purgeWrite 0;
writeFormat ascii;
writePrecision 8;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{}
gradSchemes
{}
divSchemes
{}
laplacianSchemes
{}
interpolationSchemes
{}
snGradSchemes
{}
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //
PDRblockMesh.C
EXE = $(FOAM_APPBIN)/PDRblockMesh
EXE_INC = \
-I$(LIB_SRC)/mesh/blockMesh/lnInclude
EXE_LIBS = \
-lblockMesh
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
PDRblockMesh
Group
grpMeshGenerationUtilities
Description
A specialized single-block mesh generator for a rectilinear mesh
in x-y-z.
Uses the mesh description found in
- \c system/PDRblockMeshDict
Usage
\b PDRblockMesh [OPTION]
Options:
- \par -dict \<filename\>
Alternative dictionary for the mesh description.
- \par -noClean
Do not remove any existing polyMesh/ directory or files
- \par -time
Write resulting mesh to a time directory (instead of constant)
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "polyMesh.H"
#include "PDRblock.H"
#include "Time.H"
#include "IOdictionary.H"
#include "OSspecific.H"
#include "OFstream.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"A block mesh generator for a rectilinear mesh in x-y-z.\n"
" The ordering of vertex and face labels within a block as shown "
"below.\n"
" For the local vertex numbering in the sequence 0 to 7:\n"
" Faces 0, 1 == x-min, x-max.\n"
" Faces 2, 3 == y-min, y-max.\n"
" Faces 4, 5 == z-min, z-max.\n"
"\n"
" 7 ---- 6\n"
" f5 |\\ |\\ f3\n"
" | | 4 ---- 5 \\\n"
" | 3 |--- 2 | \\\n"
" | \\| \\| f2\n"
" f4 0 ---- 1\n"
" Y Z\n"
" \\ | f0 ------ f1\n"
" \\|\n"
" O--- X\n"
);
argList::noParallel();
argList::noFunctionObjects();
argList::addBoolOption
(
"noClean",
"Do not remove any existing polyMesh/ directory or files"
);
argList::addOption
(
"dict",
"file",
"Alternative dictionary for the PDRblockMesh description"
);
argList::addOption
(
"time",
"time",
"Specify a time to write mesh to (default: constant)"
);
#include "setRootCase.H"
#include "createTime.H"
// Instance for resulting mesh
bool useTime = false;
word meshInstance(runTime.constant());
if
(
args.readIfPresent("time", meshInstance)
&& runTime.constant() != meshInstance
)
{
// Verify that the value is actually good
scalar timeValue;
useTime = readScalar(meshInstance, timeValue);
if (!useTime)
{
FatalErrorInFunction
<< "Bad input value: " << meshInstance
<< "Should be a scalar or 'constant'"
<< nl << endl
<< exit(FatalError);
}
}
const word dictName("PDRblockMeshDict");
#include "setSystemRunTimeDictionaryIO.H"
IOdictionary meshDict(dictIO);
Info<< "Creating PDRblockMesh from "
<< runTime.relativePath(dictIO.objectPath()) << endl;
PDRblock blkMesh(meshDict, true);
// Instance for resulting mesh
if (useTime)
{
Info<< "Writing polyMesh to " << meshInstance << nl << endl;
// Make sure that the time is seen to be the current time.
// This is the logic inside regIOobject that resets the instance
// to the current time before writing
runTime.setTime(instant(meshInstance), 0);
}
if (!args.found("noClean"))
{
const fileName polyMeshPath
(
runTime.path()/meshInstance/polyMesh::meshSubDir
);
if (exists(polyMeshPath))
{
Info<< "Deleting polyMesh directory "
<< runTime.relativePath(polyMeshPath) << endl;
rmDir(polyMeshPath);