Compare commits

..

6 Commits

Author SHA1 Message Date
1307c4eb2e ENH: Propagated AMI API code changes across dependant code 2024-05-03 17:26:00 +01:00
de8dd7a5cf WIP: AMI - knock out connections with invalid interpolated delta vectors 2024-05-03 17:13:23 +01:00
a083ebb7bf ENH: AMI - propagate lowWeightOption 2024-05-03 17:08:01 +01:00
279abca7fa ENH: cyclicAMI - enable user to select low-weight correction
Example

    lowWeightOption assign;

Options:

- none   : no-op
- assign : set value when sum of weights < threshold (same as v2312) [DEFAULT]
- blend  : linear blend of AMI interpolated value plus (1 - sum_of_weights)
           times (supplied) default value
2024-05-03 16:37:33 +01:00
8c89c8f417 ENH: Refactored low-level AMI code to use new field-based ops 2024-05-03 16:10:52 +01:00
e44184e626 ENH: AMI - added new set of field-based AMI operations 2024-05-03 16:06:22 +01:00
172 changed files with 2018 additions and 5120 deletions

View File

@ -145,7 +145,6 @@ Usage
#include "hexRef8Data.H"
#include "regionProperties.H"
#include "polyMeshTools.H"
#include "subsetAdjacency.H"
using namespace Foam;
@ -195,56 +194,21 @@ tmp<volScalarField> createScalarField
}
// Calculate band of mesh
// label getBand(const labelUList& owner, const labelUList& neighbour)
// {
// label bandwidth = 0;
//
// forAll(neighbour, facei)
// {
// const label width = neighbour[facei] - owner[facei];
//
// if (bandwidth < width)
// {
// bandwidth = width;
// }
// }
// return bandwidth;
// }
// Calculate band and profile of matrix. Profile is scalar to avoid overflow
Tuple2<label, scalar> getBand
(
const CompactListList<label>& mat
)
// Calculate band of matrix
label getBand(const labelList& owner, const labelList& neighbour)
{
Tuple2<label, scalar> metrics(0, 0);
label band = 0;
auto& bandwidth = metrics.first();
auto& profile = metrics.second();
forAll(mat, celli)
forAll(neighbour, facei)
{
const auto& neighbours = mat[celli];
label diff = neighbour[facei] - owner[facei];
const label nNbr = neighbours.size();
if (nNbr)
if (diff > band)
{
// Max distance
const label width = (neighbours[nNbr-1] - celli);
if (bandwidth < width)
{
bandwidth = width;
}
profile += scalar(width);
band = diff;
}
}
return metrics;
return band;
}
@ -253,36 +217,28 @@ void getBand
(
const bool calculateIntersect,
const label nCells,
const labelUList& owner,
const labelUList& neighbour,
const labelList& owner,
const labelList& neighbour,
label& bandwidth,
scalar& profile, // scalar to avoid overflow
scalar& sumSqrIntersect // scalar to avoid overflow
)
{
labelList cellBandwidth(nCells, Foam::zero{});
bandwidth = 0;
scalarField nIntersect(nCells, Foam::zero{});
forAll(neighbour, facei)
{
const label own = owner[facei];
const label nei = neighbour[facei];
label own = owner[facei];
label nei = neighbour[facei];
// Note: mag not necessary for correct (upper-triangular) ordering.
const label width = nei - own;
if (cellBandwidth[nei] < width)
{
cellBandwidth[nei] = width;
if (bandwidth < width)
{
bandwidth = width;
}
}
label diff = nei-own;
cellBandwidth[nei] = max(cellBandwidth[nei], diff);
}
bandwidth = max(cellBandwidth);
// Do not use field algebra because of conversion label to scalar
profile = 0;
for (const label width : cellBandwidth)
@ -290,16 +246,14 @@ void getBand
profile += scalar(width);
}
sumSqrIntersect = 0;
sumSqrIntersect = 0.0;
if (calculateIntersect)
{
scalarField nIntersect(nCells, Foam::zero{});
forAll(nIntersect, celli)
{
for (label colI = celli-cellBandwidth[celli]; colI <= celli; colI++)
{
nIntersect[colI] += scalar(1);
nIntersect[colI] += 1.0;
}
}
@ -721,8 +675,9 @@ CompactListList<label> regionRenumber
forAll(regionCellOrder, regioni)
{
// Info<< " region " << regioni << " starts at "
// << regionCellOrder.localStart(regioni) << nl;
// Info<< " region " << regioni
// << " starts at " << regionCellOrder.localStart(regioni)
// << nl;
// No parallel communication
const bool oldParRun = UPstream::parRun(false);
@ -748,42 +703,27 @@ CompactListList<label> regionRenumber
{
timer.resetTimeIncrement();
// Create adjacency matrix of the full mesh and subset subsequently.
// This is more efficient than creating adjacency matrices of
// sub-meshes.
// No parallel communication
const bool oldParRun = UPstream::parRun(false);
// The local connectivity of the full (non-subsetted) mesh
CompactListList<label> meshCellCells;
globalMeshData::calcCellCells(mesh, meshCellCells);
UPstream::parRun(oldParRun); // Restore parallel state
timings[TimingType::CELL_CELLS] += timer.timeIncrement();
// For the respective subMesh selections
bitSet subsetCells(mesh.nCells());
forAll(regionCellOrder, regioni)
{
// Info<< " region " << regioni << " starts at "
// << regionCellOrder.localStart(regioni) << nl;
subsetCells = false;
subsetCells.set(regionCellOrder[regioni]);
// Connectivity of local sub-mesh
labelList cellMap;
CompactListList<label> subCellCells =
subsetAdjacency(subsetCells, meshCellCells, cellMap);
timings[TimingType::CELL_CELLS] += timer.timeIncrement();
// Info<< " region " << regioni
// << " starts at " << regionCellOrder.localStart(regioni)
// << nl;
// No parallel communication
const bool oldParRun = UPstream::parRun(false);
labelList subCellOrder = method.renumber(subCellCells);
// Connectivity of local sub-mesh
CompactListList<label> cellCells;
labelList cellMap = globalMeshData::calcCellCells
(
mesh,
regionCellOrder[regioni],
cellCells
);
timings[TimingType::CELL_CELLS] += timer.timeIncrement();
labelList subCellOrder = method.renumber(cellCells);
UPstream::parRun(oldParRun); // Restore parallel state
@ -895,10 +835,10 @@ int main(int argc, char *argv[])
const bool dryrun = args.dryRun();
const bool readDict = args.found("dict");
const bool doDecompose = args.found("decompose");
const bool doFrontWidth = args.found("frontWidth");
const bool overwrite = args.found("overwrite");
const bool doFields = !args.found("no-fields");
const bool doFrontWidth = args.found("frontWidth") && !doDecompose;
const bool doDecompose = args.found("decompose");
word renumberMethodName;
args.readIfPresent("renumber-method", renumberMethodName);
@ -906,7 +846,8 @@ int main(int argc, char *argv[])
if (doDecompose && UPstream::parRun())
{
FatalErrorIn(args.executable())
<< "Cannot use -decompose option in parallel ... giving up" << nl
<< "Cannot use -decompose option in parallel"
<< " ... giving up" << nl
<< exit(FatalError);
}
@ -967,21 +908,21 @@ int main(int argc, char *argv[])
reduce(band, maxOp<label>());
reduce(profile, sumOp<scalar>());
reduce(sumSqrIntersect, sumOp<scalar>());
scalar rmsFrontwidth = Foam::sqrt
(
sumSqrIntersect/mesh.globalData().nTotalCells()
);
Info<< "Mesh " << mesh.name()
<< " size: " << mesh.globalData().nTotalCells() << nl
<< "Before renumbering" << nl
<< "Before renumbering :" << nl
<< " band : " << band << nl
<< " profile : " << profile << nl;
if (doFrontWidth)
{
reduce(sumSqrIntersect, sumOp<scalar>());
scalar rmsFrontwidth = Foam::sqrt
(
sumSqrIntersect/mesh.globalData().nTotalCells()
);
Info<< " rms frontwidth : " << rmsFrontwidth << nl;
}
@ -1150,7 +1091,10 @@ int main(int argc, char *argv[])
);
// List of stored objects to clear from mesh (after reading)
// List of objects read from time directory
// List of stored objects to clear from mesh
IOobjectList objects;
DynamicList<regIOobject*> storedObjects;
if (!dryrun && doFields)
@ -1159,60 +1103,55 @@ int main(int argc, char *argv[])
timer.resetTimeIncrement();
IOobjectList objects(mesh, runTime.timeName());
objects = IOobjectList(mesh, runTime.timeName());
storedObjects.reserve(objects.size());
const predicates::always nameMatcher;
// Read GeometricFields
#undef doLocalCode
#define doLocalCode(FieldType) \
#undef ReadFields
#define ReadFields(FieldType) \
readFields<FieldType>(mesh, objects, nameMatcher, storedObjects);
// Read volume fields
doLocalCode(volScalarField);
doLocalCode(volVectorField);
doLocalCode(volSphericalTensorField);
doLocalCode(volSymmTensorField);
doLocalCode(volTensorField);
ReadFields(volScalarField);
ReadFields(volVectorField);
ReadFields(volSphericalTensorField);
ReadFields(volSymmTensorField);
ReadFields(volTensorField);
// Read internal fields
doLocalCode(volScalarField::Internal);
doLocalCode(volVectorField::Internal);
doLocalCode(volSphericalTensorField::Internal);
doLocalCode(volSymmTensorField::Internal);
doLocalCode(volTensorField::Internal);
ReadFields(volScalarField::Internal);
ReadFields(volVectorField::Internal);
ReadFields(volSphericalTensorField::Internal);
ReadFields(volSymmTensorField::Internal);
ReadFields(volTensorField::Internal);
// Read surface fields
doLocalCode(surfaceScalarField);
doLocalCode(surfaceVectorField);
doLocalCode(surfaceSphericalTensorField);
doLocalCode(surfaceSymmTensorField);
doLocalCode(surfaceTensorField);
ReadFields(surfaceScalarField);
ReadFields(surfaceVectorField);
ReadFields(surfaceSphericalTensorField);
ReadFields(surfaceSymmTensorField);
ReadFields(surfaceTensorField);
// Read point fields
const pointMesh& pMesh = pointMesh::New(mesh);
#undef doLocalCode
#define doLocalCode(FieldType) \
#undef ReadPointFields
#define ReadPointFields(FieldType) \
readFields<FieldType>(pMesh, objects, nameMatcher, storedObjects);
doLocalCode(pointScalarField);
doLocalCode(pointVectorField);
doLocalCode(pointSphericalTensorField);
doLocalCode(pointSymmTensorField);
doLocalCode(pointTensorField);
ReadPointFields(pointScalarField);
ReadPointFields(pointVectorField);
ReadPointFields(pointSphericalTensorField);
ReadPointFields(pointSymmTensorField);
ReadPointFields(pointTensorField);
#undef doLocalCode
#undef ReadFields
#undef ReadPointFields
timings[TimingType::READ_FIELDS] += timer.timeIncrement();
// Write loaded fields when mesh.write() is called
for (auto* fldptr : storedObjects)
{
fldptr->writeOpt(IOobject::AUTO_WRITE);
}
}
@ -1285,13 +1224,7 @@ int main(int argc, char *argv[])
CompactListList<label> regionCellOrder =
regionRenumber
(
renumberPtr(),
mesh,
cellToRegion,
decomposePtr().nDomains()
);
regionRenumber(renumberPtr(), mesh, cellToRegion);
cellOrder = regionCellOrder.values();
@ -1653,25 +1586,19 @@ int main(int argc, char *argv[])
);
reduce(band, maxOp<label>());
reduce(profile, sumOp<scalar>());
reduce(sumSqrIntersect, sumOp<scalar>());
Info<< "After renumbering";
if (doDecompose)
{
Info<< " [values are misleading with -decompose option]";
}
scalar rmsFrontwidth = Foam::sqrt
(
sumSqrIntersect/mesh.globalData().nTotalCells()
);
Info<< nl
Info<< "After renumbering :" << nl
<< " band : " << band << nl
<< " profile : " << profile << nl;
if (doFrontWidth)
{
reduce(sumSqrIntersect, sumOp<scalar>());
scalar rmsFrontwidth = Foam::sqrt
(
sumSqrIntersect/mesh.globalData().nTotalCells()
);
Info<< " rms frontwidth : " << rmsFrontwidth << nl;
}

View File

@ -1,168 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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, distributed under GPL-3.0-or-later.
Description
Subsetting of an adjacency matrix (as CompactListList).
Can be relocated elsewhere.
\*---------------------------------------------------------------------------*/
#include "CompactListList.H"
#include "bitSet.H"
#include "ListOps.H"
#include "Map.H"
namespace Foam
{
// Perform a subset of the adjacency matrix
CompactListList<label> subsetAdjacency
(
const bitSet& select, // could also be labelHashSet
const CompactListList<label>& input,
labelList& subMap
)
{
// Corresponds to cellMap etc (the original selection)
subMap = select.sortedToc();
// Ensure that the subMap corresponds to a valid subset
{
label validSize = 0;
const label nTotal = input.size();
forAllReverse(subMap, i)
{
if (subMap[i] < nTotal)
{
validSize = i + 1;
break;
}
}
subMap.resize(validSize);
}
// Assumed to be sparse - use Map for reverse lookup
const Map<label> reverseMap(invertToMap(subMap));
// Pass 1: determine the selected sub-sizes
labelList sizes(subMap.size(), Foam::zero{});
forAll(subMap, idx)
{
for (const label nbr : input[subMap[idx]])
{
if
(
select.test(nbr)
&& reverseMap.contains(nbr) // extra consistency (paranoid)
)
{
++sizes[idx];
}
}
}
CompactListList<label> output(sizes);
// Reuse sizes as output offset into output.values()
sizes = labelList::subList(output.offsets(), output.size());
labelList& values = output.values();
// Pass 2: extract sub-adjacent matrix
label newNbr = -1;
forAll(subMap, idx)
{
for (const label nbr : input[subMap[idx]])
{
if
(
select.test(nbr)
&& (newNbr = reverseMap.lookup(nbr, -1)) >= 0
)
{
values[sizes[idx]++] = newNbr;
}
}
}
return output;
}
// Perform a subset of the adjacency matrix
CompactListList<label> subsetAdjacency
(
const labelRange& slice,
const CompactListList<label>& input,
labelList& subMap
)
{
// Ensure that the selection corresponds to a valid subset
const labelRange select = slice.subset0(input.size());
// Corresponds to cellMap etc (the original selection)
subMap = Foam::identity(select);
// Pass 1: determine the selected sub-sizes
labelList sizes(subMap.size(), Foam::zero{});
forAll(subMap, idx)
{
for (const label nbr : input[subMap[idx]])
{
if (select.contains(nbr))
{
++sizes[idx];
}
}
}
CompactListList<label> output(sizes);
// Reuse sizes as output offset into output.values()
sizes = labelList::subList(output.offsets(), output.size());
labelList& values = output.values();
// Pass 2: extract sub-adjacent matrix
const label localOffset = select.start();
forAll(subMap, idx)
{
for (const label nbr : input[subMap[idx]])
{
if (select.contains(nbr))
{
values[sizes[idx]++] = nbr - localOffset;
}
}
}
return output;
}
} // End namespace Foam
// ************************************************************************* //

View File

@ -83,9 +83,8 @@ See also
Foam::DynamicList
SourceFiles
PackedList.C
PackedListCore.C
PackedListI.H
PackedList.C
PackedListIO.C
\*---------------------------------------------------------------------------*/
@ -93,11 +92,11 @@ SourceFiles
#ifndef Foam_PackedList_H
#define Foam_PackedList_H
#include "className.H"
#include "BitOps.H"
#include "labelList.H"
#include "IndirectListBase.H"
#include "InfoProxy.H"
#include "PackedListCore.H"
#include <type_traits>
@ -120,23 +119,6 @@ template<unsigned Width>
Ostream& operator<<(Ostream& os, const InfoProxy<PackedList<Width>>& info);
/*---------------------------------------------------------------------------*\
Class Detail::PackedListCore Declaration
\*---------------------------------------------------------------------------*/
namespace Detail
{
//- Template-invariant parts for PackedList
struct PackedListCore
{
//- Define template name
ClassNameNoDebug("PackedList");
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class PackedList Declaration
\*---------------------------------------------------------------------------*/

View File

@ -25,7 +25,7 @@ License
\*---------------------------------------------------------------------------*/
#include "PackedList.H"
#include "PackedListCore.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -1 +1,69 @@
#warning File removed - left for old dependency check only
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 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::Detail::PackedListCore
Description
Implementation of template-invariant details for Foam::PackedList
SourceFiles
PackedListCore.C
\*---------------------------------------------------------------------------*/
#ifndef PackedListCore_H
#define PackedListCore_H
#include "className.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::PackedListCore Declaration
\*---------------------------------------------------------------------------*/
//- Template-invariant parts for PackedList
struct PackedListCore
{
//- Define template name
ClassNameNoDebug("PackedList");
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Detail
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2020-2024 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -716,14 +716,6 @@ bool Foam::fileOperations::uncollatedFileOperation::read
const bool oldMasterOnly = regIOobject::masterOnlyReading;
regIOobject::masterOnlyReading = masterOnly;
const bool oldParRun = UPstream::parRun();
if (masterOnly)
{
// Reading on master only.
// Avoid side effects from io.readStream below.
UPstream::parRun(false);
}
// Read file
ok = io.readData(io.readStream(typeName));
io.close();
@ -731,7 +723,6 @@ bool Foam::fileOperations::uncollatedFileOperation::read
// Restore flags
io.globalObject(oldGlobal);
regIOobject::masterOnlyReading = oldMasterOnly;
UPstream::parRun(oldParRun);
if (debug)
{

View File

@ -84,10 +84,7 @@ static void calcCellCellsImpl
globalNeighbour[bfacei] = val;
}
}
// Swap boundary neighbour information:
// - cyclics and (optionally) processor
syncTools::swapBoundaryFaceList(mesh, globalNeighbour, parallel);
syncTools::swapBoundaryFaceList(mesh, globalNeighbour);
// Count number of faces (internal + coupled)

View File

@ -349,10 +349,7 @@ void Foam::mapDistributeBase::receive
{
FatalErrorInFunction
<< "From processor " << proci
<< " : unallocated receive field."
<< " Expected size " << map.size()
<< " on comm " << comm
<< " with procs " << UPstream::nProcs(comm) << nl
<< " : unallocated receive field" << nl
<< exit(FatalError);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,34 +34,34 @@ void Foam::syncTools::swapBoundaryCellPositions
(
const polyMesh& mesh,
const UList<point>& cellData,
List<point>& neighbourCellData,
const bool parRun
List<point>& neighbourCellData
)
{
if (cellData.size() != mesh.nCells())
{
FatalErrorInFunction
<< "Number of values " << cellData.size()
<< " != number of cells " << mesh.nCells() << nl
<< abort(FatalError);
<< "Number of cell values " << cellData.size()
<< " is not equal to the number of cells in the mesh "
<< mesh.nCells() << abort(FatalError);
}
const polyBoundaryMesh& patches = mesh.boundaryMesh();
neighbourCellData.resize(mesh.nBoundaryFaces());
for (const polyPatch& pp : mesh.boundaryMesh())
for (const polyPatch& pp : patches)
{
const auto& faceCells = pp.faceCells();
label bFacei = pp.start()-mesh.nInternalFaces();
// ie, boundarySlice() = patchInternalList()
SubList<point>
(
neighbourCellData,
faceCells.size(),
pp.offset()
) = UIndirectList<point>(cellData, faceCells);
const labelUList& faceCells = pp.faceCells();
for (const label celli : faceCells)
{
neighbourCellData[bFacei] = cellData[celli];
++bFacei;
}
}
syncTools::swapBoundaryFacePositions(mesh, neighbourCellData, parRun);
syncTools::swapBoundaryFacePositions(mesh, neighbourCellData);
}
@ -127,7 +127,9 @@ Foam::bitSet Foam::syncTools::getMasterFaces(const polyMesh& mesh)
{
bitSet isMaster(mesh.nFaces(), true);
for (const polyPatch& pp : mesh.boundaryMesh())
const polyBoundaryMesh& patches = mesh.boundaryMesh();
for (const polyPatch& pp : patches)
{
if (pp.coupled())
{
@ -149,7 +151,9 @@ Foam::bitSet Foam::syncTools::getInternalOrMasterFaces
{
bitSet isMaster(mesh.nFaces(), true);
for (const polyPatch& pp : mesh.boundaryMesh())
const polyBoundaryMesh& patches = mesh.boundaryMesh();
for (const polyPatch& pp : patches)
{
if (pp.coupled())
{
@ -175,7 +179,9 @@ Foam::bitSet Foam::syncTools::getInternalOrCoupledFaces
{
bitSet isMaster(mesh.nFaces(), true);
for (const polyPatch& pp : mesh.boundaryMesh())
const polyBoundaryMesh& patches = mesh.boundaryMesh();
for (const polyPatch& pp : patches)
{
if (!pp.coupled())
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2024 OpenCFD Ltd.
Copyright (C) 2015-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -69,7 +69,6 @@ class syncTools
// Private Member Functions
//- Combine val with existing value in pointValues map at given index
// No communication
template<class T, class CombineOp>
static void combine
(
@ -80,7 +79,6 @@ class syncTools
);
//- Combine val with existing value in edgeValues at edge index
// No communication
template<class T, class CombineOp>
static void combine
(
@ -97,7 +95,6 @@ public:
// Preferably use specialisations below.
//- Synchronize values on selected points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp>
static void syncPointMap
(
@ -108,7 +105,6 @@ public:
);
//- Synchronize values on selected edges.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp>
static void syncEdgeMap
(
@ -119,7 +115,6 @@ public:
);
//- Synchronize values on all mesh points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp>
static void syncPointList
(
@ -131,7 +126,6 @@ public:
);
//- Synchronize values on selected mesh points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp>
static void syncPointList
(
@ -144,7 +138,6 @@ public:
);
//- Synchronize values on all mesh edges.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp, class FlipOp>
static void syncEdgeList
(
@ -157,12 +150,11 @@ public:
);
//- Synchronize values on selected mesh edges.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp, class TransformOp, class FlipOp>
static void syncEdgeList
(
const polyMesh& mesh,
const labelUList& meshEdges,
const labelList& meshEdges,
List<T>& edgeValues,
const CombineOp& cop,
const T& nullValue,
@ -178,7 +170,6 @@ public:
UList<T>& faceValues,
const CombineOp& cop,
const TransformOp& top,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
);
@ -186,7 +177,6 @@ public:
// Synchronise point-wise data
//- Synchronize values on all mesh points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp>
static void syncPointList
(
@ -207,7 +197,6 @@ public:
}
//- Synchronize locations on all mesh points.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncPointPositions
(
@ -228,12 +217,11 @@ public:
}
//- Synchronize values on selected mesh points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp>
static void syncPointList
(
const polyMesh& mesh,
const labelUList& meshPoints,
const labelList& meshPoints,
List<T>& pointValues,
const CombineOp& cop,
const T& nullValue
@ -251,12 +239,11 @@ public:
}
//- Synchronize locations on selected mesh points.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncPointPositions
(
const polyMesh& mesh,
const labelUList& meshPoints,
const labelList& meshPoints,
List<point>& positions,
const CombineOp& cop,
const point& nullValue
@ -277,7 +264,6 @@ public:
// Synchronise edge-wise data
//- Synchronize values on all mesh edges.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp>
static void syncEdgeList
(
@ -299,7 +285,6 @@ public:
}
//- Synchronize locations on all mesh edges.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncEdgePositions
(
@ -321,12 +306,11 @@ public:
}
//- Synchronize values on selected mesh edges.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp>
static void syncEdgeList
(
const polyMesh& mesh,
const labelUList& meshEdges,
const labelList& meshEdges,
List<T>& edgeValues,
const CombineOp& cop,
const T& nullValue
@ -345,12 +329,11 @@ public:
}
//- Synchronize locations on selected mesh edges.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncEdgePositions
(
const polyMesh& mesh,
const labelUList& meshEdges,
const labelList& meshEdges,
List<point>& positions,
const CombineOp& cop,
const point& nullValue
@ -414,9 +397,7 @@ public:
(
const polyMesh& mesh,
UList<T>& faceValues,
const CombineOp& cop,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
const CombineOp& cop
)
{
SubList<T> bndValues
@ -431,8 +412,7 @@ public:
mesh,
bndValues,
cop,
mapDistribute::transform(),
parRun
mapDistribute::transform()
);
}
@ -442,9 +422,7 @@ public:
(
const polyMesh& mesh,
UList<point>& positions,
const CombineOp& cop,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
const CombineOp& cop
)
{
SubList<point> bndValues
@ -458,8 +436,7 @@ public:
mesh,
bndValues,
cop,
mapDistribute::transformPosition(),
parRun
mapDistribute::transformPosition()
);
}
@ -468,9 +445,7 @@ public:
static void swapBoundaryFaceList
(
const polyMesh& mesh,
UList<T>& faceValues,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
UList<T>& faceValues
)
{
syncBoundaryFaceList
@ -478,8 +453,7 @@ public:
mesh,
faceValues,
eqOp<T>(),
mapDistribute::transform(),
parRun
mapDistribute::transform()
);
}
@ -487,9 +461,7 @@ public:
static void swapBoundaryFacePositions
(
const polyMesh& mesh,
UList<point>& positions,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
UList<point>& positions
)
{
syncBoundaryFaceList
@ -497,8 +469,7 @@ public:
mesh,
positions,
eqOp<point>(),
mapDistribute::transformPosition(),
parRun
mapDistribute::transformPosition()
);
}
@ -507,9 +478,7 @@ public:
static void swapFaceList
(
const polyMesh& mesh,
UList<T>& faceValues,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
UList<T>& faceValues
)
{
SubList<T> bndValues
@ -523,71 +492,31 @@ public:
mesh,
bndValues,
eqOp<T>(),
mapDistribute::transform(),
parRun
mapDistribute::transform()
);
}
//- Extract and swap to obtain neighbour cell values
//- for all boundary faces
//- Swap to obtain neighbour cell values for all boundary faces
template<class T>
static void swapBoundaryCellList
(
const polyMesh& mesh,
const UList<T>& cellData,
List<T>& neighbourCellData,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
List<T>& neighbourCellData
);
//- Extract and swap to obtain neighbour cell positions
//- for all boundary faces
//- Swap to obtain neighbour cell positions for all boundary faces
static void swapBoundaryCellPositions
(
const polyMesh& mesh,
const UList<point>& cellData,
List<point>& neighbourCellData,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
List<point>& neighbourCellData
);
//- Return neighbour cell values for all boundary faces
//- by swapping via boundary faces
template<class T>
FOAM_NODISCARD static List<T> swapBoundaryCellList
(
const polyMesh& mesh,
const UList<T>& cellData,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
)
{
List<T> nbrCellData;
swapBoundaryCellList(mesh, cellData, nbrCellData, parRun);
return nbrCellData;
}
//- Return neighbour cell positions for all boundary faces
//- by swapping via boundary faces
FOAM_NODISCARD static List<point> swapBoundaryCellPositions
(
const polyMesh& mesh,
const UList<point>& cellData,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
)
{
List<point> nbrCellData;
swapBoundaryCellPositions(mesh, cellData, nbrCellData, parRun);
return nbrCellData;
}
// Sparse versions
//- Synchronize values on selected points.
// Communication if UPstream::parRun() == true.
template<class T, class CombineOp>
static void syncPointMap
(
@ -606,7 +535,6 @@ public:
}
//- Synchronize locations on selected points.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncPointPositions
(
@ -624,10 +552,9 @@ public:
);
}
//- Synchronize values on selected edges.
//- Edges are represented by the two vertices that make it up
//- so global edges never get constructed.
// Communication if UPstream::parRun() == true.
//- Synchronize values on selected edges. Edges are represented
// by the two vertices that make it up so global edges never get
// constructed.
template<class T, class CombineOp>
static void syncEdgeMap
(
@ -646,7 +573,6 @@ public:
}
//- Synchronize locations on selected edges.
// Communication if UPstream::parRun() == true.
template<class CombineOp>
static void syncEdgePositions
(
@ -675,7 +601,7 @@ public:
// offset when accessing values.
// \param faceValues The face values to synchronize
// \param cop The combine operation
// \param parRun Allow parallel communication
// \param parRun True if this is a parallel simulation
template<unsigned Width, class CombineOp>
static void syncFaceList
(
@ -693,7 +619,6 @@ public:
const polyMesh& mesh,
PackedList<Width>& faceValues,
const CombineOp& cop,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
);
@ -704,7 +629,6 @@ public:
const polyMesh& mesh,
PackedList<Width>& faceValues,
const CombineOp& cop,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
);
@ -713,9 +637,7 @@ public:
static void swapFaceList
(
const polyMesh& mesh,
PackedList<Width>& faceValues,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
PackedList<Width>& faceValues
);
//- Swap coupled boundary face values. Uses eqOp
@ -723,9 +645,7 @@ public:
static void swapBoundaryFaceList
(
const polyMesh& mesh,
PackedList<Width>& faceValues,
//! Allow parallel communication
const bool parRun = UPstream::parRun()
PackedList<Width>& faceValues
);
template<unsigned Width, class CombineOp>

View File

@ -79,8 +79,6 @@ void Foam::syncTools::combine
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T, class CombineOp, class TransformOp>
void Foam::syncTools::syncPointMap
(
@ -490,7 +488,7 @@ void Foam::syncTools::syncEdgeMap
forAllConstIters(nbrPatchInfo, nbrIter)
{
const edge& e = nbrIter.key();
const edge meshEdge(meshPts, e);
const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
combine
(
@ -537,7 +535,7 @@ void Foam::syncTools::syncEdgeMap
{
const edge& e0 = edgesA[twoEdges[0]];
const edge meshEdge0(meshPtsA, e0);
const edge meshEdge0(meshPtsA[e0[0]], meshPtsA[e0[1]]);
const auto iter = edgeValues.cfind(meshEdge0);
@ -548,7 +546,7 @@ void Foam::syncTools::syncEdgeMap
}
{
const edge& e1 = edgesB[twoEdges[1]];
const edge meshEdge1(meshPtsB, e1);
const edge meshEdge1(meshPtsB[e1[0]], meshPtsB[e1[1]]);
const auto iter = edgeValues.cfind(meshEdge1);
@ -575,7 +573,7 @@ void Foam::syncTools::syncEdgeMap
if (half1Fnd.good())
{
const edge& e0 = edgesA[twoEdges[0]];
const edge meshEdge0(meshPtsA, e0);
const edge meshEdge0(meshPtsA[e0[0]], meshPtsA[e0[1]]);
combine
(
@ -591,7 +589,7 @@ void Foam::syncTools::syncEdgeMap
if (half0Fnd.good())
{
const edge& e1 = edgesB[twoEdges[1]];
const edge meshEdge1(meshPtsB, e1);
const edge meshEdge1(meshPtsB[e1[0]], meshPtsB[e1[1]]);
combine
(
@ -751,8 +749,8 @@ void Foam::syncTools::syncPointList
{
FatalErrorInFunction
<< "Number of values " << pointValues.size()
<< " != number of points " << mesh.nPoints() << nl
<< abort(FatalError);
<< " is not equal to the number of points in the mesh "
<< mesh.nPoints() << abort(FatalError);
}
mesh.globalData().syncPointData(pointValues, cop, top);
@ -774,8 +772,8 @@ void Foam::syncTools::syncPointList
{
FatalErrorInFunction
<< "Number of values " << pointValues.size()
<< " != number of meshPoints " << meshPoints.size() << nl
<< abort(FatalError);
<< " is not equal to the number of meshPoints "
<< meshPoints.size() << abort(FatalError);
}
const globalMeshData& gd = mesh.globalData();
const indirectPrimitivePatch& cpp = gd.coupledPatch();
@ -831,8 +829,8 @@ void Foam::syncTools::syncEdgeList
{
FatalErrorInFunction
<< "Number of values " << edgeValues.size()
<< " != number of edges " << mesh.nEdges() << nl
<< abort(FatalError);
<< " is not equal to the number of edges in the mesh "
<< mesh.nEdges() << abort(FatalError);
}
const edgeList& edges = mesh.edges();
@ -917,7 +915,7 @@ template<class T, class CombineOp, class TransformOp, class FlipOp>
void Foam::syncTools::syncEdgeList
(
const polyMesh& mesh,
const labelUList& meshEdges,
const labelList& meshEdges,
List<T>& edgeValues,
const CombineOp& cop,
const T& nullValue,
@ -929,8 +927,8 @@ void Foam::syncTools::syncEdgeList
{
FatalErrorInFunction
<< "Number of values " << edgeValues.size()
<< " != number of meshEdges " << meshEdges.size() << nl
<< abort(FatalError);
<< " is not equal to the number of meshEdges "
<< meshEdges.size() << abort(FatalError);
}
const edgeList& edges = mesh.edges();
const globalMeshData& gd = mesh.globalData();
@ -948,7 +946,7 @@ void Foam::syncTools::syncEdgeList
const auto iter = mpm.cfind(meshEdgei);
if (iter.good())
{
const label cppEdgei = iter.val();
const label cppEdgei = iter();
const edge& cppE = cppEdges[cppEdgei];
const edge& meshE = edges[meshEdgei];
@ -994,7 +992,7 @@ void Foam::syncTools::syncEdgeList
const auto iter = mpm.cfind(meshEdgei);
if (iter.good())
{
label cppEdgei = iter.val();
label cppEdgei = iter();
const edge& cppE = cppEdges[cppEdgei];
const edge& meshE = edges[meshEdgei];
@ -1031,13 +1029,14 @@ void Foam::syncTools::syncBoundaryFaceList
{
FatalErrorInFunction
<< "Number of values " << faceValues.size()
<< " != number of boundary faces " << mesh.nBoundaryFaces() << nl
<< " is not equal to the number of boundary faces in the mesh "
<< mesh.nBoundaryFaces() << nl
<< abort(FatalError);
}
const polyBoundaryMesh& patches = mesh.boundaryMesh();
if (parRun && UPstream::parRun())
if (parRun)
{
// Avoid mesh.globalData() - possible race condition
@ -1105,7 +1104,7 @@ void Foam::syncTools::syncBoundaryFaceList
}
// Wait for all comms to finish
UPstream::waitRequests(startRequest);
Pstream::waitRequests(startRequest);
// Combine with existing data
for (const polyPatch& pp : patches)
@ -1275,20 +1274,20 @@ void Foam::syncTools::syncFaceList
{
FatalErrorInFunction
<< "Number of values " << faceValues.size()
<< " != number of "
<< " is not equal to the number of "
<< (isBoundaryOnly ? "boundary" : "mesh") << " faces "
<< (mesh.nFaces() - boundaryOffset) << nl
<< ((mesh.nFaces() - boundaryOffset)) << nl
<< abort(FatalError);
}
const polyBoundaryMesh& patches = mesh.boundaryMesh();
if (parRun && UPstream::parRun())
if (parRun)
{
const label startRequest = UPstream::nRequests();
// Receive buffers
PtrList<PackedList<Width>> recvBufs(patches.size());
PtrList<PackedList<Width>> recvInfos(patches.size());
// Set up reads
for (const polyPatch& pp : patches)
@ -1299,21 +1298,23 @@ void Foam::syncTools::syncFaceList
{
const auto& procPatch = *ppp;
const label patchi = pp.index();
const label patchSize = pp.size();
auto& recvbuf = recvBufs.emplace_set(patchi, pp.size());
recvInfos.set(patchi, new PackedList<Width>(patchSize));
PackedList<Width>& recvInfo = recvInfos[patchi];
UIPstream::read
(
UPstream::commsTypes::nonBlocking,
procPatch.neighbProcNo(),
recvbuf.data_bytes(),
recvbuf.size_bytes()
recvInfo.data_bytes(),
recvInfo.size_bytes()
);
}
}
// Send buffers
PtrList<PackedList<Width>> sendBufs(patches.size());
PtrList<PackedList<Width>> sendInfos(patches.size());
// Set up writes
for (const polyPatch& pp : patches)
@ -1325,16 +1326,24 @@ void Foam::syncTools::syncFaceList
const auto& procPatch = *ppp;
const label patchi = pp.index();
const labelRange range(pp.start()-boundaryOffset, pp.size());
auto& sendbuf = sendBufs.emplace_set(patchi, faceValues, range);
const labelRange range
(
pp.start()-boundaryOffset,
pp.size()
);
sendInfos.set
(
patchi,
new PackedList<Width>(faceValues, range)
);
PackedList<Width>& sendInfo = sendInfos[patchi];
UOPstream::write
(
UPstream::commsTypes::nonBlocking,
procPatch.neighbProcNo(),
sendbuf.cdata_bytes(),
sendbuf.size_bytes()
sendInfo.cdata_bytes(),
sendInfo.size_bytes()
);
}
}
@ -1352,13 +1361,13 @@ void Foam::syncTools::syncFaceList
const label patchi = pp.index();
const label patchSize = pp.size();
const auto& recvbuf = recvBufs[patchi];
const PackedList<Width>& recvInfo = recvInfos[patchi];
// Combine (bitwise)
label bFacei = pp.start()-boundaryOffset;
for (label i = 0; i < patchSize; ++i)
{
unsigned int recvVal = recvbuf[i];
unsigned int recvVal = recvInfo[i];
unsigned int faceVal = faceValues[bFacei];
cop(faceVal, recvVal);
@ -1411,16 +1420,15 @@ void Foam::syncTools::swapBoundaryCellList
(
const polyMesh& mesh,
const UList<T>& cellData,
List<T>& neighbourCellData,
const bool parRun
List<T>& neighbourCellData
)
{
if (cellData.size() != mesh.nCells())
{
FatalErrorInFunction
<< "Number of cell values " << cellData.size()
<< " != number of cells " << mesh.nCells() << nl
<< abort(FatalError);
<< " is not equal to the number of cells in the mesh "
<< mesh.nCells() << abort(FatalError);
}
const polyBoundaryMesh& patches = mesh.boundaryMesh();
@ -1429,18 +1437,15 @@ void Foam::syncTools::swapBoundaryCellList
for (const polyPatch& pp : patches)
{
const auto& faceCells = pp.faceCells();
label bFacei = pp.offset();
// ie, boundarySlice() = patchInternalList()
SubList<T>
(
neighbourCellData,
faceCells.size(),
pp.offset()
) = UIndirectList<T>(cellData, faceCells);
for (const label celli : pp.faceCells())
{
neighbourCellData[bFacei] = cellData[celli];
++bFacei;
}
}
syncTools::swapBoundaryFaceList(mesh, neighbourCellData, parRun);
syncTools::swapBoundaryFaceList(mesh, neighbourCellData);
}
@ -1474,17 +1479,10 @@ template<unsigned Width>
void Foam::syncTools::swapFaceList
(
const polyMesh& mesh,
PackedList<Width>& faceValues,
const bool parRun
PackedList<Width>& faceValues
)
{
syncFaceList
(
mesh,
faceValues,
eqOp<unsigned int>(),
parRun
);
syncFaceList(mesh, faceValues, eqOp<unsigned int>());
}
@ -1492,17 +1490,10 @@ template<unsigned Width>
void Foam::syncTools::swapBoundaryFaceList
(
const polyMesh& mesh,
PackedList<Width>& faceValues,
const bool parRun
PackedList<Width>& faceValues
)
{
syncBoundaryFaceList
(
mesh,
faceValues,
eqOp<unsigned int>(),
parRun
);
syncBoundaryFaceList(mesh, faceValues, eqOp<unsigned int>());
}
@ -1519,8 +1510,8 @@ void Foam::syncTools::syncPointList
{
FatalErrorInFunction
<< "Number of values " << pointValues.size()
<< " != number of points " << mesh.nPoints() << nl
<< abort(FatalError);
<< " is not equal to the number of points in the mesh "
<< mesh.nPoints() << abort(FatalError);
}
const globalMeshData& gd = mesh.globalData();
@ -1562,8 +1553,8 @@ void Foam::syncTools::syncEdgeList
{
FatalErrorInFunction
<< "Number of values " << edgeValues.size()
<< " != number of edges " << mesh.nEdges() << nl
<< abort(FatalError);
<< " is not equal to the number of edges in the mesh "
<< mesh.nEdges() << abort(FatalError);
}
const globalMeshData& gd = mesh.globalData();

View File

@ -96,7 +96,7 @@ void Foam::ZoneMesh<ZoneType, MeshType>::calcZoneMap() const
{
map.insert(id, zonei);
}
else if (fnd.val() != zonei)
else if (fnd() != zonei)
{
// Multiple zones for same id
@ -112,7 +112,7 @@ void Foam::ZoneMesh<ZoneType, MeshType>::calcZoneMap() const
: static_cast<const labelList&>(zn)
)
{
maxIndex = Foam::max(maxIndex, id);
maxIndex = max(maxIndex, id);
}
}
additionalMapPtr_.reset(new labelListList(maxIndex+1));
@ -135,7 +135,7 @@ void Foam::ZoneMesh<ZoneType, MeshType>::calcZoneMap() const
if (zones.size())
{
Foam::stableSort(zones);
stableSort(zones);
const label zonei = map[id];
const label index = findLower(zones, zonei);
if (index == -1)
@ -426,11 +426,11 @@ Foam::label Foam::ZoneMesh<ZoneType, MeshType>::whichZones
) const
{
zones.clear();
const auto fnd = zoneMap().cfind(objectIndex);
const auto fnd = zoneMap().find(objectIndex);
if (fnd)
{
// Add main element
zones.push_back(fnd.val());
zones.push_back(fnd());
if (additionalMapPtr_)
{
const auto& additionalMap = *additionalMapPtr_;
@ -967,7 +967,7 @@ bool Foam::ZoneMesh<ZoneType, MeshType>::checkParallelSync
const bool report
) const
{
if (!UPstream::parRun())
if (!Pstream::parRun())
{
return false;
}
@ -1025,7 +1025,7 @@ bool Foam::ZoneMesh<ZoneType, MeshType>::checkParallelSync
{
hasError = true;
if (debug || (report && UPstream::master()))
if (debug || (report && Pstream::master()))
{
Info<< " ***Zone " << zn.name()
<< " of type " << zn.type()

View File

@ -194,8 +194,9 @@ public:
// If object does not belong to any zones, return -1
label whichZone(const label objectIndex) const;
//- Given a global object index, return (in argument) its zones.
// Returns number of zones (0 if object does not belong to any zones)
//- Given a global object index, return (in argument) the zones it is
// in. Returns number of zones (0 if object does not belong to any
// zones)
label whichZones
(
const label objectIndex,

View File

@ -33,15 +33,7 @@ fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C
fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C
fvOptions/atmPlantCanopyTSource/atmPlantCanopyTSource.C
fvOptions/atmNutSource/atmNutSource.C
fvOptions/treeTurbulence/treeTurbulence.C
etht = fvOptions/evapotranspirationHeatTransfer
ethtModels = $(etht)/evapotranspirationHeatTransferModels
$(etht)/evapotranspirationHeatTransfer.C
$(ethtModels)/evapotranspirationHeatTransferModel/evapotranspirationHeatTransferModel.C
$(ethtModels)/evapotranspirationHeatTransferModel/evapotranspirationHeatTransferModelNew.C
$(ethtModels)/tree/tree.C
$(ethtModels)/grass/grass.C
/* functionObjects */
functionObjects/ObukhovLength/ObukhovLength.C

View File

@ -8,7 +8,6 @@ EXE_INC = \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/solidThermo/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
@ -19,7 +18,6 @@ LIB_LIBS = \
-lfvOptions \
-lmeshTools \
-lsurfMesh \
-lradiationModels \
-lfluidThermophysicalModels \
-lsolidThermo \
-lturbulenceModels \

View File

@ -1,172 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "evapotranspirationHeatTransfer.H"
#include "evapotranspirationHeatTransferModel.H"
#include "fvMesh.H"
#include "fvMatrix.H"
#include "basicThermo.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
defineTypeNameAndDebug(evapotranspirationHeatTransfer, 0);
addToRunTimeSelectionTable
(
option,
evapotranspirationHeatTransfer,
dictionary
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fv::evapotranspirationHeatTransfer::evapotranspirationHeatTransfer
(
const word& sourceName,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
)
:
fv::cellSetOption(sourceName, modelType, dict, mesh),
ethtModelPtr_()
{
// Set the field name to that of the energy
// field from which the temperature is obtained
const auto& thermo = mesh_.lookupObject<basicThermo>(basicThermo::dictName);
fieldNames_.resize(1, thermo.he().name());
fv::option::resetApplied();
Info<< " Applying evapotranspirationHeatTransfer to: " << fieldNames_[0]
<< endl;
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::fv::evapotranspirationHeatTransfer::~evapotranspirationHeatTransfer()
{} // evapotranspirationHeatTransferModel was forward declared
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fv::evapotranspirationHeatTransfer::addSup
(
fvScalarMatrix& eqn,
const label fieldi
)
{
if (this->V() < VSMALL)
{
return;
}
const scalar V = this->V();
const scalarField& Vcells = mesh_.V();
const volScalarField& he = eqn.psi();
scalarField& heSource = eqn.source();
// Calculate evapotranspiration heat transfer rate per volume [J/s/m^3]
const scalarField Q(ethtModelPtr_->Q(cells_)/V);
if (he.dimensions() == dimEnergy/dimMass)
{
forAll(cells_, i)
{
const label celli = cells_[i];
heSource[celli] += Q[i]*Vcells[celli];
}
}
else if (he.dimensions() == dimTemperature)
{
const auto& thermo =
mesh_.lookupObject<basicThermo>(basicThermo::dictName);
// Calculate density*heat capacity at constant pressure/volume
const volScalarField rhoCpv(thermo.rho()*thermo.Cpv());
// heSource [K m^3/s] = [J/s/m^3] * m^3 / [kg/m^3] / [J/kg/K]
forAll(cells_, i)
{
const label celli = cells_[i];
heSource[celli] += Q[i]*Vcells[celli]*rhoCpv[i];
}
}
}
void Foam::fv::evapotranspirationHeatTransfer::addSup
(
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
)
{
addSup(eqn, fieldi);
}
bool Foam::fv::evapotranspirationHeatTransfer::read(const dictionary& dict)
{
if (!fv::cellSetOption::read(dict))
{
return false;
}
if (selectionMode_ != selectionModeType::smCellZone)
{
FatalIOErrorInFunction(dict)
<< "evapotranspirationHeatTransfer requires "
<< selectionModeTypeNames_[selectionModeType::smCellZone]
<< exit(FatalIOError);
}
ethtModelPtr_.reset
(
evapotranspirationHeatTransferModel::New(dict, mesh_)
);
return true;
}
// ************************************************************************* //

View File

@ -1,183 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::fv::evapotranspirationHeatTransfer
Description
Applies sources on temperature (\c T - incompressible)
or energy (\c h/e - compressible) equation to incorporate
evapotranspiration heat-transfer effects from the specified
plant canopy. Heat transfer is usually calculated based on
empirical relations between plants and solar radiation.
Usage
Example by using \c constant/fvOptions:
\verbatim
evapotranspirationHeatTransfer1
{
// Mandatory entries
type evapotranspirationHeatTransfer;
model <word>;
// Model-specific entries
...
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: evapotranspirationHeatTransfer | word | yes | -
model | Name of heat-transfer model | word | yes | -
\endtable
Options for the \c model entry:
\verbatim
tree | Regression-based heat-transfer model for trees
grass | Heat-transfer model for grass
\endverbatim
The inherited entries are elaborated in:
- \link fvOption.H \endlink
- \link cellSetOption.H \endlink
Note
- Evapotranspiration mass transfer is not modelled.
SourceFiles
evapotranspirationHeatTransfer.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_fv_evapotranspirationHeatTransfer_H
#define Foam_fv_evapotranspirationHeatTransfer_H
#include "cellSetOption.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class evapotranspirationHeatTransferModel;
namespace fv
{
/*---------------------------------------------------------------------------*\
Class evapotranspirationHeatTransfer Declaration
\*---------------------------------------------------------------------------*/
class evapotranspirationHeatTransfer
:
public fv::cellSetOption
{
// Private Data
//- Runtime-selectable evapotranspiration heat transfer model
autoPtr<evapotranspirationHeatTransferModel> ethtModelPtr_;
public:
//- Runtime type information
TypeName("evapotranspirationHeatTransfer");
// Constructors
//- Construct from explicit source name and mesh
evapotranspirationHeatTransfer
(
const word& sourceName,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
evapotranspirationHeatTransfer(const evapotranspirationHeatTransfer&) =
delete;
//- No copy assignment
void operator=(const evapotranspirationHeatTransfer&) = delete;
//- Destructor
virtual ~evapotranspirationHeatTransfer();
// Member Functions
//- Add explicit contribution to energy equation
//- for incompressible flow computations
virtual void addSup
(
fvScalarMatrix& eqn,
const label fieldi
);
//- Add explicit contribution to energy equation
//- for compressible flow computations
virtual void addSup
(
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
);
//- Add explicit contribution to energy equation
//- for multiphase flow computations
virtual void addSup
(
const volScalarField& alpha,
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
)
{
NotImplemented;
}
//- Read dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fv
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,196 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "evapotranspirationHeatTransferModel.H"
#include "radiationModel.H"
#include "solarLoadBase.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(evapotranspirationHeatTransferModel, 0);
defineRunTimeSelectionTable
(
evapotranspirationHeatTransferModel,
dictionary
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::volScalarField& Foam::evapotranspirationHeatTransferModel::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::scalar Foam::evapotranspirationHeatTransferModel::q() const
{
// Retrieve solar-load information
const auto& base =
mesh().lookupObject<radiation::solarLoadBase>("solarLoadBase");
const solarCalculator& solar = base.solarCalculatorRef();
// Retrieve internal & boundary faces directly hit by solar rays
const faceShading& shade = base.faceShadingRef();
const labelList& hitFacesId = shade.rayStartFaces();
// Retrieve face zone information
const faceZone& zone = mesh_.faceZones()[faceZoneId_];
const vectorField& faceNormals = zone().faceNormals();
const scalarField& faceAreas = zone().magFaceAreas();
// Retrieve direct solar load [W/m^2]
const vector directSolarRad(solar.directSolarRad()*solar.direction());
// Identify zone faces within mesh
bitSet isZoneFace(mesh_.nFaces());
isZoneFace.set(zone);
// Calculate area-averaged incident solar load
// Assuming hit faces are updated by solarLoad
scalar q = 0;
scalar totalFaceArea = 0;
for (const label facei : hitFacesId)
{
if (isZoneFace[facei])
{
const label localFacei = zone.whichFace(facei);
const vector& faceNormal = faceNormals[localFacei];
const scalar faceArea = faceAreas[localFacei];
const scalar qIncident = directSolarRad & faceNormal;
q += qIncident*faceArea;
totalFaceArea += faceArea;
}
}
reduce(q, sumOp<scalar>());
reduce(totalFaceArea, sumOp<scalar>());
q /= totalFaceArea;
// Sum diffusive solar loads
switch(solar.sunLoadModel())
{
case solarCalculator::mSunLoadFairWeatherConditions:
case solarCalculator::mSunLoadTheoreticalMaximum:
{
// Calculate diffusive radiance
// contribution from sky and ground
tmp<scalarField> tdiffuseSolarRad =
solar.diffuseSolarRad(faceNormals);
const scalarField& diffuseSolarRad = tdiffuseSolarRad.cref();
// Calculate area-averaged diffusive solar load
scalar meanDiffuseSolarRad = 0;
forAll(faceAreas, i)
{
meanDiffuseSolarRad += diffuseSolarRad[i]*faceAreas[i];
}
meanDiffuseSolarRad /= totalFaceArea;
q += meanDiffuseSolarRad;
}
break;
case solarCalculator::mSunLoadConstant:
case solarCalculator::mSunLoadTimeDependent:
{
q += solar.diffuseSolarRad();
}
break;
}
return q;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::evapotranspirationHeatTransferModel::evapotranspirationHeatTransferModel
(
const dictionary& dict,
const fvMesh& mesh
)
:
mesh_(mesh)
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::evapotranspirationHeatTransferModel::read(const dictionary& dict)
{
faceZoneId_ = mesh_.faceZones().findZoneID(dict.get<word>("faceZone"));
if (faceZoneId_ < 0)
{
const word faceZoneName(mesh_.faceZones()[faceZoneId_].name());
FatalIOErrorInFunction(dict)
<< type() << ' ' << typeName << ": "
<< " No matching face zone: " << faceZoneName << nl
<< " Known face zones: "
<< flatOutput(mesh_.faceZones().names()) << nl
<< exit(FatalIOError);
return false;
}
return true;
}
// ************************************************************************* //

View File

@ -1,180 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::evapotranspirationHeatTransferModel
Description
Base class for evapotranspiration models
to handle general evapotranspiration characteristics.
SourceFiles
evapotranspirationHeatTransferModel.C
evapotranspirationHeatTransferModelNew.C
evapotranspirationHeatTransferModelTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_evapotranspirationHeatTransferModel_H
#define Foam_evapotranspirationHeatTransferModel_H
#include "dictionary.H"
#include "HashSet.H"
#include "volFields.H"
#include "runTimeSelectionTables.H"
#include "OFstream.H"
#include "coordinateSystem.H"
#include "writeFile.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class fvMesh;
/*---------------------------------------------------------------------------*\
Class evapotranspirationHeatTransferModel Declaration
\*---------------------------------------------------------------------------*/
class evapotranspirationHeatTransferModel
{
// Private Data
//- Reference to the mesh
const fvMesh& mesh_;
//- Identifier of specified face zone
label faceZoneId_;
protected:
// Protected Member Functions
//- Return requested field from the object registry
//- or read+register the field to the object registry
volScalarField& getOrReadField(const word& fieldName) const;
//- Area-averaged heat flux due to short-wave
//- solar rays on face zone [W/m^2]
// Short-wave: direct and diffusive solar rays
scalar q() const;
public:
//- Runtime type information
TypeName("evapotranspirationHeatTransferModel");
// Declare runtime constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
evapotranspirationHeatTransferModel,
dictionary,
(
const dictionary& dict,
const fvMesh& mesh
),
(dict, mesh)
);
// Selectors
//- Return a reference to the selected evapotranspiration model
static autoPtr<evapotranspirationHeatTransferModel> New
(
const dictionary& dict,
const fvMesh& mesh
);
// Constructors
//- Construct from components
evapotranspirationHeatTransferModel
(
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
evapotranspirationHeatTransferModel
(
const evapotranspirationHeatTransferModel&
) = delete;
//- No copy assignment
void operator=(const evapotranspirationHeatTransferModel&) = delete;
//- Destructor
virtual ~evapotranspirationHeatTransferModel() = default;
// Member Functions
// Access
//- Return const reference to the mesh
const fvMesh& mesh() const noexcept
{
return mesh_;
}
//- Return the face-zone identifier
label faceZoneId() const noexcept
{
return faceZoneId_;
}
// Evaluation
//- Return heat-transfer rate for speficied cells [J/s]
virtual tmp<scalarField> Q(const labelList& cells) const = 0;
// I-O
//- Read the dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,418 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "grass.H"
#include "basicThermo.H"
#include "fluidThermo.H"
#include "turbulentTransportModel.H"
#include "turbulentFluidThermoModel.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace evapotranspirationHeatTransferModels
{
defineTypeNameAndDebug(grass, 0);
addToRunTimeSelectionTable
(
evapotranspirationHeatTransferModel,
grass,
dictionary
);
}
}
const Foam::Enum
<
Foam::evapotranspirationHeatTransferModels::grass::soilHeatFluxType
>
Foam::evapotranspirationHeatTransferModels::grass::soilHeatFluxTypeNames
({
{
soilHeatFluxType::PROPORTIONAL_TO_SOLAR_RADIATION,
"proportionalToSolarRadiation"
},
{ soilHeatFluxType::BOUNDARY, "boundary" }
});
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::tmp<Foam::scalarField>
Foam::evapotranspirationHeatTransferModels::grass::E(const labelList& cells)
const
{
const scalar q = this->q();
const scalar G = this->G(cells);
const scalar Delta = this->Delta();
const scalar D = this->D();
const scalar ra = this->ra();
const scalar rs = this->rs();
const scalar gamma = this->gamma();
// (BSG:Eq. 11)
const scalar E =
(Delta*(q - G) + rho_*Cp_*D/ra)/(Delta + gamma*(1 + rs/ra));
return tmp<scalarField>::New(cells.size(), E);
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::Delta() const
{
// (BSG:Eq. 15), (APR:Eq. 13) - note 0.6108 -> 610.8 due to kPa -> Pa
const scalar Ta = Tref_ + 237.3;
return 4098*(610.8*exp(17.27*Tref_/Ta))/sqr(Ta);
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::D() const
{
// (BSG:Eq. 16)
const scalar RHref = RHptr_->value(mesh().time().timeOutputValue());
return (1 - RHref)*pSat();
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::pSat() const
{
// (BSG:Eq. 17; Arden Buck equation)
const scalar p1 = (1.0007 + 3.46e-8*pAtm_)*611.21;
return p1*exp((18.678 - Tref_/234.5)*Tref_/(Tref_ + 257.14));
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::gamma() const
{
// (APR:Eq. 8)
return Cp_*pAtm_/(epsilon_*lambda());
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::lambda() const
{
// (BSG:Eq. 12)
const scalar T1 = Tref_ + 273.15;
const scalar T2 = Tref_ + 239.24;
return 1.91846e6*sqr(T1/T2);
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::ra() const
{
// (APR:Eq. 4), (BSG:Eq. 14)
const scalar log1 = log((zRefU_ - d_*h_)/(zom_*h_));
const scalar log2 = log((zRefH_ - d_*h_)/(zoh_*h_));
return log1*log2/(sqr(kappa_)*uRef_);
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::rs() const
{
// (BSG:Eq. 13), (APR:Eq. 5; reduced form in p. 4-5)
return ri_/(scalar(12)*h_);
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::S
(
const labelList& cells
) const
{
// Mark fvOption cells within mesh
bitSet isZoneCell(mesh().nCells());
isZoneCell.set(cells);
scalar S = 0;
// Select cells next to specified patches
// Sum patch area that is covered by fvOption cells
for (const label patchi : patchSet_)
{
const scalarField& s = mesh().magSf().boundaryField()[patchi];
const polyPatch& pp = mesh().boundaryMesh()[patchi];
const labelList& faceCells = pp.faceCells();
forAll(faceCells, i)
{
const bool isCovered = isZoneCell[faceCells[i]];
if (isCovered)
{
S += s[i];
}
}
}
reduce(S, sumOp<scalar>());
if (mag(S) < SMALL)
{
FatalErrorInFunction
<< "Area coverage of grass cannot be zero. "
<< "Check whether cellZone has any boundary faces."
<< exit(FatalError);
}
return S;
}
Foam::scalar Foam::evapotranspirationHeatTransferModels::grass::G
(
const labelList& cells
) const
{
switch (soilHeatFluxMethod_)
{
case soilHeatFluxType::PROPORTIONAL_TO_SOLAR_RADIATION:
{
return Csoil_*q();
}
case soilHeatFluxType::BOUNDARY:
{
// Retrieve heat flux through patches
tmp<FieldField<Field, scalar>> tqBf = this->qBf();
const FieldField<Field, scalar>& qBf = tqBf.cref();
// Mark fvOption cells within mesh
bitSet isZoneCell(mesh().nCells());
isZoneCell.set(cells);
scalar G = 0;
for (const label patchi : patchSet_)
{
const scalarField& s = mesh().magSf().boundaryField()[patchi];
const scalarField& qfld = qBf[patchi];
const polyPatch& pp = mesh().boundaryMesh()[patchi];
const labelList& faceCells = pp.faceCells();
forAll(faceCells, i)
{
const bool isCovered = isZoneCell[faceCells[i]];
if (isCovered)
{
G += qfld[i]*s[i];
}
}
}
reduce(G, sumOp<scalar>());
return G/area_;
}
}
return -1;
}
Foam::tmp<Foam::FieldField<Foam::Field, Foam::scalar>>
Foam::evapotranspirationHeatTransferModels::grass::qBf() const
{
const auto& T = mesh().lookupObject<volScalarField>(TName_);
const volScalarField::Boundary& Tbf = T.boundaryField();
auto tq = tmp<FieldField<Field, scalar>>::New(Tbf.size());
auto& q = tq.ref();
forAll(q, patchi)
{
q.set(patchi, new Field<scalar>(Tbf[patchi].size(), Zero));
}
typedef compressible::turbulenceModel cmpTurbModel;
if (mesh().foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
{
const auto& turb =
mesh().lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
// Note: calling he(p,T) instead of he()
const volScalarField he(turb.transport().he(turb.transport().p(), T));
const volScalarField::Boundary& hebf = he.boundaryField();
const volScalarField alphaEff(turb.alphaEff());
const volScalarField::Boundary& alphaEffbf = alphaEff.boundaryField();
for (const label patchi : patchSet_)
{
q[patchi] = alphaEffbf[patchi]*hebf[patchi].snGrad();
}
}
else if (mesh().foundObject<fluidThermo>(fluidThermo::dictName))
{
const auto& thermo =
mesh().lookupObject<fluidThermo>(fluidThermo::dictName);
// Note: calling he(p,T) instead of he()
const volScalarField he(thermo.he(thermo.p(), T));
const volScalarField::Boundary& hebf = he.boundaryField();
const volScalarField& alpha(thermo.alpha());
const volScalarField::Boundary& alphabf = alpha.boundaryField();
for (const label patchi : patchSet_)
{
q[patchi] = alphabf[patchi]*hebf[patchi].snGrad();
}
}
else
{
FatalErrorInFunction
<< "Unable to find a valid thermo model to evaluate q. " << nl
<< "Database contents are: " << mesh().objectRegistry::sortedToc()
<< exit(FatalError);
}
// No radiative heat flux contribution is present
return tq;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::evapotranspirationHeatTransferModels::grass::grass
(
const dictionary& dict,
const fvMesh& mesh
)
:
evapotranspirationHeatTransferModel(dict, mesh),
soilHeatFluxMethod_
(
soilHeatFluxTypeNames.getOrDefault
(
"soilHeatFluxMethod",
dict,
soilHeatFluxType::PROPORTIONAL_TO_SOLAR_RADIATION
)
),
Tptr_(nullptr),
RHptr_(nullptr),
area_(-1),
Csoil_(),
rho_(),
Cp_(),
epsilon_(),
h_(),
kappa_(),
uRef_(),
zRefU_(),
zRefH_(),
zom_(),
zoh_(),
d_(),
ri_(),
pAtm_(),
Tref_(0),
TName_(),
patchSet_()
{
Info<< " Activating evapotranspiration heat transfer model: "
<< typeName << endl;
read(dict);
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::tmp<Foam::scalarField>
Foam::evapotranspirationHeatTransferModels::grass::Q
(
const labelList& cells
) const
{
if (area_ == -1)
{
area_ = S(cells);
}
Tref_ = Tptr_->value(mesh().time().timeOutputValue());
return E(cells)*area_;
}
bool Foam::evapotranspirationHeatTransferModels::grass::read
(
const dictionary& dict
)
{
if (!evapotranspirationHeatTransferModel::read(dict))
{
return false;
}
Tptr_.reset(Function1<scalar>::New("Tref", dict, &mesh()));
RHptr_.reset(Function1<scalar>::New("RHref", dict, &mesh()));
area_ = -1;
const auto range = scalarMinMax::ge(SMALL);
Csoil_ = dict.getCheckOrDefault<scalar>("Csoil", 0.1, range);
rho_ = dict.getCheckOrDefault<scalar>("rho", 1.225, range);
Cp_ = dict.getCheckOrDefault<scalar>("Cp", 1013.0, range);
epsilon_ = dict.getCheckOrDefault<scalar>("epsilon", 0.622, range);
h_ = dict.getCheckOrDefault<scalar>("h", 0.1, range);
kappa_ = dict.getCheckOrDefault<scalar>("kappa", 0.41, range);
uRef_ = dict.getCheckOrDefault<scalar>("uRef", 2, range);
zRefU_ = dict.getCheckOrDefault<scalar>("zRefU", 10, range);
zRefH_ = dict.getCheckOrDefault<scalar>("zRefH", 10, range);
zom_ = dict.getCheckOrDefault<scalar>("zom", 0.123, range);
zoh_ = dict.getCheckOrDefault<scalar>("zoh", 0.0123, range);
d_ = dict.getCheckOrDefault<scalar>("d", 2.0/3.0, range);
ri_ = dict.getCheckOrDefault<scalar>("ri", 100, range);
pAtm_ = dict.getCheckOrDefault<scalar>("pAtm", 101.325, range);
TName_ = dict.getOrDefault<word>("T", "T");
if (soilHeatFluxMethod_ == soilHeatFluxType::BOUNDARY)
{
patchSet_ =
mesh().boundaryMesh().patchSet(dict.get<wordRes>("patches"));
}
return true;
}
// ************************************************************************* //

View File

@ -1,342 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::evapotranspirationHeatTransferModels::grass
Description
Applies sources on temperature (\c T - incompressible) or energy
(\c h/e - compressible) equation to incorporate evapotranspiration
heat-transfer effects from the specified grass canopy.
The model is based on Pemnan-Monteith Equation model.
Sources applied to either of the below, if exist:
\verbatim
T | Temperature [K]
e | Internal energy [m^2/s^2]
h | Enthalphy [m^2/s^2]
\endverbatim
Required fields:
\verbatim
T | Temperature [K]
e | Internal energy [m^2/s^2]
h | Enthalphy [m^2/s^2]
LAD | Leaf area density [m^2/m^3]
\endverbatim
References:
\verbatim
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
Governing equations (tag:APR):
Allen, R. G., Pereira, L. S., Raes, D., & Smith, M. (1998).
Crop evapotranspiration-Guidelines for computing crop
water requirements-FAO Irrigation and drainage paper 56.
Fao, Rome, 300(9), D05109.
\endverbatim
Usage
Example by using \c constant/fvOptions:
\verbatim
evapotranspirationHeatTransfer1
{
// Inherited entries
...
// Mandatory entries
model grass;
Tref <Function1<scalar>>;
RHref <Function1<scalar>>;
// Conditional entries
// when soilHeatFluxMethod == boundary
patches <wordRes>;
// Optional entries
soilHeatFluxMethod <word>;
Csoil <scalar>;
rho <scalar>;
Cp <scalar>;
epsilon <scalar>;
h <scalar>;
kappa <scalar>;
uRef <scalar>;
zRefU <scalar>;
zRefH <scalar>;
zom <scalar>;
zoh <scalar>;
d <scalar>;
ri <scalar>;
pAtm <scalar>;
T <word>;
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
model | Model name: grass | word | yes | -
Tref | Reference weather station air temperature [Celsius] <!--
--> | Function1\<scalar\> | yes | -
RHref | Reference weather station relative humidity [%] <!--
--> | Function1\<scalar\> | yes | -
patches | Names of ground patches | wordRes | yes | -
soilHeatFluxMethod | Method to calculate soil heat flux - see below <!--
--> | word | no | -
Csoil | Proportionality constant of soil heat-flux wrt <!--
--> solar radiation | scalar | no | 0.1
rho | Mean air density at constant pressure [kg/m^3] <!--
--> | scalar | no | 1.225
Cp | Specific heat at constant pressure [J/kg/C] <!--
--> | scalar | no | 1013.0
epsilon | Molecular-weight ratio of water vapour/dry air [-] <!--
--> | scalar | no | 0.622
h | Height of grass layer [m] | scalar | no | 0.1
kappa | Von Karman constant [-] | scalar | no | 0.41
uRef | Reference velocity magnitude [m/s] | scalar | no | 2.0
zRefU | Height of wind speed measurements [m] | scalar | no | 10.0
zRefH | Height of humidity measurements [m] | scalar | no | 10.0
zom | Roughness length governing momentum transfer coefficient <!--
--> [-] | scalar | no | 0.123
zoh | Roughness length governing transfer of heat and vapour <!--
--> coefficient [-] | scalar | no | 0.0123
d | Zero plane displacement height coefficient [-] <!--
--> | scalar | no | 0.666
ri | Bulk stomata resistance of leaf [s/m] | scalar | no | 100.0
pAtm | Atmospheric pressure [kPa] | scalar | no | 101.325
T | Name of temperature field | word | no | T
\endtable
Options for the \c soilHeatFluxMethod entry:
\verbatim
proportionalToSolarRadiation | Estimate from solar load
boundary | Obtain soil heat flux from boundary
\endverbatim
The inherited entries are elaborated in:
- \link evapotranspirationHeatTransfer.H \endlink
- \link evapotranspirationHeatTransferModel.H \endlink
SourceFiles
grass.C
grassTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_evapotranspirationHeatTransferModels_grass_H
#define Foam_evapotranspirationHeatTransferModels_grass_H
#include "evapotranspirationHeatTransferModel.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace evapotranspirationHeatTransferModels
{
/*---------------------------------------------------------------------------*\
Class grass Declaration
\*---------------------------------------------------------------------------*/
class grass
:
public evapotranspirationHeatTransferModel
{
// Private Enumerations
//- Options for the soil heat flux
enum soilHeatFluxType : char
{
PROPORTIONAL_TO_SOLAR_RADIATION = 0, //!< "Estimate from solar load"
BOUNDARY, //!< "Obtain soil heat flux from boundary"
};
//- Names for soilHeatFluxType
static const Enum<soilHeatFluxType> soilHeatFluxTypeNames;
// Private Data
//- Soil heat-flux calculation method
enum soilHeatFluxType soilHeatFluxMethod_;
//- Reference weather station air temperature [Celsius]
autoPtr<Function1<scalar>> Tptr_;
//- Reference weather station relative humidity [%]
autoPtr<Function1<scalar>> RHptr_;
//- Area coverage of grass [m^2]
mutable scalar area_;
//- Proportionality constant of soil heat-flux wrt solar radiation [-]
scalar Csoil_;
//- Mean air density at constant pressure [kg/m^3]
scalar rho_;
//- Specific heat at constant pressure [J/kg/C]
scalar Cp_;
//- Molecular-weight ratio of water vapour/dry air [-]
scalar epsilon_;
//- Height of grass layer [m]
scalar h_;
//- Von Karman constant [-]
scalar kappa_;
//- Reference velocity magnitude [m/s]
scalar uRef_;
//- Height of wind speed measurements [m]
scalar zRefU_;
//- Height of humidity measurements [m]
scalar zRefH_;
//- Roughness length governing momentum transfer coefficient [-]
scalar zom_;
//- Roughness length governing transfer of heat and vapour coeff [-]
scalar zoh_;
//- Zero plane displacement height coefficient [-]
scalar d_;
//- Bulk stomata resistance of leaf [s/m]
scalar ri_;
//- Atmospheric pressure [kPa]
scalar pAtm_;
//- Cached reference weather station air temperature [Celsius]
mutable scalar Tref_;
//- Name of temperature field
word TName_;
//- List of patches to calculate boundary heat flux
labelHashSet patchSet_;
// Private Member Functions
//- Return evapotranspiration heat flux through grass layer [W/m^2]
tmp<scalarField> E(const labelList& cells) const;
//- Return slope of the relation between
//- vapour pressure-temperature [Pa/K]
scalar Delta() const;
//- Return atmospheric vapour pressure deficit [Pa]
scalar D() const;
//- Return saturated vapour pressure over water [Pa]
scalar pSat() const;
//- Return psychrometric constant [kPa/K]
scalar gamma() const;
//- Return specific latent heat of vaporisation [MJ/kg]
scalar lambda() const;
//- Return bulk aerodynamic resistance [Pa]
scalar ra() const;
//- Return bulk surface resistance [Pa]
scalar rs() const;
//- Return area coverage of grass [m^2]
scalar S(const labelList& cells) const;
//- Return area-averaged heat flux through ground [W/m^2]
scalar G(const labelList& cells) const;
//- Return heat-flux boundary fields
tmp<FieldField<Field, scalar>> qBf() const;
public:
//- Runtime type information
TypeName("grass");
// Constructors
//- Construct from components
grass
(
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
grass(const grass&) = delete;
//- No copy assignment
void operator=(const grass&) = delete;
//- Destructor
virtual ~grass() = default;
// Member Functions
// Evaluation
//- Return heat-transfer rate for speficied cells [J/s]
virtual tmp<scalarField> Q(const labelList& cells) const;
// I-O
//- Read the dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace evapotranspirationHeatTransferModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,139 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "tree.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace evapotranspirationHeatTransferModels
{
defineTypeNameAndDebug(tree, 0);
addToRunTimeSelectionTable
(
evapotranspirationHeatTransferModel,
tree,
dictionary
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::scalar Foam::evapotranspirationHeatTransferModels::tree::Et() const
{
return a_*q() + b_;
}
Foam::tmp<Foam::scalarField>
Foam::evapotranspirationHeatTransferModels::tree::leafArea
(
const labelList& cells
) const
{
const volScalarField& LAD = getOrReadField(LADname_);
const scalarField& V = mesh().V();
auto tleafArea = tmp<scalarField>::New(cells.size(), Zero);
auto& leafArea = tleafArea.ref();
forAll(cells, i)
{
const label celli = cells[i];
leafArea[i] = LAD[celli]*V[celli];
}
return tleafArea;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::evapotranspirationHeatTransferModels::tree::tree
(
const dictionary& dict,
const fvMesh& mesh
)
:
evapotranspirationHeatTransferModel(dict, mesh),
a_(),
b_(),
lambda_(),
LADname_()
{
Info<< " Activating evapotranspiration heat transfer model: "
<< typeName << endl;
read(dict);
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::tmp<Foam::scalarField>
Foam::evapotranspirationHeatTransferModels::tree::Q
(
const labelList& cells
) const
{
// Convert units from [MJ g/hr] to [J kg/s]
static const scalar unitConverter = scalar(1000)/scalar(3600);
return unitConverter*lambda_*Et()*leafArea(cells);
}
bool Foam::evapotranspirationHeatTransferModels::tree::read
(
const dictionary& dict
)
{
if (!evapotranspirationHeatTransferModel::read(dict))
{
return false;
}
const auto range = scalarMinMax::ge(SMALL);
a_ = dict.getOrDefault<scalar>("a", 0.3622);
b_ = dict.getOrDefault<scalar>("b", 60.758);
lambda_ = dict.getCheckOrDefault<scalar>("lambda", 2.44, range);
LADname_ = dict.getOrDefault<word>("LAD", "LAD");
(void) getOrReadField(LADname_);
return true;
}
// ************************************************************************* //

View File

@ -1,219 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::evapotranspirationHeatTransferModels::tree
Description
Applies sources on temperature (\c T - incompressible) or energy
(\c h/e - compressible) equation to incorporate evapotranspiration
heat-transfer effects from the specified tree canopy.
The heat-transfer is calculated based on the following relations.
The heat transfer is given by the first equation and the
evapotranspiration is calculated linearly proportional to absorbed
solar radiation (direct and diffusive) with the empirical relation
shown in the second equation below.
\f[
Q = \lambda E_t \frac{1000}{3600} \int_{cellZone} LAD \, dV
\f]
where
\vartable
Q | Heat transfer from tree crown [W]
\lambda | Specific latent heat of vaporisation [MJ/kg]
E_t | Area-averaged evapotranspiration [g/m^2/hr]
LAD | Leaf area density [m^2/m^3]
V | Volume [m^3]
\endvartable
with
\f[
E_t = a R_n + b
\f]
where
\vartable
R_n | Heat flux through tree crown [W/m^2]
a | Linear-regression coefficient - slope parameter [g/W/hr]
b | Linear-regression coefficient - intercept parameter [g/m^2/hr]
\endvartable
Sources applied to either of the below, if exist:
\verbatim
T | Temperature [K]
e | Internal energy [m^2/s^2]
h | Enthalphy [m^2/s^2]
\endverbatim
Required fields:
\verbatim
T | Temperature [K]
e | Internal energy [m^2/s^2]
h | Enthalphy [m^2/s^2]
LAD | Leaf area density [m^2/m^3]
\endverbatim
Usage
Example by using \c constant/fvOptions:
\verbatim
evapotranspirationHeatTransfer1
{
// Inherited entries
...
// Mandatory entries
model tree;
// Optional entries
a <scalar>;
b <scalar>;
lambda <scalar>;
LAD <word>;
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
model | Model name: tree | word | yes | -
a | Linear-regression coefficient - slope parameter [g/W/hr] | scalar <!--
--> | no | 0.3622
b | Linear-regression coefficient - intercept parameter [g/m^2/hr] <!--
--> | scalar | no | 60.758
lambda | Specific latent heat of vaporisation [MJ/kg] | scalar <!--
--> | no | 2.44
LAD | Name of leaf-area density field | word | no | LAD
\endtable
The inherited entries are elaborated in:
- \link evapotranspirationHeatTransfer.H \endlink
- \link evapotranspirationHeatTransferModel.H \endlink
SourceFiles
tree.C
treeTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_evapotranspirationHeatTransferModels_tree_H
#define Foam_evapotranspirationHeatTransferModels_tree_H
#include "evapotranspirationHeatTransferModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace evapotranspirationHeatTransferModels
{
/*---------------------------------------------------------------------------*\
Class tree Declaration
\*---------------------------------------------------------------------------*/
class tree
:
public evapotranspirationHeatTransferModel
{
// Private Data
//- Linear-regression coefficient - slope parameter [g/W/hr]
scalar a_;
//- Linear-regression coefficient - intercept parameter [g/m^2/hr]
scalar b_;
//- Specific latent heat of vaporisation [MJ/kg]
scalar lambda_;
//- Name of leaf-area density field
word LADname_;
// Private Member Functions
//- Return area-averaged transpiration [g/m^2/hr]
// Calculated from empirical regressions with heat flux
scalar Et() const;
//- Return volume weighted leaf area density (LAD) [m^2]
// LAD [m^2/m^3]: one-sided area of leaves per unit volume
tmp<scalarField> leafArea(const labelList& cells) const;
public:
//- Runtime type information
TypeName("tree");
// Constructors
//- Construct from components
tree
(
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
tree(const tree&) = delete;
//- No copy assignment
void operator=(const tree&) = delete;
//- Destructor
virtual ~tree() = default;
// Member Functions
// Evaluation
//- Return heat-transfer rate for speficied cells [J/s]
virtual tmp<scalarField> Q(const labelList& cells) const;
// I-O
//- Read the dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace evapotranspirationHeatTransferModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,234 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "treeTurbulence.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
defineTypeNameAndDebug(treeTurbulence, 0);
addToRunTimeSelectionTable(option, treeTurbulence, dictionary);
}
}
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
Foam::volScalarField& Foam::fv::treeTurbulence::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::treeTurbulence::treeTurbulence
(
const word& sourceName,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
)
:
fv::cellSetOption(sourceName, modelType, dict, mesh),
isEpsilon_(true),
betaP_(),
betaD_(),
Ceps1_(),
Ceps2_(),
betaStar_(),
CdName_(),
LADname_()
{
read(dict);
const auto* turbPtr = mesh_.findObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
if (!turbPtr)
{
FatalErrorInFunction
<< "Unable to find a turbulence model."
<< abort(FatalError);
}
fieldNames_.resize(2);
tmp<volScalarField> tepsilon = turbPtr->epsilon();
tmp<volScalarField> tomega = turbPtr->omega();
if (!tepsilon.isTmp())
{
fieldNames_[0] = tepsilon().name();
}
else if (!tomega.isTmp())
{
isEpsilon_ = false;
fieldNames_[0] = tomega().name();
}
else
{
FatalErrorInFunction
<< "Unable to find epsilon or omega field." << nl
<< abort(FatalError);
}
fieldNames_[1] = turbPtr->k()().name();
fv::option::resetApplied();
Log << " Applying treeTurbulence to: "
<< fieldNames_[0] << " and " << fieldNames_[1]
<< endl;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fv::treeTurbulence::addSup
(
fvScalarMatrix& eqn,
const label fieldi
)
{
if (fieldi == 1)
{
kSource(geometricOneField(), geometricOneField(), eqn, fieldi);
return;
}
if (isEpsilon_)
{
epsilonSource(geometricOneField(), geometricOneField(), eqn, fieldi);
}
else
{
omegaSource(geometricOneField(), geometricOneField(), eqn, fieldi);
}
}
void Foam::fv::treeTurbulence::addSup
(
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
)
{
if (fieldi == 1)
{
kSource(geometricOneField(), rho, eqn, fieldi);
return;
}
if (isEpsilon_)
{
epsilonSource(geometricOneField(), rho, eqn, fieldi);
}
else
{
omegaSource(geometricOneField(), rho, eqn, fieldi);
}
}
void Foam::fv::treeTurbulence::addSup
(
const volScalarField& alpha,
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
)
{
if (fieldi == 1)
{
kSource(alpha, rho, eqn, fieldi);
return;
}
if (isEpsilon_)
{
epsilonSource(alpha, rho, eqn, fieldi);
}
else
{
omegaSource(alpha, rho, eqn, fieldi);
}
}
bool Foam::fv::treeTurbulence::read(const dictionary& dict)
{
if (!fv::cellSetOption::read(dict))
{
return false;
}
betaP_ = dict.getOrDefault<scalar>("betaP", 1.0);
betaD_ = dict.getOrDefault<scalar>("betaD", 4.0);
Ceps1_ = dict.getOrDefault<scalar>("Ceps1", 0.9);
Ceps2_ = dict.getOrDefault<scalar>("Ceps2", 0.9);
betaStar_ = dict.getOrDefault<scalar>("betaStar", 0.09);
CdName_ = dict.getOrDefault<word>("Cd", "Cd");
LADname_ = dict.getOrDefault<word>("LAD", "LAD");
(void) getOrReadField(CdName_);
(void) getOrReadField(LADname_);
return true;
}
// ************************************************************************* //

View File

@ -1,262 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::fv::treeTurbulence
Group
grpFvOptionsSources
Description
Applies sources on \c k and either \c epsilon or \c omega
to incorporate effects of trees on atmospheric boundary layer.
Corrections applied to:
\verbatim
k | Turbulent kinetic energy [m^2/s^2]
\endverbatim
Corrections applied to either of the below, if exist:
\verbatim
epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3]
omega | Specific dissipation rate [1/s]
\endverbatim
Required fields:
\verbatim
k | Turbulent kinetic energy [m^2/s^2]
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:
\verbatim
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
Example by using \c constant/fvOptions:
\verbatim
treeTurbulence1
{
// Mandatory entries
type treeTurbulence;
// Optional entries
Cd <word>;
LAD <word>;
betaP <scalar>;
betaD <scalar>;
Ceps1 <scalar>;
Ceps2 <scalar>;
betaStar <scalar>;
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: treeTurbulence | word | yes | -
Cd | Name of operand canopy drag coefficient field | word | no | Cd
LAD | Name of operand leaf area density field | word | no | LAD
betaP | Model coefficient | scalar | no | 1.0
betaD | Model coefficient | scalar | no | 4.0
Ceps1 | Model coefficient | scalar | no | 0.9
Ceps2 | Model coefficient | scalar | no | 0.9
betaStar | Model coefficient | scalar | no | 0.09
\endtable
The inherited entries are elaborated in:
- \link fvOption.H \endlink
- \link cellSetOption.H \endlink
SourceFiles
treeTurbulence.C
treeTurbulenceTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef fv_treeTurbulence_H
#define fv_treeTurbulence_H
#include "cellSetOption.H"
#include "turbulentTransportModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
/*---------------------------------------------------------------------------*\
Class treeTurbulence Declaration
\*---------------------------------------------------------------------------*/
class treeTurbulence
:
public fv::cellSetOption
{
// Private Data
//- Internal flag to determine the working field is epsilon or omega
bool isEpsilon_;
// Model coefficients
scalar betaP_;
scalar betaD_;
scalar Ceps1_;
scalar Ceps2_;
scalar betaStar_;
//- Name of operand canopy drag coefficient field
word CdName_;
//- 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;
//- Apply sources to turbulent kinetic energy
template<class AlphaFieldType, class RhoFieldType>
void kSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const;
//- Apply sources to turbulent kinetic energy dissipation rate
template<class AlphaFieldType, class RhoFieldType>
void epsilonSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const;
//- Apply sources to specific dissipation rate
template<class AlphaFieldType, class RhoFieldType>
void omegaSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const;
public:
//- Runtime type information
TypeName("treeTurbulence");
// Constructors
//- Construct from explicit source name and mesh
treeTurbulence
(
const word& sourceName,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
treeTurbulence(const treeTurbulence&) = delete;
//- No copy assignment
void operator=(const treeTurbulence&) = delete;
// Member Functions
//- Add explicit contribution to epsilon or omega equation
//- for incompressible flow computations
virtual void addSup
(
fvScalarMatrix& eqn,
const label fieldi
);
//- Add explicit contribution to epsilon or omega equation
//- for compressible flow computations
virtual void addSup
(
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
);
//- Add explicit contribution to epsilon or omega equation
//- for multiphase flow computations
virtual void addSup
(
const volScalarField& alpha,
const volScalarField& rho,
fvScalarMatrix& eqn,
const label fieldi
);
//- Read source dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fv
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "treeTurbulenceTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,124 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "treeTurbulence.H"
#include "volFields.H"
#include "fvmSup.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class AlphaFieldType, class RhoFieldType>
void Foam::fv::treeTurbulence::kSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const
{
const auto* turbPtr = mesh_.findObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
const volScalarField& k = turbPtr->k();
const volVectorField& U = turbPtr->U();
const volScalarField magU(mag(U));
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
// (BSG:Eq. 8)
eqn +=
alpha*rho*LAD*Cd*betaP_*pow3(magU)
- fvm::Sp(alpha*rho*LAD*Cd*betaD_*magU, k);
}
template<class AlphaFieldType, class RhoFieldType>
void Foam::fv::treeTurbulence::epsilonSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const
{
const auto* turbPtr = mesh_.findObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
const volScalarField& epsilon = turbPtr->epsilon();
const volScalarField& k = turbPtr->k();
const volVectorField& U = turbPtr->U();
const volScalarField magU(mag(U));
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
// (BSG:Eq. 9)
eqn +=
fvm::Sp
(
alpha*rho*LAD*Cd*(Ceps1_*betaP_/k*pow3(magU) - Ceps2_*betaD_*magU),
epsilon
);
}
template<class AlphaFieldType, class RhoFieldType>
void Foam::fv::treeTurbulence::omegaSource
(
const AlphaFieldType& alpha,
const RhoFieldType& rho,
fvScalarMatrix& eqn,
const label fieldi
) const
{
const auto* turbPtr = mesh_.findObject<turbulenceModel>
(
turbulenceModel::propertiesName
);
const volScalarField& omega = turbPtr->omega();
const volScalarField& k = turbPtr->k();
const volVectorField& U = turbPtr->U();
const volScalarField magU(mag(U));
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
// (derived from BSG:Eq. 9 by assuming epsilon = betaStar*omega*k)
eqn +=
fvm::Sp
(
alpha*rho*LAD*Cd*betaStar_
*(Ceps1_*betaP_*pow3(magU) - Ceps2_*betaD_*k*magU),
omega
);
}
// ************************************************************************* //

View File

@ -109,6 +109,19 @@ motionSolvers/displacement/solidBody/solidBodyMotionSolver.C
motionSolvers/displacement/solidBody/multiSolidBodyMotionSolver.C
motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
solidBodyMotionFunctions = motionSolvers/displacement/solidBody/solidBodyMotionFunctions
$(solidBodyMotionFunctions)/solidBodyMotionFunction/solidBodyMotionFunction.C
$(solidBodyMotionFunctions)/solidBodyMotionFunction/solidBodyMotionFunctionNew.C
$(solidBodyMotionFunctions)/SDA/SDA.C
$(solidBodyMotionFunctions)/tabulated6DoFMotion/tabulated6DoFMotion.C
$(solidBodyMotionFunctions)/linearMotion/linearMotion.C
$(solidBodyMotionFunctions)/drivenLinearMotion/drivenLinearMotion.C
$(solidBodyMotionFunctions)/rotatingMotion/rotatingMotion.C
$(solidBodyMotionFunctions)/axisRotationMotion/axisRotationMotion.C
$(solidBodyMotionFunctions)/multiMotion/multiMotion.C
$(solidBodyMotionFunctions)/oscillatingLinearMotion/oscillatingLinearMotion.C
$(solidBodyMotionFunctions)/oscillatingRotatingMotion/oscillatingRotatingMotion.C
motionSolvers/displacement/solidBody/pointPatchFields/derived/solidBodyMotionDisplacement/solidBodyMotionDisplacementPointPatchVectorField.C
createShellMesh/createShellMesh.C

View File

@ -39,12 +39,12 @@ Description
SourceFiles
solidBodyMotionFunction.C
solidBodyMotionFunctionNew.C
dynamicFvMeshNew.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_solidBodyMotionFunction_H
#define Foam_solidBodyMotionFunction_H
#ifndef solidBodyMotionFunction_H
#define solidBodyMotionFunction_H
#include "Time.H"
#include "dictionary.H"
@ -101,7 +101,7 @@ public:
// Constructors
//- Construct from the coefficients dictionary and Time
//- Construct from the SBMFCoeffs dictionary and Time
solidBodyMotionFunction
(
const dictionary& SBMFCoeffs,
@ -114,28 +114,10 @@ public:
// Selectors
//- Construct and dispatch motionType with dictionary and Time.
// Returns nullptr if motionType is empty
//- Select constructed from the SBMFCoeffs dictionary and Time
static autoPtr<solidBodyMotionFunction> New
(
const word& motionType,
const dictionary& dict,
const Time& runTime
);
//- Select "solidBodyMotionFunction" type from dictionary
//- and create with Time.
static autoPtr<solidBodyMotionFunction> New
(
const dictionary& dict,
const Time& runTime
);
//- Select "solidBodyMotionFunction" type (if present) from dictionary
//- and create with Time.
static autoPtr<solidBodyMotionFunction> NewIfPresent
(
const dictionary& dict,
const dictionary& SBMFCoeffs,
const Time& runTime
);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2024 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,18 +30,15 @@ License
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::solidBodyMotionFunction>
Foam::solidBodyMotionFunction::New
Foam::autoPtr<Foam::solidBodyMotionFunction> Foam::solidBodyMotionFunction::New
(
const word& motionType,
const dictionary& dict,
const Time& runTime
)
{
if (motionType.empty())
{
return nullptr;
}
const word motionType(dict.get<word>("solidBodyMotionFunction"));
Info<< "Selecting solid-body motion function " << motionType << endl;
auto* ctorPtr = dictionaryConstructorTable(motionType);
@ -56,45 +53,8 @@ Foam::solidBodyMotionFunction::New
) << exit(FatalIOError);
}
Info<< "Selecting solid-body motion function " << motionType << endl;
return autoPtr<solidBodyMotionFunction>(ctorPtr(dict, runTime));
}
Foam::autoPtr<Foam::solidBodyMotionFunction>
Foam::solidBodyMotionFunction::New
(
const dictionary& dict,
const Time& runTime
)
{
return New
(
dict.get<word>("solidBodyMotionFunction", keyType::LITERAL),
dict,
runTime
);
}
Foam::autoPtr<Foam::solidBodyMotionFunction>
Foam::solidBodyMotionFunction::NewIfPresent
(
const dictionary& dict,
const Time& runTime
)
{
word motionType;
dict.readIfPresent("solidBodyMotionFunction", motionType, keyType::LITERAL);
if (motionType.empty())
{
return nullptr;
}
return New(motionType, dict, runTime);
}
// ************************************************************************* //

View File

@ -2817,7 +2817,7 @@ void Foam::polyMeshAdder::add
if (newNei < newOwn)
{
std::swap(newOwn, newNei);
newFace.flip();
newFace = newFace.reverseFace();
flipFaceFlux = !flipFaceFlux;
for (bool& flip : flips)
{

View File

@ -109,21 +109,7 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
<< exit(FatalIOError);
}
// Tricky: avoid call to evaluate without call to initEvaluate.
// For now just disable the localConsistency to make it use the
// old logic (ultimately calls the fully self contained
// patchNeighbourField)
int& consistency =
GeometricField<Type, fvPatchField, volMesh>::
Boundary::localConsistency;
const int oldConsistency = consistency;
consistency = 0;
this->evaluate(Pstream::commsTypes::blocking);
consistency = oldConsistency;
}
}

View File

@ -44,6 +44,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p)),
lowWeightOption_(lowWeightCorrectionBase::option::ASSIGN),
patchNeighbourFieldPtr_(nullptr)
{}
@ -59,6 +60,15 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p, dict)),
lowWeightOption_
(
lowWeightCorrectionBase::optionNames_.getOrDefault
(
"lowWeightOption",
dict,
lowWeightCorrectionBase::option::ASSIGN
)
),
patchNeighbourFieldPtr_(nullptr)
{
if (!isA<cyclicAMIFvPatch>(p))
@ -92,21 +102,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
{
if (this->coupled())
{
// Tricky: avoid call to evaluate without call to initEvaluate.
// For now just disable the localConsistency to make it use the
// old logic (ultimately calls the fully self contained
// patchNeighbourField)
int& consistency =
GeometricField<Type, fvPatchField, volMesh>::
Boundary::localConsistency;
const int oldConsistency = consistency;
consistency = 0;
this->evaluate(UPstream::commsTypes::nonBlocking);
consistency = oldConsistency;
}
else
{
@ -128,6 +124,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, p, iF, mapper),
cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p)),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
//if (ptf.patchNeighbourFieldPtr_ && cacheNeighbourField())
@ -166,6 +163,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf),
cyclicAMIPatch_(ptf.cyclicAMIPatch_),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
if (debug && !ptf.all_ready())
@ -187,6 +185,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
cyclicAMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, iF),
cyclicAMIPatch_(ptf.cyclicAMIPatch_),
lowWeightOption_(ptf.lowWeightOption_),
patchNeighbourFieldPtr_(nullptr)
{
if (debug && !ptf.all_ready())
@ -312,7 +311,8 @@ Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField
defaultValues = Field<Type>(iField, cyclicAMIPatch_.faceCells());
}
tmp<Field<Type>> tpnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
tmp<Field<Type>> tpnf =
cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
if (doTransform())
{
@ -540,7 +540,8 @@ void Foam::cyclicAMIFvPatchField<Type>::evaluate
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_,
defaultValues
defaultValues,
lowWeightOption_
).ptr()
);
@ -666,7 +667,8 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
solveScalarField::null(), // Not used for distributed
recvRequests_,
scalarRecvBufs_,
defaultValues
defaultValues,
lowWeightOption_
);
// Receive requests all handled by last function call
@ -688,7 +690,7 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
// Transform according to the transformation tensors
transformCoupleField(pnf, cmpt);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
}
// Multiply the field by coefficients and add into the result
@ -800,7 +802,8 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_,
defaultValues
defaultValues,
lowWeightOption_
);
// Receive requests all handled by last function call
@ -822,7 +825,7 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
defaultValues = Field<Type>(psiInternal, faceCells);
}
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues);
pnf = cyclicAMIPatch_.interpolate(pnf, defaultValues, lowWeightOption_);
}
// Multiply the field by coefficients and add into the result
@ -1008,6 +1011,12 @@ void Foam::cyclicAMIFvPatchField<Type>::write(Ostream& os) const
{
patchNeighbourFieldPtr_->writeEntry("neighbourValue", os);
}
os.writeEntry
(
"lowWeightOption",
lowWeightCorrectionBase::optionNames_[lowWeightOption_]
);
}

View File

@ -71,6 +71,7 @@ SourceFiles
#include "cyclicAMIFvPatch.H"
#include "coupledFvPatchField.H"
#include "cyclicAMILduInterfaceField.H"
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -92,6 +93,10 @@ class cyclicAMIFvPatchField
//- Local reference cast into the cyclic patch
const cyclicAMIFvPatch& cyclicAMIPatch_;
//- Low weight correction mode
// Default: assign (same as v2312 and earlier)
lowWeightCorrectionBase::option lowWeightOption_;
// Sending and receiving (distributed AMI)

View File

@ -29,6 +29,7 @@ License
#include "addToRunTimeSelectionTable.H"
#include "faceAreaWeightAMI.H"
#include "turbulentDFSEMInletFvPatchVectorField.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -82,14 +83,8 @@ void Foam::turbulentDigitalFilterInletFvPatchField<Type>::mapL
}
// Map two-point correlations (integral scales)
plusEqOp<Type> cop;
AMIPtr_->interpolateToSource
(
sourceFld,
multiplyWeightedOp<Type, plusEqOp<Type>>(cop),
fld,
UList<Type>::null()
);
AMIMultiplyWeightedOp<Type> cop(AMIPtr_(), true);
AMIPtr_->interpolate(sourceFld, cop, fld, UList<Type>::null());
// Map forward-stepwise method correlations if requested
if (L_.fsm())

View File

@ -100,12 +100,19 @@ void Foam::cyclicACMIFvPatch::makeWeights(scalarField& w) const
// These deltas are of the cyclic part alone - they are
// not affected by the amount of overlap with the nonOverlapPatch
scalarField nbrDeltas
scalarField nbrDeltas;
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<scalar>(AMI, owner());
AMI.interpolate
(
interpolate
(
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta()
)
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
nbrDeltas,
UList<scalar>()
);
const scalar tol = cyclicACMIPolyPatch::tolerance();
@ -244,31 +251,35 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
const vectorField patchD(coupledFvPatch::delta());
vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta()));
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<vector>(AMI, owner());
vectorField nbrPatchD;
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
nbrPatchD,
UList<vector>()
);
// Do the transformation if necessary
if (!parallel())
{
transform(nbrPatchD, forwardT()[0], nbrPatchD);
}
auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref();
// do the transformation if necessary
if (parallel())
forAll(patchD, facei)
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
}
else
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - transform(forwardT()[0], dni);
}
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
pdv[facei] = ddi - dni;
}
return tpdv;

View File

@ -251,7 +251,7 @@ public:
localFld,
requests,
recvBuffers,
UList<Type>()
UList<Type>::null()
);
}

View File

@ -97,32 +97,50 @@ void Foam::cyclicAMIFvPatch::makeWeights(scalarField& w) const
{
const cyclicAMIFvPatch& nbrPatch = neighbFvPatch();
const scalarField deltas(nf() & coupledFvPatch::delta());
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
tmp<scalarField> tnbrDeltas;
auto tnbrDeltas = tmp<scalarField>::New();
if (applyLowWeightCorrection())
{
tnbrDeltas =
interpolate
(
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta(),
scalarField(this->size(), 1.0)
);
// Use 'assign' correction for geometric interpolation
auto cop = AMICorrectedMultiplyWeightedOp<scalar>
(
AMI,
owner(),
lowWeightCorrectionBase::option::ASSIGN
);
// Faces with invalid interpolation weights converted to one-sided
AMI.interpolate
(
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
tnbrDeltas.ref(),
scalarList(this->size(), 1.0)
);
}
else
{
tnbrDeltas =
interpolate(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta());
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<scalar>(AMI, owner());
AMI.interpolate
(
(nbrPatch.nf() & nbrPatch.coupledFvPatch::delta())(),
cop,
tnbrDeltas.ref(),
UList<scalar>::null()
);
}
const scalarField& nbrDeltas = tnbrDeltas();
const scalarField deltas(nf() & coupledFvPatch::delta());
forAll(deltas, facei)
{
// Note use of mag
scalar di = mag(deltas[facei]);
scalar dni = mag(nbrDeltas[facei]);
w[facei] = dni/(di + dni);
}
}
@ -162,46 +180,58 @@ Foam::tmp<Foam::vectorField> Foam::cyclicAMIFvPatch::delta() const
{
const vectorField patchD(coupledFvPatch::delta());
tmp<vectorField> tnbrPatchD;
const auto& AMI = owner() ? this->AMI() : nbrPatch.AMI();
auto tnbrPatchD = tmp<vectorField>::New();
if (applyLowWeightCorrection())
{
tnbrPatchD =
interpolate
(
nbrPatch.coupledFvPatch::delta(),
vectorField(this->size(), Zero)
);
// Use 'assign' correction for geometric interpolation
auto cop = AMICorrectedMultiplyWeightedOp<vector>
(
AMI,
owner(),
lowWeightCorrectionBase::option::ASSIGN
);
// Faces with invalid interpolation weights converted to one-sided
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
tnbrPatchD.ref(),
vectorField(this->size(), Zero)
);
}
else
{
tnbrPatchD = interpolate(nbrPatch.coupledFvPatch::delta());
// Multiply-weighted op - no low weight correction
auto cop = AMIMultiplyWeightedOp<vector>(AMI, owner());
AMI.interpolate
(
nbrPatch.coupledFvPatch::delta()(),
cop,
tnbrPatchD.ref(),
UList<vector>::null()
);
}
const vectorField& nbrPatchD = tnbrPatchD();
vectorField& nbrPatchD = tnbrPatchD.ref();
// Do the transformation if necessary
if (!parallel())
{
transform(nbrPatchD, forwardT()[0], nbrPatchD);
}
auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref();
// do the transformation if necessary
if (parallel())
forAll(patchD, facei)
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
}
else
{
forAll(patchD, facei)
{
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - transform(forwardT()[0], dni);
}
const vector& ddi = patchD[facei];
const vector& dni = nbrPatchD[facei];
pdv[facei] = ddi - dni;
}
return tpdv;

View File

@ -217,20 +217,34 @@ public:
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const
{
return cyclicAMIPolyPatch_.interpolate(fld, defaultValues);
return cyclicAMIPolyPatch_.interpolate
(
fld,
defaultValues,
lwOption
);
}
template<class Type>
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const
{
return cyclicAMIPolyPatch_.interpolate(tFld, defaultValues);
return cyclicAMIPolyPatch_.interpolate
(
tFld,
defaultValues,
lwOption
);
}

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::AMIFieldOP
Description
General template for AMI field operations
\*---------------------------------------------------------------------------*/
#ifndef AMIFieldOp_H
#define AMIFieldOp_H
#include "AMIFieldOpBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIFieldOp Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class CombineOp>
class AMIFieldOp
:
public AMIFieldOpBase
{
// Private Data
//- Combine operator, e.g. plusEqOp<Type>()
// Note: must be null-constructed
CombineOp cop_;
public:
typedef Type value_type;
//- Constructor
AMIFieldOp(const AMIInterpolation& ami, bool toSource)
:
AMIFieldOpBase(ami, toSource),
cop_()
{}
//- Destructor
~AMIFieldOp() = default;
//- Apply the op
// Note: does not use default values
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& /* unused defaultValues */
) const
{
const auto& address = this->address();
forAll(result, facei)
{
const labelList& faceSlots = address[facei];
forAll(faceSlots, i)
{
if (i == 0)
{
result[facei] = fld[faceSlots[i]];
}
else
{
cop_(result[facei], fld[faceSlots[i]]);
}
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::AMIFieldOpBase
Description
Base class for AMI field operations
\*---------------------------------------------------------------------------*/
#ifndef AMIFieldOpsBase_H
#define AMIFieldOpsBase_H
#include "AMIInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIFieldOpBase Declaration
\*---------------------------------------------------------------------------*/
class AMIFieldOpBase
{
protected:
//- Reference to the AMI
const AMIInterpolation& ami_;
//- Interpolation to source; false=interpolate to target
const bool toSource_;
public:
//- Constructor
AMIFieldOpBase(const AMIInterpolation& ami, const bool toSource)
:
ami_(ami),
toSource_(toSource)
{}
// Member Functions
//- Return the 'toSource' flag
bool toSource() const
{
return toSource_;
}
//- Return the AMI addressing
const labelListList& address() const
{
return toSource_ ? ami_.srcAddress() : ami_.tgtAddress();
}
//- Return the AMI weights
const scalarListList& weights() const
{
return toSource_ ? ami_.srcWeights() : ami_.tgtWeights();
}
//- Return the AMI sum of weights
const scalarList& weightsSum() const
{
return toSource_ ? ami_.srcWeightsSum() : ami_.tgtWeightsSum();
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 OpenCFD Ltd.
Copyright (C) 2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,38 +25,34 @@ License
\*---------------------------------------------------------------------------*/
#include "evapotranspirationHeatTransferModel.H"
#include "fvMesh.H"
#ifndef AMIFieldOps_H
#define AMIFieldOps_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::evapotranspirationHeatTransferModel>
Foam::evapotranspirationHeatTransferModel::New
(
const dictionary& dict,
const fvMesh& mesh
)
#include "ops.H"
#include "AMIFieldOp.H"
#include "AMIMultiplyWeightedOp.H"
#include "LowWeightCorrection.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
word modelType(dict.get<word>("model"));
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
template<class Type>
using AMIMaxOp = AMIFieldOp<Type, maxEqOp<Type>>;
if (!cstrIter.found())
{
FatalIOErrorInLookup
(
dict,
"model",
modelType,
*dictionaryConstructorTablePtr_
) << exit(FatalIOError);
}
template<class Type>
using AMIMinOp = AMIFieldOp<Type, minEqOp<Type>>;
return autoPtr<evapotranspirationHeatTransferModel>
(
cstrIter()(dict, mesh)
);
template<class Type>
using AMICorrectedMultiplyWeightedOp =
LowWeightCorrection<AMIMultiplyWeightedOp<Type>, plusEqOp<Type>>;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
#ifndef AMIMultiplyWeightedOp_H
#define AMIMultiplyWeightedOp_H
#include "AMIFieldOpBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class AMIMultiplyWeightedOp Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class CombineOp = plusEqOp<Type>>
class AMIMultiplyWeightedOp
:
public AMIFieldOpBase
{
// Private Data
//- Combine operator, e.g. plusEqOp<Type>()
// Note: must be null-constructed
CombineOp cop_;
public:
typedef Type value_type;
//- Constructor
AMIMultiplyWeightedOp
(
const AMIInterpolation& ami,
const bool toSource
)
:
AMIFieldOpBase(ami, toSource),
cop_()
{}
//- Multiply-weighted op
// Note: does not use default values
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& /* unused defaultValues */
) const
{
const auto& address = this->address();
const auto& weights = this->weights();
forAll(result, facei)
{
const labelList& faceSlots = address[facei];
const scalarList& faceWeights = weights[facei];
forAll(faceSlots, i)
{
if (i == 0)
{
result[facei] = faceWeights[i]*fld[faceSlots[i]];
}
else
{
cop_(result[facei], faceWeights[i]*fld[faceSlots[i]]);
}
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::LowWeightCorrection
Description
Wrapper around the AMI field op
\*---------------------------------------------------------------------------*/
#ifndef LowWeightCorrection_H
#define LowWeightCorrection_H
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class LowWeightCorrection Declaration
\*---------------------------------------------------------------------------*/
template<class AMIOpType, class CombineOp>
class LowWeightCorrection
:
public lowWeightCorrectionBase,
public AMIOpType
{
typedef typename AMIOpType::value_type value_type;
public:
//- Constructor
LowWeightCorrection
(
const AMIInterpolation& ami,
const bool toSource,
const lowWeightCorrectionBase::option& opt =
lowWeightCorrectionBase::option::NONE
)
:
lowWeightCorrectionBase(opt),
AMIOpType(ami, toSource)
{}
// Member Functions
//- Helper function to ensure default value field is valid
bool validDefaults(const UList<value_type>& defaultValues) const
{
const auto& ami = AMIOpType::ami_;
if (ami.lowWeightCorrection() > 0)
{
const auto& weightsSum = this->weightsSum();
if (defaultValues.size() != weightsSum.size())
{
FatalErrorInFunction
<< "Employing default values when sum of weights "
<< "falls below " << ami.lowWeightCorrection()
<< " but number of default values is not equal to "
<< "addressing size" << nl
<< " default values size = "
<< defaultValues.size() << nl
<< " addressing size = "
<< weightsSum.size() << nl
<< abort(FatalError);
}
return true;
}
return false;
}
//- Correction operator
void operator()
(
List<value_type>& result,
const UList<value_type>& fld,
const UList<value_type>& defaultValues
) const
{
// Apply AMI interpolator
AMIOpType::operator()(result, fld, UList<value_type>::null());
if (!validDefaults(defaultValues)) return;
switch (opt_)
{
case option::NONE:
{
break;
}
case option::ASSIGN:
{
const auto& ami = AMIOpType::ami_;
const auto& weightsSum = this->weightsSum();
forAll(result, facei)
{
if (weightsSum[facei] < ami.lowWeightCorrection())
{
// Assign default value
result[facei] = defaultValues[facei];
}
}
break;
}
case option::BLEND:
{
const auto& ami = AMIOpType::ami_;
const auto& weightsSum = this->weightsSum();
forAll(result, facei)
{
if (weightsSum[facei] < ami.lowWeightCorrection())
{
// Already have 'weightSum' contribution in result
// - blend 'missing' contribution into result
const scalar w = min(1, max(0, weightsSum[facei]));
result[facei] += (1 - w)*defaultValues[facei];
}
}
break;
}
default:
{
FatalErrorInFunction
<< "Unhandled enumeration " << static_cast<int>(opt_)
<< abort(FatalError);
}
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum<Foam::lowWeightCorrectionBase::option>
Foam::lowWeightCorrectionBase::optionNames_
({
{ option::NONE, "none" },
{ option::ASSIGN, "assign" },
{ option::BLEND, "blend" },
});
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lowWeightCorrectionBase::lowWeightCorrectionBase(const option& opt)
:
opt_(opt)
{}
// ************************************************************************* //

View File

@ -0,0 +1,90 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::lowWeightCorrectionBase
Description
Base class for AMI low weight corrections
\*---------------------------------------------------------------------------*/
#ifndef lowWeightCorrectionBase_H
#define lowWeightCorrectionBase_H
#include "Enum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class lowWeightCorrectionBase Declaration
\*---------------------------------------------------------------------------*/
class lowWeightCorrectionBase
{
public:
enum class option
{
NONE,
ASSIGN,
BLEND
};
static const Enum<option> optionNames_;
protected:
// Protected Data
//- Option
option opt_;
public:
//- Constructors
lowWeightCorrectionBase(const option& opt = option::NONE);
//- Destructor
~lowWeightCorrectionBase() = default;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1123,6 +1123,36 @@ void Foam::AMIInterpolation::normaliseWeights
}
void Foam::AMIInterpolation::removeSourceConnection(const label facei)
{
if (facei < 0 || facei > srcAddress_.size())
{
FatalErrorInFunction
<< "Face index " << facei << " out of bonds"
<< abort(FatalError);
}
srcWeightsSum_[facei] = 0;
srcWeights_[facei].clear();
srcAddress_[facei].clear();
}
void Foam::AMIInterpolation::removeTargetConnection(const label facei)
{
if (facei < 0 || facei > tgtAddress_.size())
{
FatalErrorInFunction
<< "Face index " << facei << " out of bonds"
<< abort(FatalError);
}
tgtWeightsSum_[facei] = 0;
tgtWeights_[facei].clear();
tgtAddress_[facei].clear();
}
Foam::label Foam::AMIInterpolation::srcPointFace
(
const primitivePatch& srcPatch,

View File

@ -61,7 +61,7 @@ SourceFiles
#include "indexedOctree.H"
#include "treeDataPrimitivePatch.H"
#include "runTimeSelectionTables.H"
#include "lowWeightCorrectionBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -512,39 +512,21 @@ public:
//- Normalise the weights
void normaliseWeights(const bool conformal, const bool output);
//- Remove source face connection
void removeSourceConnection(const label facei);
//- Remove target face connection
void removeTargetConnection(const label facei);
// Evaluation
// Low-level
//- Weighted sum of contributions
//- Interpolate with supplied op to combine existing value
//- with remote value and weight
template<class Type, class CombineOp>
static void weightedSum
(
const scalar lowWeightCorrection,
const labelListList& allSlots,
const scalarListList& allWeights,
const scalarField& weightsSum,
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
);
//- Weighted sum of contributions
template<class Type>
void weightedSum
(
const bool interpolateToSource,
const UList<Type>& fld,
List<Type>& result,
const UList<Type>& defaultValues
) const;
//- Interpolate from target to source with supplied op
//- to combine existing value with remote value and weight
template<class Type, class CombineOp>
void interpolateToSource
void interpolate
(
const UList<Type>& fld,
const CombineOp& cop,
@ -552,48 +534,18 @@ public:
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source to target with supplied op
//- to combine existing value with remote value and weight
template<class Type, class CombineOp>
void interpolateToTarget
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from target to source with supplied op
//- Interpolate with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToSource
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from target tmp field to source with supplied op
//- Interpolate with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToSource
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source to target with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToTarget
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues = UList<Type>::null()
) const;
//- Interpolate from source tmp field to target with supplied op
template<class Type, class CombineOp>
tmp<Field<Type>> interpolateToTarget
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
@ -605,7 +557,9 @@ public:
tmp<Field<Type>> interpolateToSource
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from target tmp field
@ -613,7 +567,9 @@ public:
tmp<Field<Type>> interpolateToSource
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from source to target
@ -621,7 +577,9 @@ public:
tmp<Field<Type>> interpolateToTarget
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate from source tmp field
@ -629,7 +587,9 @@ public:
tmp<Field<Type>> interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>::null()
const UList<Type>& defaultValues = UList<Type>::null(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;

View File

@ -28,266 +28,80 @@ License
#include "profiling.H"
#include "mapDistribute.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type, class CombineOp>
void Foam::AMIInterpolation::weightedSum
void Foam::AMIInterpolation::interpolate
(
const scalar lowWeightCorrection,
const labelListList& allSlots,
const scalarListList& allWeights,
const scalarField& weightsSum,
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
)
) const
{
if (lowWeightCorrection > 0)
{
forAll(result, facei)
{
if (weightsSum[facei] < lowWeightCorrection)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& slots = allSlots[facei];
const scalarList& weights = allWeights[facei];
addProfiling(ami, "AMIInterpolation::interpolate");
forAll(slots, i)
{
cop(result[facei], facei, fld[slots[i]], weights[i]);
}
}
}
label inSize = cop.toSource() ? tgtAddress_.size() : srcAddress_.size();
if (fld.size() != inSize)
{
FatalErrorInFunction
<< "Supplied field size is not equal to expected field size ("
<< inSize << ")" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
label outSize = cop.toSource() ? srcAddress_.size() : tgtAddress_.size();
result.resize_nocopy(outSize);
if (distributed())
{
const auto& map = cop.toSource() ? tgtMapPtr_() : srcMapPtr_();
List<Type> work = fld; // deep copy
map.distribute(work);
// Apply interpolation
cop(result, work, defaultValues);
}
else
{
forAll(result, facei)
{
const labelList& slots = allSlots[facei];
const scalarList& weights = allWeights[facei];
forAll(slots, i)
{
cop(result[facei], facei, fld[slots[i]], weights[i]);
}
}
// Apply interpolation
cop(result, fld, defaultValues);
}
}
template<class Type>
void Foam::AMIInterpolation::weightedSum
(
const bool interpolateToSource,
const UList<Type>& fld,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
weightedSum
(
lowWeightCorrection_,
(interpolateToSource ? srcAddress_ : tgtAddress_),
(interpolateToSource ? srcWeights_ : tgtWeights_),
(interpolateToSource ? srcWeightsSum_ : tgtWeightsSum_),
fld,
multiplyWeightedOp<Type, plusEqOp<Type>>(plusEqOp<Type>()),
result,
defaultValues
);
}
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToTarget
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToTarget");
if (fld.size() != srcAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to source patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
else if
(
(lowWeightCorrection_ > 0)
&& (defaultValues.size() != tgtAddress_.size())
)
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but supplied default field size is not equal to target "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< abort(FatalError);
}
result.setSize(tgtAddress_.size());
List<Type> work;
if (distributed())
{
const mapDistribute& map = srcMapPtr_();
work = fld; // deep copy
map.distribute(work);
}
weightedSum
(
lowWeightCorrection_,
tgtAddress_,
tgtWeights_,
tgtWeightsSum_,
(distributed() ? work : fld),
cop,
result,
defaultValues
);
}
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToSource
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToSource");
if (fld.size() != tgtAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to target patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
else if
(
(lowWeightCorrection_ > 0)
&& (defaultValues.size() != srcAddress_.size())
)
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but number of default values is not equal to source "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " source patch = " << srcAddress_.size() << nl
<< abort(FatalError);
}
result.setSize(srcAddress_.size());
List<Type> work;
if (distributed())
{
const mapDistribute& map = tgtMapPtr_();
work = fld; // deep copy
map.distribute(work);
}
weightedSum
(
lowWeightCorrection_,
srcAddress_,
srcWeights_,
srcWeightsSum_,
(distributed() ? work : fld),
cop,
result,
defaultValues
);
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolate
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(srcAddress_.size(), Zero);
auto tresult = tmp<Field<Type>>::New();
interpolateToSource
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
interpolate(fld, cop, tresult.ref(), defaultValues);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolate
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToSource(tFld(), cop, defaultValues);
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(tgtAddress_.size(), Zero);
interpolateToTarget
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToTarget(tFld(), cop, defaultValues);
return interpolate(tFld(), cop, defaultValues);
}
@ -295,10 +109,13 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToSource(fld, plusEqOp<Type>(), defaultValues);
AMICorrectedMultiplyWeightedOp<Type> cop(*this, true, lwOption);
return interpolate(fld, cop, defaultValues);
}
@ -306,10 +123,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToSource(tFld(), plusEqOp<Type>(), defaultValues);
return interpolateToSource(tFld(), defaultValues, lwOption);
}
@ -317,10 +135,13 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToTarget(fld, plusEqOp<Type>(), defaultValues);
AMICorrectedMultiplyWeightedOp<Type> cop(*this, false, lwOption);
return interpolate(fld, cop, defaultValues);
}
@ -328,10 +149,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolateToTarget(tFld(), plusEqOp<Type>(), defaultValues);
return interpolateToTarget(tFld(), defaultValues, lwOption);
}

View File

@ -292,14 +292,15 @@ void Foam::cyclicACMIGAMGInterfaceField::updateInterfaceMatrix
recvRequests_.clear();
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicACMIInterface_.owner(),
work,
pnf, // result
solveScalarField::null()
AMI,
cyclicACMIInterface_.owner()
);
cop(pnf, work, solveScalarField::null());
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
}

View File

@ -306,13 +306,14 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
recvRequests_.clear();
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
// Note: no low-weight correction
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicAMIInterface_.owner(),
work,
pnf, // result
defaultValues
AMI,
cyclicAMIInterface_.owner()
);
cop(pnf, work, defaultValues);
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
@ -329,13 +330,14 @@ void Foam::cyclicAMIGAMGInterfaceField::updateInterfaceMatrix
transformCoupleField(work, cmpt);
solveScalarField pnf(faceCells.size(), Zero);
AMI.weightedSum
// Note: no low-weight correction
AMIMultiplyWeightedOp<solveScalar> cop
(
cyclicAMIInterface_.owner(),
work,
pnf, // result
defaultValues
AMI,
cyclicAMIInterface_.owner()
);
cop(pnf, work, defaultValues);
// Add result using coefficients
this->addToInternalField(result, !add, faceCells, coeffs, pnf);

View File

@ -446,6 +446,54 @@ void Foam::cyclicAMIPolyPatch::resetAMI(const UList<point>& points) const
{
AMIPtr_->checkSymmetricWeights(true);
}
// Check connectivity
if (applyLowWeightCorrection() || !AMIPtr_->requireMatch())
{
Info<< "AMI: performing connectivity checks" << endl;
const auto& C = boundaryMesh().mesh().cellCentres();
auto cosTheta =
[&](const polyPatch& p1, const polyPatch& p2, const bool toSource)
{
const auto& Cf1 = p1.faceCentres();
const auto& faceCells1 = p1.faceCells();
vectorField delta1(p1.size());
forAll(delta1, i)
{
delta1[i] = Cf1[i] - C[faceCells1[i]];
}
// Interpolate nbr delta to local (src) side using (uncorrected)
// multiply-weighted op
const AMIMultiplyWeightedOp<vector> cop(*AMIPtr_, toSource);
AMIPtr_->interpolate(delta1, cop, UList<vector>::null());
delta1.normalise();
return delta1 & p2.faceNormals();
};
const scalarField ctSrc(cosTheta(*this, nbr, true));
forAll(ctSrc, facei)
{
if (ctSrc[facei] < 0)
{
AMIPtr_->removeSourceConnection(facei);
}
}
const scalarField ctTgt(cosTheta(nbr, *this, false));
forAll(ctTgt, facei)
{
if (ctTgt[facei] < 0)
{
AMIPtr_->removeTargetConnection(facei);
}
}
}
}

View File

@ -483,7 +483,9 @@ public:
tmp<Field<Type>> interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate tmp field
@ -491,7 +493,9 @@ public:
tmp<Field<Type>> interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues = UList<Type>()
const UList<Type>& defaultValues = UList<Type>(),
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Interpolate without periodic
@ -499,7 +503,9 @@ public:
tmp<Field<Type>> interpolateUntransformed
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;
//- Low-level interpolate List
@ -541,7 +547,9 @@ public:
const Field<Type>& localFld,
const labelRange& requests, // The receive requests
const PtrList<List<Type>>& recvBuffers,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption =
lowWeightCorrectionBase::option::ASSIGN
) const;

View File

@ -26,22 +26,30 @@ License
\*---------------------------------------------------------------------------*/
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolateUntransformed
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
if (owner())
{
return AMI().interpolateToSource(fld, defaultValues);
return AMI().interpolateToSource(fld, defaultValues, lwOption);
}
else
{
return neighbPatch().AMI().interpolateToTarget(fld, defaultValues);
return neighbPatch().AMI().interpolateToTarget
(
fld,
defaultValues,
lwOption
);
}
}
@ -50,7 +58,8 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
autoPtr<coordSystem::cylindrical> cs;
@ -65,7 +74,7 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
if (!cs)
{
return interpolateUntransformed(fld, defaultValues);
return interpolateUntransformed(fld, defaultValues, lwOption);
}
else
{
@ -141,7 +150,7 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
return Foam::transform
(
ownT,
interpolateUntransformed(localFld, localDeflt)
interpolateUntransformed(localFld, localDeflt, lwOption)
);
}
}
@ -151,10 +160,11 @@ template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
return interpolate(tFld(), defaultValues);
return interpolate(tFld(), defaultValues, lwOption);
}
@ -245,7 +255,8 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
const Field<Type>& localFld,
const labelRange& requests,
const PtrList<List<Type>>& recvBuffers,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const lowWeightCorrectionBase::option& lwOption
) const
{
const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
@ -272,13 +283,9 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
if (!cs)
{
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
defaultValues
);
AMICorrectedMultiplyWeightedOp<Type> cop(AMI, owner(), lwOption);
cop(tresult.ref(), fld, defaultValues);
}
else
{
@ -296,13 +303,8 @@ Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
Foam::invTransform(localDeflt, ownT, defaultFld);
}
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
localDeflt
);
AMICorrectedMultiplyWeightedOp<Type> cop(AMI, owner(), lwOption);
cop(tresult.ref(), fld, defaultValues);
// Transform back
Foam::transform(tresult.ref(), ownT, tresult());
@ -356,26 +358,7 @@ void Foam::cyclicAMIPolyPatch::interpolate
}
// Do actual AMI interpolation
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
localDeflt
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
localDeflt
);
}
AMI().interpolate(fld, cop, result, defaultValues);
// Transform back. Result is now at *this
Foam::transform(result, ownT, result);
@ -383,26 +366,7 @@ void Foam::cyclicAMIPolyPatch::interpolate
else
*/
{
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
defaultValues
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
defaultValues
);
}
AMI().interpolate(fld, cop, result, defaultValues);
}
}

View File

@ -276,6 +276,7 @@ processorLOD/cellBox/cellBox.C
processorLOD/faceBox/faceBox.C
AMI=AMIInterpolation
$(AMI)/AMIInterpolation/AMIFieldOps/lowWeightCorrectionBase.C
$(AMI)/AMIInterpolation/AMIInterpolation.C
$(AMI)/AMIInterpolation/AMIInterpolationNew.C
$(AMI)/AMIInterpolation/advancingFrontAMI/advancingFrontAMI.C
@ -354,18 +355,4 @@ tetOverlapVolume/tetOverlapVolume.C
triangulatedPatch/triangulatedPatch.C
solidBodyMotion = solidBodyMotionFunctions
$(solidBodyMotion)/solidBodyMotionFunction/solidBodyMotionFunction.C
$(solidBodyMotion)/solidBodyMotionFunction/solidBodyMotionFunctionNew.C
$(solidBodyMotion)/SDA/SDA.C
$(solidBodyMotion)/tabulated6DoFMotion/tabulated6DoFMotion.C
$(solidBodyMotion)/linearMotion/linearMotion.C
$(solidBodyMotion)/drivenLinearMotion/drivenLinearMotion.C
$(solidBodyMotion)/rotatingMotion/rotatingMotion.C
$(solidBodyMotion)/axisRotationMotion/axisRotationMotion.C
$(solidBodyMotion)/multiMotion/multiMotion.C
$(solidBodyMotion)/oscillatingLinearMotion/oscillatingLinearMotion.C
$(solidBodyMotion)/oscillatingRotatingMotion/oscillatingRotatingMotion.C
LIB = $(FOAM_LIBBIN)/libmeshTools

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
LIB_LIBS = \
-lfileFormats \

View File

@ -38,6 +38,7 @@ License
#include "typeInfo.H"
#include "SubField.H"
#include "globalMeshData.H"
#include "AMIFieldOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -95,6 +96,73 @@ namespace Foam
}
}
};
// Combine operator for AMIInterpolation
template<class Type, class TrackingData>
class combineField
:
public AMIFieldOpBase
{
// Private Data
FaceCellWave<Type, TrackingData>& solver_;
const cyclicAMIPolyPatch& patch_;
public:
combineField
(
FaceCellWave<Type, TrackingData>& solver,
const cyclicAMIPolyPatch& patch
)
:
AMIFieldOpBase(patch.AMI(), patch.owner()),
solver_(solver),
patch_(patch)
{}
void operator()
(
List<Type>& result,
const UList<Type>& fld,
const UList<Type>& /* unused defaultValues */
) const
{
const auto& allSlots = address();
forAll(result, facei)
{
const labelList& slots = allSlots[facei];
for (const label sloti : slots)
{
if (fld[sloti].valid(solver_.data()))
{
label meshFacei = -1;
if (patch_.owner())
{
meshFacei = patch_.start() + facei;
}
else
{
meshFacei =
patch_.neighbPatch().start() + facei;
}
result[facei].updateFace
(
solver_.mesh(),
meshFacei,
fld[sloti],
solver_.propagationTol(),
solver_.data()
);
}
}
}
}
};
}
@ -782,7 +850,7 @@ void Foam::FaceCellWave<Type, TrackingData>::handleAMICyclicPatches()
}
// Transfer sendInfo to cycPatch
combine<Type, TrackingData> cmb(*this, cycPatch);
combineField<Type, TrackingData> cmb(*this, cycPatch);
if (cycPatch.applyLowWeightCorrection())
{

View File

@ -26,6 +26,9 @@ License
\*---------------------------------------------------------------------------*/
#include "AMIFieldOps.H"
template<class Type>
void Foam::mappedPatchBase::distribute(List<Type>& lst) const
{
@ -120,7 +123,9 @@ void Foam::mappedPatchBase::distribute
const label oldWarnComm = UPstream::commWarn(myComm);
const label oldWorldComm = UPstream::commWorld(myComm);
lst = interp.interpolateToSource(Field<Type>(std::move(lst)), cop);
const auto op = AMIFieldOp<Type, CombineOp>(interp, cop, true);
lst = interp.interpolate(Field<Type>(std::move(lst)), op);
UPstream::commWarn(oldWarnComm);
UPstream::commWorld(oldWorldComm);
@ -206,7 +211,9 @@ void Foam::mappedPatchBase::reverseDistribute
const label oldWarnComm = UPstream::commWarn(myComm);
const label oldWorldComm = UPstream::commWorld(myComm);
lst = interp.interpolateToTarget(Field<Type>(std::move(lst)), cop);
const auto op = AMIFieldOp<Type, CombineOp>(interp, false);
lst = interp.interpolate(Field<Type>(std::move(lst)), op);
UPstream::commWarn(oldWarnComm);
UPstream::commWorld(oldWorldComm);

View File

@ -90,10 +90,10 @@ Foam::boundaryToCell::boundaryToCell(const polyMesh& mesh)
Foam::boundaryToCell::boundaryToCell
(
const polyMesh& mesh,
const dictionary& dict
const dictionary&
)
:
topoSetCellSource(mesh, dict)
topoSetCellSource(mesh)
{}

View File

@ -92,8 +92,7 @@ static void readBoxDim(const dictionary& dict, treeBoundBox& bb)
void Foam::boxToCell::combine(topoSet& set, const bool add) const
{
const tmp<pointField> tctrs(this->transform(mesh_.cellCentres()));
const pointField& ctrs = tctrs();
const pointField& ctrs = mesh_.cellCentres();
forAll(ctrs, elemi)
{
@ -139,7 +138,7 @@ Foam::boxToCell::boxToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
bbs_()
{
// Accept 'boxes', 'box' or 'min/max'

View File

@ -50,7 +50,7 @@ Usage
source boxToCell;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
boxes

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -60,8 +60,7 @@ Foam::cellToCell::cellToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, setName),
isZone_(false)
names_(one{}, setName)
{}
@ -71,10 +70,16 @@ Foam::cellToCell::cellToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
names_(),
isZone_(topoSetSource::readNames(dict, names_))
{}
topoSetCellSource(mesh),
names_()
{
// Look for 'sets' or 'set'
if (!dict.readIfPresent("sets", names_))
{
names_.resize(1);
dict.readEntry("set", names_.front());
}
}
Foam::cellToCell::cellToCell
@ -84,8 +89,7 @@ Foam::cellToCell::cellToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, word(checkIs(is))),
isZone_(false)
names_(one{}, word(checkIs(is)))
{}
@ -101,44 +105,30 @@ void Foam::cellToCell::applyToSet
{
if (verbose_)
{
Info<< " Adding all elements of cell "
<< (isZone_ ? "zones: " : "sets: ")
Info<< " Adding all elements of cell sets: "
<< flatOutput(names_) << nl;
}
for (const word& setName : names_)
{
if (isZone_)
{
set.addSet(mesh_.cellZones()[setName]);
}
else
{
cellSet loadedSet(mesh_, setName);
set.addSet(loadedSet);
}
cellSet loadedSet(mesh_, setName);
set.addSet(loadedSet);
}
}
else if (action == topoSetSource::SUBTRACT)
{
if (verbose_)
{
Info<< " Removing all elements of cell "
<< (isZone_ ? "zones: " : "sets: ")
Info<< " Removing all elements of cell sets: "
<< flatOutput(names_) << nl;
}
for (const word& setName : names_)
{
if (isZone_)
{
set.subtractSet(mesh_.cellZones()[setName]);
}
else
{
cellSet loadedSet(mesh_, setName);
set.subtractSet(loadedSet);
}
cellSet loadedSet(mesh_, setName);
set.subtractSet(loadedSet);
}
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,8 +28,7 @@ Class
Foam::cellToCell
Description
A \c topoSetCellSource to select all the cells from given \c cellSet(s)
or \c cellZone(s).
A \c topoSetCellSource to select all the cells from given \c cellSet(s).
Operands:
\table
@ -51,7 +50,7 @@ Usage
source cellToCell;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
sets
@ -62,18 +61,7 @@ Usage
);
// Option-2
zones
(
<cellZoneName0>
<cellZoneName1>
...
);
// Option-3
set <cellSetName>;
// Option-4
zone <cellZoneName>;
set <cellSetName>;
}
\endverbatim
@ -93,15 +81,17 @@ Usage
subtract | Remove selected cells from this cellSet
\endverbatim
Options for the conditional mandatory entries (in order of precedence):
Options for the conditional mandatory entries:
\verbatim
Entry | Description | Type | Req'd | Dflt
sets | Names of input cellSets | wordList | cond'l | -
zones | Names of input cellZones | wordList | cond'l | -
set | Name of input cellSet | word | cond'l | -
zone | Name of input cellZone | word | cond'l | -
\endverbatim
Note
The order of precedence among the conditional mandatory entries from the
highest to the lowest is \c sets, and \c set.
See also
- Foam::topoSetSource
- Foam::topoSetCellSource
@ -111,8 +101,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_cellToCell_H
#define Foam_cellToCell_H
#ifndef cellToCell_H
#define cellToCell_H
#include "topoSetCellSource.H"
@ -134,12 +124,9 @@ class cellToCell
//- Add usage string
static addToUsageTable usage_;
//- Names of sets or zones to use
//- Names of sets to use
wordList names_;
//- Is name a set or a zone
const bool isZone_;
public:

View File

@ -69,8 +69,7 @@ void Foam::clipPlaneToCell::combine(topoSet& set, const bool add) const
{
// Cell centres above the plane
const tmp<pointField> tctrs(this->transform(mesh_.cellCentres()));
const pointField& ctrs = tctrs();
const pointField& ctrs = mesh_.cellCentres();
forAll(ctrs, elemi)
{
@ -103,9 +102,12 @@ Foam::clipPlaneToCell::clipPlaneToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
point_(dict.get<vector>("point")),
normal_(dict.get<vector>("normal"))
clipPlaneToCell
(
mesh,
dict.get<vector>("point"),
dict.get<vector>("normal")
)
{}

View File

@ -68,8 +68,7 @@ Foam::topoSetSource::addToUsageTable Foam::cylinderToCell::usage_
void Foam::cylinderToCell::combine(topoSet& set, const bool add) const
{
const tmp<pointField> tctrs(this->transform(mesh_.cellCentres()));
const pointField& ctrs = tctrs();
const pointField& ctrs = mesh_.cellCentres();
const vector axis = (point2_ - point1_);
const scalar magAxis2 = magSqr(axis);
@ -128,12 +127,12 @@ Foam::cylinderToCell::cylinderToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
point1_(dict.getCompat<point>("point1", {{"p1", -2112}})),
point2_(dict.getCompat<point>("point2", {{"p2", -2112}})),
radius_(dict.getCompat<scalar>("radius", {{"outerRadius", -2112}})),
innerRadius_
cylinderToCell
(
mesh,
dict.getCompat<point>("point1", {{"p1", -2112}}),
dict.getCompat<point>("point2", {{"p2", -2112}}),
dict.getCompat<scalar>("radius", {{"outerRadius", -2112}}),
dict.getCheckOrDefault<scalar>("innerRadius", 0, scalarMinMax::ge(0))
)
{}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -66,14 +66,18 @@ Foam::faceToCell::faceActionNames_
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Selector>
void Foam::faceToCell::combineImpl
void Foam::faceToCell::combine
(
topoSet& set,
const bool add,
const Selector& faceLabels
const word& setName
) const
{
// Load the set
faceSet loadedSet(mesh_, setName);
const labelHashSet& faceLabels = loadedSet;
// Handle owner/neighbour/any selection
for (const label facei : faceLabels)
{
@ -100,7 +104,7 @@ void Foam::faceToCell::combineImpl
{
// Count number of selected faces per cell.
Map<label> facesPerCell(faceLabels.size());
Map<label> facesPerCell(loadedSet.size());
for (const label facei : faceLabels)
{
@ -130,31 +134,6 @@ void Foam::faceToCell::combineImpl
}
void Foam::faceToCell::combine
(
topoSet& set,
const bool add,
const word& setName
) const
{
if (isZone_)
{
const labelList& faceLabels = mesh_.faceZones()[setName];
combineImpl(set, add, faceLabels);
}
else
{
// Load the set
faceSet loadedSet(mesh_, setName);
const labelHashSet& faceLabels = loadedSet;
combineImpl(set, add, faceLabels);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faceToCell::faceToCell
@ -165,8 +144,7 @@ Foam::faceToCell::faceToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, setName),
isZone_(false),
names_(one{}, setName),
option_(option)
{}
@ -177,11 +155,17 @@ Foam::faceToCell::faceToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
names_(),
isZone_(topoSetSource::readNames(dict, names_)),
option_(faceActionNames_.get("option", dict))
{}
{
// Look for 'sets' or 'set'
if (!dict.readIfPresent("sets", names_))
{
names_.resize(1);
dict.readEntry("set", names_.front());
}
}
Foam::faceToCell::faceToCell
@ -191,8 +175,7 @@ Foam::faceToCell::faceToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, word(checkIs(is))),
isZone_(false),
names_(one{}, word(checkIs(is))),
option_(faceActionNames_.read(checkIs(is)))
{}
@ -209,9 +192,8 @@ void Foam::faceToCell::applyToSet
{
if (verbose_)
{
Info<< " Adding cells according to face "
<< (isZone_ ? "zones: " : "sets: ")
<< flatOutput(names_) << nl;
Info<< " Adding cells according to face sets: "
<< flatOutput(names_) << endl;
}
for (const word& setName : names_)
@ -223,9 +205,8 @@ void Foam::faceToCell::applyToSet
{
if (verbose_)
{
Info<< " Removing cells according to face "
<< (isZone_ ? "zones: " : "sets: ")
<< flatOutput(names_) << nl;
Info<< " Removing cells according to face sets: "
<< flatOutput(names_) << endl;
}
for (const word& setName : names_)

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -53,7 +53,7 @@ Usage
option <option>;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
sets
@ -64,18 +64,7 @@ Usage
);
// Option-2
zones
(
<faceZoneName0>
<faceZoneName1>
...
);
// Option-3
set <faceSetName>;
// Option-4
zone <faceZoneName>;
}
\endverbatim
@ -104,15 +93,17 @@ Usage
neighbour | Cells that are neighbour of given faces
\endverbatim
Options for the conditional mandatory entries (in order of precedence):
Options for the conditional mandatory entries:
\verbatim
Entry | Description | Type | Req'd | Dflt
sets | Names of input faceSets | wordList | cond'l | -
zones | Names of input faceZones | wordList | cond'l | -
set | Name of input faceSet | word | cond'l | -
zone | Name of input faceZone | word | cond'l | -
\endverbatim
Note
The order of precedence among the conditional mandatory entries from the
highest to the lowest is \c sets, and \c set.
See also
- Foam::topoSetSource
- Foam::topoSetCellSource
@ -123,8 +114,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_faceToCell_H
#define Foam_faceToCell_H
#ifndef faceToCell_H
#define faceToCell_H
#include "topoSetCellSource.H"
#include "Enum.H"
@ -162,27 +153,15 @@ private:
//- Add usage string
static addToUsageTable usage_;
//- Names of sets or zones to use
//- Names of sets to use
wordList names_;
//- Is name a set or a zone
const bool isZone_;
//- Option
faceAction option_;
// Private Member Functions
//- Depending on face to cell option add to or delete from cellSet.
template<class Selector>
void combineImpl
(
topoSet& set,
const bool add,
const Selector& faceLabels
) const;
//- Depending on face to cell option add to or delete from cellSet.
void combine(topoSet& set, const bool add, const word& setName) const;

View File

@ -214,7 +214,7 @@ Foam::faceZoneToCell::faceZoneToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
zoneMatcher_(),
option_(faceActionNames_.get("option", dict))
{

View File

@ -52,7 +52,7 @@ Usage
option <option>;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
zones
@ -63,7 +63,7 @@ Usage
);
// Option-2
zone <faceZoneName>;
set <faceZoneName>;
}
\endverbatim

View File

@ -148,10 +148,13 @@ Foam::fieldToCell::fieldToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
fieldName_(dict.get<word>("field")),
min_(dict.get<scalar>("min")),
max_(dict.get<scalar>("max"))
fieldToCell
(
mesh,
dict.get<word>("field"),
dict.get<scalar>("min"),
dict.get<scalar>("max")
)
{}

View File

@ -198,8 +198,7 @@ Foam::haloToCell::haloToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
steps_(dict.getOrDefault<label>("steps", 1))
haloToCell(mesh, dict.getOrDefault<label>("steps", 1))
{}

View File

@ -94,8 +94,7 @@ Foam::labelToCell::labelToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
labels_(dict.get<labelList>("value"))
labelToCell(mesh, dict.get<labelList>("value"))
{}

View File

@ -74,7 +74,6 @@ void Foam::nbrToCell::combine(topoSet& set, const bool add) const
}
const cellList& cells = mesh().cells();
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
boolList isCoupled(mesh_.nBoundaryFaces(), false);
@ -137,8 +136,7 @@ Foam::nbrToCell::nbrToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
minNbrs_(dict.getCheck<label>("neighbours", labelMinMax::ge(1)))
nbrToCell(mesh, dict.getCheck<label>("neighbours", labelMinMax::ge(1)))
{}

View File

@ -127,8 +127,11 @@ Foam::nearestToCell::nearestToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
points_(dict.get<pointField>("points"))
nearestToCell
(
mesh,
dict.get<pointField>("points")
)
{}

View File

@ -125,7 +125,7 @@ Foam::patchToCell::patchToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
selectedPatches_()
{
// Look for 'patches' and 'patch', but accept 'name' as well

View File

@ -48,7 +48,7 @@ Usage
source patchToCell;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
patches

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -64,14 +64,18 @@ Foam::pointToCell::pointActionNames_
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Selector>
void Foam::pointToCell::combineImpl
void Foam::pointToCell::combine
(
topoSet& set,
const bool add,
const Selector& pointLabels
const word& setName
) const
{
// Load the set
pointSet loadedSet(mesh_, setName);
const labelHashSet& pointLabels = loadedSet;
// Handle any selection
if (option_ == ANY)
{
@ -110,31 +114,6 @@ void Foam::pointToCell::combineImpl
}
void Foam::pointToCell::combine
(
topoSet& set,
const bool add,
const word& setName
) const
{
if (isZone_)
{
const labelList& pointLabels = mesh_.pointZones()[setName];
combineImpl(set, add, pointLabels);
}
else
{
// Load the set
pointSet loadedSet(mesh_, setName);
const labelHashSet& pointLabels = loadedSet;
combineImpl(set, add, pointLabels);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::pointToCell::pointToCell
@ -145,8 +124,7 @@ Foam::pointToCell::pointToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, setName),
isZone_(false),
names_(one{}, setName),
option_(option)
{}
@ -157,11 +135,17 @@ Foam::pointToCell::pointToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
names_(),
isZone_(topoSetSource::readNames(dict, names_)),
option_(pointActionNames_.get("option", dict))
{}
{
// Look for 'sets' or 'set'
if (!dict.readIfPresent("sets", names_))
{
names_.resize(1);
dict.readEntry("set", names_.front());
}
}
Foam::pointToCell::pointToCell
@ -171,8 +155,7 @@ Foam::pointToCell::pointToCell
)
:
topoSetCellSource(mesh),
names_(Foam::one{}, word(checkIs(is))),
isZone_(false),
names_(one{}, word(checkIs(is))),
option_(pointActionNames_.read(checkIs(is)))
{}
@ -189,8 +172,7 @@ void Foam::pointToCell::applyToSet
{
if (verbose_)
{
Info<< " Adding cells according to point "
<< (isZone_ ? "zones: " : "sets: ")
Info<< " Adding cells according to point sets: "
<< flatOutput(names_) << nl;
}
@ -203,8 +185,7 @@ void Foam::pointToCell::applyToSet
{
if (verbose_)
{
Info<< " Removing cells according to point "
<< (isZone_ ? "zones: " : "sets: ")
Info<< " Removing cells according to point sets: "
<< flatOutput(names_) << nl;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -52,7 +52,7 @@ Usage
option <option>;
// Conditional mandatory entries
// Select one of the below
// Select either of the below
// Option-1
sets
@ -62,19 +62,8 @@ Usage
...
);
// Option-3
zones
(
<pointZoneName0>
<pointZoneName1>
...
);
// Option-3
set <pointSetName>;
// Option-4
zone <pointZoneName>;
// Option-2
set <pointSetName>;
}
\endverbatim
@ -101,15 +90,17 @@ Usage
edge | Cells using an edge with both points in pointSet
\endverbatim
Options for the conditional mandatory entries (in order of precedence):
Options for the conditional mandatory entries:
\verbatim
Entry | Description | Type | Req'd | Dflt
sets | Names of input pointSets | wordList | cond'l | -
zones | Names of input pointZones | wordList | cond'l | -
set | Name of input pointSet | word | cond'l | -
zone | Name of input pointZone | word | cond'l | -
\endverbatim
Note
The order of precedence among the conditional mandatory entries from the
highest to the lowest is \c sets, and \c set.
See also
- Foam::topoSetSource
- Foam::topoSetCellSource
@ -119,8 +110,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_pointToCell_H
#define Foam_pointToCell_H
#ifndef pointToCell_H
#define pointToCell_H
#include "topoSetCellSource.H"
#include "Enum.H"
@ -157,27 +148,15 @@ private:
static const Enum<pointAction> pointActionNames_;
//- Names of sets or zones to use
//- Names of sets to use
wordList names_;
//- Is name a set or a zone
const bool isZone_;
//- Selection type
pointAction option_;
// Private Member Functions
//- Depending on point to cell option add to or delete from cellSet.
template<class Selector>
void combineImpl
(
topoSet& set,
const bool add,
const Selector& pointLabels
) const;
//- Depending on point-to-cell option add to or delete from cellSet.
void combine(topoSet& set, const bool add, const word& setName) const;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2024 OpenCFD Ltd.
Copyright (C) 2015-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -346,33 +346,18 @@ void Foam::regionToCell::combine(topoSet& set, const bool add) const
// Note: wip. Select cells first
boolList selectedCell(mesh_.nCells(), true);
if (!setName_.empty() && setName_ != "none")
if (setName_.size() && setName_ != "none")
{
if (isZone_)
Info<< " Loading subset " << setName_
<< " to delimit search region."
<< endl;
cellSet subSet(mesh_, setName_);
selectedCell = false;
for (const label celli : subSet)
{
Info<< " Using cellZone " << setName_
<< " to delimit search region."
<< endl;
selectedCell = false;
for (const label celli : mesh_.cellZones()[setName_])
{
selectedCell[celli] = true;
}
}
else
{
Info<< " Loading cellSet " << setName_
<< " to delimit search region."
<< endl;
cellSet subSet(mesh_, setName_);
selectedCell = false;
for (const label celli : subSet)
{
selectedCell[celli] = true;
}
selectedCell[celli] = true;
}
}
@ -407,7 +392,6 @@ Foam::regionToCell::regionToCell
:
topoSetCellSource(mesh),
setName_(setName),
isZone_(false),
insidePoints_(insidePoints),
nErode_(nErode)
{}
@ -419,25 +403,14 @@ Foam::regionToCell::regionToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
setName_(),
isZone_(false),
topoSetCellSource(mesh),
setName_(dict.getOrDefault<word>("set", "none")),
insidePoints_
(
dict.getCompat<pointField>("insidePoints", {{ "insidePoint", 0 }})
),
nErode_(dict.getCheckOrDefault<label>("nErode", 0, labelMinMax::ge(0)))
{
// A single set or zone only!
if (dict.readIfPresent("set", setName_))
{
isZone_ = false;
}
else if (dict.readIfPresent("zone", setName_))
{
isZone_ = true;
}
}
{}
Foam::regionToCell::regionToCell
@ -448,7 +421,6 @@ Foam::regionToCell::regionToCell
:
topoSetCellSource(mesh),
setName_(checkIs(is)),
isZone_(false),
insidePoints_(checkIs(is)),
nErode_(readLabel(checkIs(is)))
{}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -59,7 +59,6 @@ Usage
// Optional entries
set <cellSetName>;
zone <cellZoneName>;
nErode <label>;
}
\endverbatim
@ -94,8 +93,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_regionToCell_H
#define Foam_regionToCell_H
#ifndef regionToCell_H
#define regionToCell_H
#include "topoSetCellSource.H"
#include "boolList.H"
@ -120,11 +119,8 @@ class regionToCell
//- Add usage string
static addToUsageTable usage_;
//- Name of cellSet or cellZone to keep to
word setName_;
//- Is name a set or a zone
bool isZone_;
//- Name of cellSet to keep to
const word setName_;
//- Coordinate(s) that is inside connected region
const pointField insidePoints_;

View File

@ -96,8 +96,7 @@ void Foam::rotatedBoxToCell::combine(topoSet& set, const bool add) const
// Check whether cell centre is inside all faces of box.
const tmp<pointField> tctrs(this->transform(mesh_.cellCentres()));
const pointField& ctrs = tctrs();
const pointField& ctrs = mesh_.cellCentres();
forAll(ctrs, celli)
{
@ -147,11 +146,14 @@ Foam::rotatedBoxToCell::rotatedBoxToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
origin_(dict.get<point>("origin")),
i_(dict.get<vector>("i")),
j_(dict.get<vector>("j")),
k_(dict.get<vector>("k"))
rotatedBoxToCell
(
mesh,
dict.get<point>("origin"),
dict.get<vector>("i"),
dict.get<vector>("j"),
dict.get<vector>("k")
)
{}

View File

@ -102,13 +102,9 @@ void Foam::searchableSurfaceToCell::combine(topoSet& set, const bool add) const
{
return;
}
const tmp<pointField> tctrs(this->transform(mesh_.cellCentres()));
const pointField& ctrs = tctrs();
const pointField& ctrs = mesh_.cellCentres();
const searchableSurface& s = *surf_;
// Cell centres within the enclosing volumes
List<volumeType> volTypes;
@ -134,7 +130,7 @@ Foam::searchableSurfaceToCell::searchableSurfaceToCell
const dictionary& dict
)
:
topoSetCellSource(mesh, dict),
topoSetCellSource(mesh),
surf_
(
searchableSurface::New

Some files were not shown because too many files have changed in this diff Show More