Compare commits

..

5 Commits

14 changed files with 365 additions and 1442 deletions

View File

@ -1157,6 +1157,34 @@ Foam::label Foam::checkGeometry
globalFaces,
globalPoints
);
if (cpp.sameWorld())
{
//- Get the patch on the region
const polyPatch& nbrPp = cpp.samplePolyPatch();
// Collect neighbour geometry
faceList mergedFaces;
pointField mergedPoints;
autoPtr<globalIndex> globalFaces;
autoPtr<globalIndex> globalPoints;
collectAndWriteAMIWeights
(
cpp.sampleMesh(),
wr,
outputDir / pName + "-tgt_" + tmName,
ami.tgtWeightsSum(),
nbrPp.localFaces(),
nbrPp.meshPoints(),
nbrPp.meshPointMap(),
mergedFaces,
mergedPoints,
globalFaces,
globalPoints
);
}
}
}
}

View File

@ -43,8 +43,9 @@ Description
- volScalarField with regions as different scalars (-detectOnly)
or
- mesh with multiple regions and mapped patches. These patches
either cover the whole interface between two region (default) or
only part according to faceZones (-useFaceZones)
either cover the whole interface between two region (default),
only part according to faceZones (-useFaceZones) or be auto-generated
according to an AMI method (see below)
or
- mesh with cells put into cellZones (-makeCellZones)
@ -57,7 +58,7 @@ Description
-combineZones '((zoneA "zoneB.*")(none otherZone))
This can be combined with e.g. 'cellZones' or 'cellZonesOnly'. The
addZones option supplies the destination region name as first element in
the list. The combineZones option synthesises the region name e.g.
the list. The combineZones option synthesises the region name e.g.
zoneA_zoneB0_zoneB1
- cellZonesOnly does not do a walk and uses the cellZones only. Use
@ -98,6 +99,14 @@ Description
- boundaryRegionAddressing : for every patch in this region the
patch in the original mesh (or -1 if added patch)
- auto-generate patches using AMI area-overlap detection. This requires a
patchSet to apply it to and an optional AMIMethod (default is
faceAreaWeightAMI2D).
-autoPatch '("solid*")'
-AMIMethod faceAreaWeightAMI2D
Any mapped patch thus generated should probably use the
nearestPatchFaceAMI sampling method.
\*---------------------------------------------------------------------------*/
#include "argList.H"
@ -116,6 +125,7 @@ Description
#include "fvMeshTools.H"
#include "zeroGradientFvPatchFields.H"
#include "processorMeshes.H"
#include "faceAreaWeightAMI2D.H"
using namespace Foam;
@ -317,12 +327,115 @@ void addToInterface
}
labelList getMinBoundaryValue
(
const polyMesh& mesh,
const word& AMIMethod,
const labelList& matchPatchIDs,
const labelList& cellRegion
)
{
// Neighbour cellRegion.
labelList coupledRegion(mesh.nBoundaryFaces());
forAll(coupledRegion, i)
{
label celli = mesh.faceOwner()[i+mesh.nInternalFaces()];
coupledRegion[i] = cellRegion[celli];
}
syncTools::swapBoundaryFaceList(mesh, coupledRegion);
// Add approximate matches
forAll(matchPatchIDs, i)
{
const label patchi = matchPatchIDs[i];
const auto& pp = mesh.boundaryMesh()[patchi];
for (label j = i+1; j < matchPatchIDs.size(); ++j)
{
const label nbrPatchi = matchPatchIDs[j];
const auto& nbrPp = mesh.boundaryMesh()[nbrPatchi];
// Use AMI to try and find matches
auto AMPtr(AMIInterpolation::New(AMIMethod));
AMPtr->calculate(pp, nbrPp, nullptr);
if
(
gAverage(AMPtr->tgtWeightsSum()) > SMALL
|| gAverage(AMPtr->srcWeightsSum()) > SMALL
)
{
// Pull remote data local
labelList thisDecomp(pp.size(), labelMax);
AMPtr->interpolateToSource
(
labelList(cellRegion, nbrPp.faceCells()),
[]
(
label& res,
const label facei,
const label& fld,
const scalar& w
)
{
res = min(res, fld);
},
thisDecomp,
thisDecomp // used in case of low-weight-corr
);
// Put thisDecomp into coupledRegion. Check for unmatched faces.
forAll(thisDecomp, i)
{
if (thisDecomp[i] != labelMax)
{
coupledRegion[pp.offset()+i] = thisDecomp[i];
}
}
labelList nbrDecomp(nbrPp.size(), labelMax);
AMPtr->interpolateToTarget
(
labelList(cellRegion, pp.faceCells()), //thisDecomp,
[]
(
label& res,
const label facei,
const label& fld,
const scalar& w
)
{
res = min(res, fld);
},
nbrDecomp,
nbrDecomp // used in case of low-weight-corr
);
// Put nbrDecomp into coupledRegion. Check for unmatched faces/
forAll(nbrDecomp, i)
{
if (nbrDecomp[i] != labelMax)
{
coupledRegion[nbrPp.offset()+i] = nbrDecomp[i];
}
}
}
}
}
return coupledRegion;
}
// Get region-region interface name and sizes.
// Returns interfaces as straight list for looping in identical order.
void getInterfaceSizes
(
const polyMesh& mesh,
const bool useFaceZones,
const word& AMIMethod,
const labelList& matchPatchIDs,
const labelList& cellRegion,
const wordList& regionNames,
@ -361,15 +474,16 @@ void getInterfaceSizes
// Boundary faces
// ~~~~~~~~~~~~~~
// Neighbour cellRegion.
labelList coupledRegion(mesh.nBoundaryFaces());
forAll(coupledRegion, i)
{
label celli = mesh.faceOwner()[i+mesh.nInternalFaces()];
coupledRegion[i] = cellRegion[celli];
}
syncTools::swapBoundaryFaceList(mesh, coupledRegion);
const labelList coupledRegion
(
getMinBoundaryValue
(
mesh,
AMIMethod,
matchPatchIDs,
cellRegion
)
);
forAll(coupledRegion, i)
{
@ -583,6 +697,8 @@ autoPtr<mapPolyMesh> createRegionMesh
const labelList& cellRegion,
const label regionI,
const word& regionName,
const word& AMIMethod,
const labelList& matchPatchIDs,
// Interface info
const labelList& interfacePatches,
const labelList& faceToInterface,
@ -594,15 +710,16 @@ autoPtr<mapPolyMesh> createRegionMesh
fvMeshTools::createDummyFvMeshFiles(mesh, regionName, true);
// Neighbour cellRegion.
labelList coupledRegion(mesh.nBoundaryFaces());
forAll(coupledRegion, i)
{
label celli = mesh.faceOwner()[i+mesh.nInternalFaces()];
coupledRegion[i] = cellRegion[celli];
}
syncTools::swapBoundaryFaceList(mesh, coupledRegion);
const labelList coupledRegion
(
getMinBoundaryValue
(
mesh,
AMIMethod,
matchPatchIDs,
cellRegion
)
);
// Topology change container. Start off from existing mesh.
polyTopoChange meshMod(mesh);
@ -621,20 +738,16 @@ autoPtr<mapPolyMesh> createRegionMesh
labelList exposedPatchIDs(exposedFaces.size());
forAll(exposedFaces, i)
{
label facei = exposedFaces[i];
label interfacei = faceToInterface[facei];
const label facei = exposedFaces[i];
const label interfacei = faceToInterface[facei];
label ownRegion = cellRegion[mesh.faceOwner()[facei]];
label neiRegion = -1;
if (mesh.isInternalFace(facei))
{
neiRegion = cellRegion[mesh.faceNeighbour()[facei]];
}
else
{
neiRegion = coupledRegion[facei-mesh.nInternalFaces()];
}
const label ownRegion = cellRegion[mesh.faceOwner()[facei]];
const label neiRegion
(
mesh.isInternalFace(facei)
? cellRegion[mesh.faceNeighbour()[facei]]
: coupledRegion[facei-mesh.nInternalFaces()]
);
// Check which side is being kept - determines which of the two
@ -681,6 +794,62 @@ autoPtr<mapPolyMesh> createRegionMesh
meshMod
);
// Do re-patching on non-removed cells ourselves. These are not exposed
// faces but are boundary faces
for (label bFacei = 0; bFacei < mesh.nBoundaryFaces(); bFacei++)
{
const label facei = mesh.nInternalFaces()+bFacei;
if (!meshMod.faceRemoved(facei))
{
const label interfacei = faceToInterface[facei];
const label ownRegion = cellRegion[mesh.faceOwner()[facei]];
const label neiRegion = coupledRegion[bFacei];
label exposedPatchID = -1;
if (ownRegion == regionI)
{
if (regionI < neiRegion)
{
exposedPatchID = interfacePatches[interfacei];
}
else if (regionI > neiRegion)
{
exposedPatchID = interfacePatches[interfacei]+1;
}
}
else if (neiRegion == regionI)
{
if (regionI < ownRegion)
{
exposedPatchID = interfacePatches[interfacei];
}
else if (regionI > ownRegion)
{
exposedPatchID = interfacePatches[interfacei]+1;
}
}
if (exposedPatchID != -1)
{
// In-place modify the patch
DynamicList<label>& patchID =
const_cast<DynamicList<label>&>(meshMod.region());
//Pout<< "For face:" << facei
// << " on interface:" << interfacei
// << " modifying from own:" << meshMod.faceOwner()[facei]
// << " nei:" << meshMod.faceNeighbour()[facei]
// << " verts:" << meshMod.faces()[facei]
// << " patch " << patchID[facei]
// << " to " << exposedPatchID << endl;
patchID[facei] = exposedPatchID;
}
}
}
autoPtr<mapPolyMesh> map = meshMod.makeMesh
(
newMesh,
@ -705,6 +874,8 @@ void createAndWriteRegion
const labelList& cellRegion,
const wordList& regionNames,
const bool prefixRegion,
const word& AMIMethod,
const labelList& matchPatchIDs,
const labelList& faceToInterface,
const labelList& interfacePatches,
const label regionI,
@ -721,6 +892,8 @@ void createAndWriteRegion
cellRegion,
regionI,
regionNames[regionI],
AMIMethod,
matchPatchIDs,
interfacePatches,
faceToInterface,
newMesh
@ -1019,6 +1192,7 @@ labelList addRegionPatches
const wordList& regionNames,
const edgeList& interfaces,
const List<Pair<word>>& interfaceNames
//const List<mappedPatchBase::sampleMode>& interfaceModes
)
{
Info<< nl << "Adding patches" << nl << endl;
@ -1042,7 +1216,7 @@ labelList addRegionPatches
0, // overridden
0, // overridden
regionNames[e[1]], // sampleRegion
mappedPatchBase::NEARESTPATCHFACE,
mappedPatchBase::NEARESTPATCHFACE, //interfaceModes[interI]
names[1], // samplePatch
point::zero, // offset
mesh.boundaryMesh()
@ -1064,7 +1238,7 @@ labelList addRegionPatches
0,
0,
regionNames[e[0]], // sampleRegion
mappedPatchBase::NEARESTPATCHFACE,
mappedPatchBase::NEARESTPATCHFACE, //interfaceModes[interI]
names[0],
point::zero, // offset
mesh.boundaryMesh()
@ -1455,6 +1629,7 @@ int main(int argc, char *argv[])
"Split mesh into multiple regions (detected by walking across faces)"
);
#include "addRegionOption.H"
#include "addOverwriteOption.H"
argList::addBoolOption
(
@ -1521,6 +1696,18 @@ int main(int argc, char *argv[])
"useFaceZones",
"Use faceZones to patch inter-region faces instead of single patch"
);
argList::addOption
(
"autoPatch",
"lists of patches",
"Find overlapping faces to auto-generate interface patches"
);
argList::addOption
(
"AMIMethod",
"word",
"type of AMI matching method"
);
argList::addBoolOption
(
"prefixRegion",
@ -1533,6 +1720,12 @@ int main(int argc, char *argv[])
#include "createTime.H"
#include "createNamedMesh.H"
// Note: could try to read multiple meshes and merge into one before
// operation but this would give problems with unique prefixes:
// - patches get renamed. So patchFields would need to be renamed.
// - what about e.g. 'samplePatch' in mapped patches?
const word oldInstance = mesh.pointsInstance();
word blockedFacesName;
@ -1556,6 +1749,14 @@ int main(int argc, char *argv[])
const bool useFaceZones = args.found("useFaceZones");
const bool prefixRegion = args.found("prefixRegion");
labelList matchPatchIDs;
word AMIMethod(faceAreaWeightAMI2D::typeName);
if (args.found("autoPatch"))
{
const wordRes patchNames(args.getList<wordRe>("autoPatch"));
matchPatchIDs = mesh.boundaryMesh().indices(patchNames);
args.readIfPresent("AMIMethod", AMIMethod);
}
if
(
@ -1585,6 +1786,13 @@ int main(int argc, char *argv[])
}
if (matchPatchIDs.size())
{
Info<< "Auto-detecting matching faces out of patches "
<< UIndirectList<word>(mesh.boundaryMesh().names(), matchPatchIDs)
<< nl << endl;
}
if (insidePoint && largestOnly)
{
@ -1652,8 +1860,8 @@ int main(int argc, char *argv[])
<< " This requires all"
<< " cells to be in one and only one cellZone." << nl << endl;
// Collect sets of zones into clusters. If no cluster is just an identity
// list (cluster 0 is cellZone 0 etc.)
// Collect sets of zones into clusters. If no cluster is just an
// identity list (cluster 0 is cellZone 0 etc.)
wordList clusterNames;
labelListList clusterToZones;
labelList zoneToCluster;
@ -1829,7 +2037,7 @@ int main(int argc, char *argv[])
{
label ownCluster = clusterID[mesh.faceOwner()[facei]];
label neiCluster = clusterID[mesh.faceNeighbour()[facei]];
if (ownCluster != neiCluster)
{
blockedFace[facei] = true;
@ -1968,6 +2176,8 @@ int main(int argc, char *argv[])
(
mesh,
useFaceZones,
AMIMethod,
matchPatchIDs,
cellRegion,
regionNames,
@ -2147,6 +2357,7 @@ int main(int argc, char *argv[])
regionNames,
interfaces,
interfaceNames
//interfaceModes
)
);
@ -2199,6 +2410,8 @@ int main(int argc, char *argv[])
cellRegion,
regionNames,
prefixRegion,
AMIMethod,
matchPatchIDs,
faceToInterface,
interfacePatches,
regionI,
@ -2220,6 +2433,8 @@ int main(int argc, char *argv[])
cellRegion,
regionNames,
prefixRegion,
AMIMethod,
matchPatchIDs,
faceToInterface,
interfacePatches,
regionI,
@ -2241,6 +2456,8 @@ int main(int argc, char *argv[])
cellRegion,
regionNames,
prefixRegion,
AMIMethod,
matchPatchIDs,
faceToInterface,
interfacePatches,
regionI,

View File

@ -47,6 +47,9 @@ pointSync false;
// Patches to create.
patches
(
// Example of creating cyclic patch pair
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
// Name of new patch
name cyc_half0;
@ -70,10 +73,17 @@ patches
//matchTolerance 1E-2;
}
// How to construct: either from 'patches' or 'set'
// How to select the faces:
// - set : specify faceSet in 'set'
// - patches : specify names in 'patches'
// - autoPatch : attempts automatic patching of the specified
// candidates in 'patches'.
// - single region : match in the region itself
// - multi regions : match in between regions only
constructFrom patches;
// If constructFrom = patches : names of patches. Wildcards allowed.
// If constructFrom = patches or autoPatch: names of patches.
// Wildcards&patchGroups allowed.
patches (periodic1);
// If constructFrom = set : name of faceSet
@ -98,15 +108,66 @@ patches
// separationVector (1 0 0);
}
// How to construct: either from 'patches' or 'set'
// How to select the faces:
// - set : specify faceSet in 'set'
// - patches : specify names in 'patches'
// - autoPatch : attempts automatic patching of the specified
// candidates in 'patches'.
// - single region : match in the region itself
// - multi regions : match in between regions only
constructFrom patches;
// If constructFrom = patches : names of patches. Wildcards allowed.
// If constructFrom = patches or autoPatch: names of patches.
// Wildcards&patchGroups allowed.
patches (periodic2);
// If constructFrom = set : name of faceSet
set f0;
}
// Example of creating mapped patches using geometric matching
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
// Name of new patch
name solid;
// Dictionary to construct new patch from
patchInfo
{
type mappedPatch;
sampleMode nearestPatchFaceAMI;
AMIMethod faceAreaWeightAMI;
// Overwritten
//sampleRegion otherRegion;
//samplePatch otherPatch;
//- Optional override of added patchfields. If not specified
// any added patchfields are of type calculated.
patchFields
{
T
{
type fixedValue;
value uniform 300;
}
}
}
// How to select the faces:
// - set : specify faceSet in 'set'
// - patches : specify names in 'patches'
// - autoPatch : attempts automatic patching of the specified
// candidates in 'patches'.
// - single region : match in the region itself
// - multi regions : match in between regions only
constructFrom autoPatch;
// If constructFrom = patches or autoPatch: names of patches.
// Wildcards&patchGroups allowed.
patches (coupling_group);
}
);
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd.
Copyright (C) 2015-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -1354,7 +1354,9 @@ void Foam::argList::parse
// Disable any parallel comms happening inside the fileHandler
// since we are on master. This can happen e.g. inside
// the masterUncollated/collated handler.
// the masterUncollated/collated handler. Note that we
// also have to protect the actual dictionary parsing since
// it might trigger file access (e.g. #include, #codeStream)
const bool oldParRun = Pstream::parRun(false);
autoPtr<ISstream> dictStream
@ -1362,8 +1364,6 @@ void Foam::argList::parse
fileHandler().NewIFstream(source)
);
Pstream::parRun(oldParRun); // Restore parallel state
if (dictStream && dictStream->good())
{
dictionary decompDict(*dictStream);
@ -1412,6 +1412,8 @@ void Foam::argList::parse
}
}
Pstream::parRun(oldParRun); // Restore parallel state
if (Pstream::nProcs() == 1)
{
Warning

View File

@ -798,20 +798,6 @@ bool Foam::AMIInterpolation::calculate
}
bool Foam::AMIInterpolation::calculate
(
const polyMesh& mesh,
const label srcPatchi,
const primitivePatch& srcPatch,
const label tgtPatchi,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr
)
{
return calculate(srcPatch, tgtPatch, surfPtr);
}
void Foam::AMIInterpolation::reset
(
autoPtr<mapDistribute>&& srcToTgtMap,

View File

@ -73,8 +73,6 @@ SourceFiles
namespace Foam
{
class polyMesh;
/*---------------------------------------------------------------------------*\
Class AMIInterpolation Declaration
\*---------------------------------------------------------------------------*/
@ -200,6 +198,15 @@ protected:
) const;
// Access
//- Return the orginal src patch with optionally updated points
inline const primitivePatch& srcPatch0() const;
//- Return the orginal tgt patch with optionally updated points
inline const primitivePatch& tgtPatch0() const;
// Evaluation
//- Normalise the (area) weights - suppresses numerical error in
@ -341,15 +348,6 @@ public:
// Member Functions
// Access
//- Return the orginal src patch with optionally updated points
inline const primitivePatch& srcPatch0() const;
//- Return the orginal tgt patch with optionally updated points
inline const primitivePatch& tgtPatch0() const;
// Access
//- Access to the up-to-date flag
@ -448,12 +446,6 @@ public:
//- patch weights (i.e. the sum before normalisation)
inline const scalarField& tgtWeightsSum() const;
//- Return const access to target patch face centroids
inline const pointListList& tgtCentroids() const;
//- Return access to target patch face centroids
inline pointListList& tgtCentroids();
//- Return access to normalisation factor of target
//- patch weights (i.e. the sum before normalisation)
inline scalarField& tgtWeightsSum();
@ -474,17 +466,6 @@ public:
const autoPtr<searchableSurface>& surfPtr = nullptr
);
//- Update addressing, weights and (optional) centroids
virtual bool calculate
(
const polyMesh& mesh,
const label srcPatchi,
const primitivePatch& srcPatch,
const label tgtPatchi,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
);
//- Set the maps, addresses and weights from an external source
void reset
(

View File

@ -222,18 +222,6 @@ inline const Foam::scalarField& Foam::AMIInterpolation::tgtWeightsSum() const
}
inline const Foam::pointListList& Foam::AMIInterpolation::tgtCentroids() const
{
return tgtCentroids_;
}
inline Foam::pointListList& Foam::AMIInterpolation::tgtCentroids()
{
return tgtCentroids_;
}
inline Foam::scalarField& Foam::AMIInterpolation::tgtWeightsSum()
{
return tgtWeightsSum_;

View File

@ -1,52 +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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
template<class Type, class PrimitivePatchType>
Foam::Ostream& Foam::operator<<
(
Foam::Ostream& os,
const Foam::edgeTopoDistancesData<Type, PrimitivePatchType>& wDist
)
{
return os << wDist.distance_ << token::SPACE << wDist.data_;
}
template<class Type, class PrimitivePatchType>
Foam::Istream& Foam::operator>>
(
Foam::Istream& is,
Foam::edgeTopoDistancesData<Type, PrimitivePatchType>& wDist
)
{
return is >> wDist.distance_ >> wDist.data_;
}
// ************************************************************************* //

View File

@ -1,261 +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::edgeTopoDistancesData
Description
For use with PatchEdgeFaceWave. Determines topological distance to
starting edges. Templated on passive transported data.
SourceFiles
edgeTopoDistancesDataI.H
edgeTopoDistancesData.C
\*---------------------------------------------------------------------------*/
#ifndef edgeTopoDistancesData_H
#define edgeTopoDistancesData_H
#include "point.H"
#include "tensor.H"
#include "indirectPrimitivePatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class polyPatch;
class polyMesh;
template<class Type, class PrimitivePatchType>
class edgeTopoDistancesData;
template<class Type, class PrimitivePatchType>
Istream& operator>>
(
Istream&,
edgeTopoDistancesData<Type, PrimitivePatchType>&
);
template<class Type, class PrimitivePatchType>
Ostream& operator<<
(
Ostream&,
const edgeTopoDistancesData<Type, PrimitivePatchType>&
);
/*---------------------------------------------------------------------------*\
Class edgeTopoDistancesData Declaration
\*---------------------------------------------------------------------------*/
template<class Type, class PrimitivePatchType = indirectPrimitivePatch>
class edgeTopoDistancesData
{
public:
//- Class used to pass additional data in
struct trackData
{
//- Max number of entries stored per element
label n_;
};
protected:
// Protected data
//- Distance (up to size n_)
labelList distance_;
//- Starting data (up to size n_)
List<Type> data_;
public:
typedef Type dataType;
// Constructors
//- Construct null with null constructor for distance and data
inline edgeTopoDistancesData();
//- Construct from distance, data
inline edgeTopoDistancesData
(
const labelList& distance,
const List<Type>& data
);
// Member Functions
// Access
inline const labelList& distance() const
{
return distance_;
}
inline const List<Type>& data() const
{
return data_;
}
// Needed by PatchEdgeFaceWave
//- Check whether origin has been changed at all or
// still contains original (invalid) value.
template<class TrackingData>
inline bool valid(TrackingData& td) const;
//- Apply rotation matrix
template<class TrackingData>
inline void transform
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const tensor& rotTensor,
const scalar tol,
TrackingData& td
);
//- Influence of face on edge
template<class TrackingData>
inline bool updateEdge
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const label edgeI,
const label facei,
const edgeTopoDistancesData<Type, PrimitivePatchType>& faceInfo,
const scalar tol,
TrackingData& td
);
//- New information for edge (from e.g. coupled edge)
template<class TrackingData>
inline bool updateEdge
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const edgeTopoDistancesData<Type, PrimitivePatchType>& edgeInfo,
const bool sameOrientation,
const scalar tol,
TrackingData& td
);
//- Influence of edge on face.
template<class TrackingData>
inline bool updateFace
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const label facei,
const label edgeI,
const edgeTopoDistancesData<Type, PrimitivePatchType>& edgeInfo,
const scalar tol,
TrackingData& td
);
//- Same (like operator==)
template<class TrackingData>
inline bool equal
(
const edgeTopoDistancesData<Type, PrimitivePatchType>&,
TrackingData&
) const;
// Member Operators
// Needed for List IO
inline bool operator==
(
const edgeTopoDistancesData<Type, PrimitivePatchType>&
) const;
inline bool operator!=
(
const edgeTopoDistancesData<Type, PrimitivePatchType>&
) const;
// IOstream Operators
friend Ostream& operator<< <Type, PrimitivePatchType>
(
Ostream&,
const edgeTopoDistancesData<Type, PrimitivePatchType>&
);
friend Istream& operator>> <Type, PrimitivePatchType>
(
Istream&,
edgeTopoDistancesData<Type, PrimitivePatchType>&
);
};
// * * * * * * * * * * * * * * * * * Traits * * * * * * * * * * * * * * * * //
//- Data are contiguous if data type is contiguous
template<class Type, class PrimitivePatchType>
struct is_contiguous<edgeTopoDistancesData<Type, PrimitivePatchType>> :
std::false_type {};
//- Data are contiguous label if data type is label
template<class Type, class PrimitivePatchType>
struct is_contiguous_label<edgeTopoDistancesData<Type, PrimitivePatchType>> :
std::false_type {};
//- Data are contiguous scalar if data type is scalar
template<class Type, class PrimitivePatchType>
struct is_contiguous_scalar<edgeTopoDistancesData<Type, PrimitivePatchType>> :
std::false_type {};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "edgeTopoDistancesData.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "edgeTopoDistancesDataI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,224 +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 "polyMesh.H"
#include "transform.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type, class PrimitivePatchType>
inline
Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::edgeTopoDistancesData()
:
distance_(),
data_()
{}
template<class Type, class PrimitivePatchType>
inline
Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::edgeTopoDistancesData
(
const labelList& distance,
const List<Type>& data
)
:
distance_(distance),
data_(data)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::valid
(
TrackingData& td
) const
{
return distance_.size();
}
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline void Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::transform
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const tensor& rotTensor,
const scalar tol,
TrackingData& td
)
{}
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::updateEdge
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const label edgeI,
const label facei,
const edgeTopoDistancesData<Type, PrimitivePatchType>& faceInfo,
const scalar tol,
TrackingData& td
)
{
// From face to edge
if (distance_.size() >= td.n_)
{
return false;
}
const label oldSize = data_.size();
forAll(faceInfo.data_, i)
{
const auto& d = faceInfo.data_[i];
if (!data_.found(d))
{
data_.append(d);
distance_.append(faceInfo.distance_[i] + 1);
}
}
return data_.size() > oldSize;
}
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::updateEdge
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const edgeTopoDistancesData<Type, PrimitivePatchType>& edgeInfo,
const bool sameOrientation,
const scalar tol,
TrackingData& td
)
{
// From edge to edge (e.g. coupled edges)
if (distance_.size() >= td.n_)
{
return false;
}
const label oldSize = data_.size();
forAll(edgeInfo.data_, i)
{
const auto& d = edgeInfo.data_[i];
if (!data_.found(d))
{
data_.append(d);
distance_.append(edgeInfo.distance_[i]);
}
}
return data_.size() > oldSize;
}
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::updateFace
(
const polyMesh& mesh,
const PrimitivePatchType& patch,
const label facei,
const label edgeI,
const edgeTopoDistancesData<Type, PrimitivePatchType>& edgeInfo,
const scalar tol,
TrackingData& td
)
{
// From edge to edge (e.g. coupled edges)
if (distance_.size() >= td.n_)
{
return false;
}
const label oldSize = data_.size();
forAll(edgeInfo.data_, i)
{
const auto& d = edgeInfo.data_[i];
if (!data_.found(d))
{
data_.append(d);
distance_.append(edgeInfo.distance_[i]);
}
}
return data_.size() > oldSize;
}
template<class Type, class PrimitivePatchType>
template<class TrackingData>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::equal
(
const edgeTopoDistancesData<Type, PrimitivePatchType>& rhs,
TrackingData& td
) const
{
return operator==(rhs);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class Type, class PrimitivePatchType>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::operator==
(
const Foam::edgeTopoDistancesData<Type, PrimitivePatchType>& rhs
) const
{
return distance() == rhs.distance() && data() == rhs.data();
}
template<class Type, class PrimitivePatchType>
inline bool Foam::edgeTopoDistancesData<Type, PrimitivePatchType>::operator!=
(
const Foam::edgeTopoDistancesData<Type, PrimitivePatchType>& rhs
) const
{
return !(*this == rhs);
}
// ************************************************************************* //

View File

@ -1,578 +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 "lowWeightCorrection.H"
#include "addToRunTimeSelectionTable.H"
#include "edgeTopoDistancesData.H"
#include "PatchEdgeFaceWave.H"
#include "OBJstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(lowWeightCorrection, 0);
addToRunTimeSelectionTable(AMIInterpolation, lowWeightCorrection, dict);
addToRunTimeSelectionTable
(
AMIInterpolation,
lowWeightCorrection,
component
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::lowWeightCorrection::findNearest
(
const polyMesh& mesh,
const primitivePatch& pp,
const globalIndex& globalFaces,
const labelList& uncoveredFaces,
labelListList& nearestCoveredFaces
) const
{
// Data on all edges and faces
typedef edgeTopoDistancesData<label, primitivePatch> Type;
List<Type> allEdgeInfo(pp.nEdges());
List<Type> allFaceInfo(pp.size());
// Seed all covered faces
bitSet isUncovered(pp.size(), uncoveredFaces);
DynamicList<label> changedEdges(pp.nEdges());
DynamicList<Type> changedInfo(pp.nEdges());
forAll(pp, facei)
{
if (!isUncovered(facei))
{
const labelList& fEdges = pp.faceEdges()[facei];
const Type seed
(
labelList(1, 0),
labelList(1, globalFaces.toGlobal(facei))
);
allFaceInfo[facei] = seed;
for (const label edgei : fEdges)
{
changedEdges.append(edgei);
changedInfo.append(seed);
}
}
}
// Walk
Type::trackData td;
td.n_ = nDonors_;
PatchEdgeFaceWave
<
primitivePatch,
Type,
Type::trackData
> calc
(
mesh,
pp,
changedEdges,
changedInfo,
allEdgeInfo,
allFaceInfo,
0, //returnReduce(pp.nEdges(), sumOp<label>())
td
);
calc.iterate(nIters_); // should be enough iterations?
nearestCoveredFaces.setSize(uncoveredFaces.size());
forAll(uncoveredFaces, i)
{
const label facei = uncoveredFaces[i];
if (allFaceInfo[facei].valid(calc.data()))
{
// Collect donor faces
nearestCoveredFaces[i] = allFaceInfo[facei].data();
}
}
}
void Foam::lowWeightCorrection::calculateStencil
(
const label facei,
const point& sample,
const labelList& covered,
const labelListList& stencilAddressing,
labelListList& addressing,
scalarListList& weights,
scalarField& sumWeights,
const pointField& faceCentres
) const
{
addressing[facei].clear();
weights[facei].clear();
sumWeights[facei] = Zero;
// The (uncovered) facei has local donors
// Add the donors
for (const label coveredSlot : covered)
{
// Get remote slots for the local covered face
const labelList& slots = stencilAddressing[coveredSlot];
for (const label sloti : slots)
{
const point& donorPt = faceCentres[sloti];
const label index = addressing[facei].find(sloti);
if (index == -1)
{
addressing[facei].append(sloti);
weights[facei].append(1.0/mag(sample-donorPt));
}
else
{
weights[facei][index] += 1.0/mag(sample-donorPt);
}
}
}
scalarList& wghts = weights[facei];
const scalar w = sum(wghts);
forAll(wghts, i)
{
wghts[i] /= w;
}
sumWeights[facei] = 1.0;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lowWeightCorrection::lowWeightCorrection
(
const dictionary& dict,
const bool reverseTarget
)
:
AMIInterpolation(dict, reverseTarget),
lowWeightCorrection_(dict.get<scalar>("lowWeightCorrection")),
nDonors_(dict.get<label>("nDonors")),
nIters_(dict.get<label>("nIters")),
AMIPtr_
(
AMIInterpolation::New
(
dict.subDict(type() + "Coeffs").get<word>("AMIMethod"),
dict.subDict(type() + "Coeffs"),
reverseTarget
)
)
{
if (nDonors_ <= 0 || nIters_ <= 0)
{
WarningInFunction << "Disabled low-weight correction. Using "
<< AMIPtr_->type() << " AMI interpolation" << endl;
}
}
Foam::lowWeightCorrection::lowWeightCorrection
(
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection
)
:
AMIInterpolation(requireMatch, reverseTarget, lowWeightCorrection),
lowWeightCorrection_(-1),
nDonors_(0),
nIters_(0),
AMIPtr_()
{}
Foam::lowWeightCorrection::lowWeightCorrection(const lowWeightCorrection& ami)
:
AMIInterpolation(ami),
lowWeightCorrection_(ami.lowWeightCorrection_),
nDonors_(ami.nDonors_),
nIters_(ami.nIters_),
AMIPtr_(ami.AMIPtr_.clone())
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::lowWeightCorrection::calculate
(
const polyMesh& mesh,
const label srcPatchi,
const primitivePatch& srcPatch,
const label tgtPatchi,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr
)
{
if (upToDate_)
{
return false;
}
AMIInterpolation::calculate(srcPatch, tgtPatch, surfPtr);
AMIPtr_->calculate
(
mesh,
srcPatchi,
srcPatch,
tgtPatchi,
tgtPatch,
surfPtr
);
// Take over AMI data
// ~~~~~~~~~~~~~~~~~~
upToDate_ = AMIPtr_->upToDate();
// distributed / singlePatchProc
singlePatchProc_ = AMIPtr_->singlePatchProc();;
// Source patch
srcMagSf_ = AMIPtr_->srcMagSf();
srcAddress_ = AMIPtr_->srcAddress();
srcWeights_ = AMIPtr_->srcWeights();
srcWeightsSum_ = AMIPtr_->srcWeightsSum();
srcCentroids_ = AMIPtr_->srcCentroids();
//TBD: srcPatchPts_ = AMIPtr_->srcPatchPts();
tsrcPatch0_ = AMIPtr_->srcPatch0();
if (AMIPtr_->distributed())
{
srcMapPtr_.reset(new mapDistribute(AMIPtr_->srcMap()));
}
// Target
tgtMagSf_ = AMIPtr_->tgtMagSf();
tgtAddress_ = AMIPtr_->tgtAddress();
tgtWeights_ = AMIPtr_->tgtWeights();
tgtWeightsSum_ = AMIPtr_->tgtWeightsSum();
tgtCentroids_ = AMIPtr_->tgtCentroids();
//TBD: tgtPatchPts_ = AMIPtr_->tgtPatchPts();
ttgtPatch0_ = AMIPtr_->tgtPatch0();
if (AMIPtr_->distributed())
{
tgtMapPtr_.reset(new mapDistribute(AMIPtr_->tgtMap()));
}
// Walk out valid donors
// ~~~~~~~~~~~~~~~~~~~~~
if (nDonors_ > 0 && nIters_ > 0)
{
// Extend source side
{
// Low weight faces
DynamicList<label> uncoveredFaces;
forAll(srcWeightsSum(), facei)
{
if (srcWeightsSum()[facei] < lowWeightCorrection_)
{
uncoveredFaces.append(facei);
}
}
uncoveredFaces.shrink();
// Global indexing for src faces
const globalIndex globalFaces(srcPatch.size());
// Find nearest face with high weight
labelListList nearestCoveredFaces;
findNearest
(
mesh,
mesh.boundaryMesh()[srcPatchi],
globalFaces,
uncoveredFaces,
nearestCoveredFaces
);
// Create map to get remote data into nearestCoveredFaces
// order
List<Map<label>> compactMap;
const mapDistribute uncoveredToPatchMap
(
globalFaces,
nearestCoveredFaces,
compactMap
);
// Get srcPatch faceCentres in stencil ordering
pointField stencilFcs(srcPatch.faceCentres());
uncoveredToPatchMap.distribute(stencilFcs);
// Get addressing (to donors) over in stencil ordering
labelListList stencilAddressing(srcAddress());
uncoveredToPatchMap.distribute(stencilAddressing);
//scalarListList stencilWeights(srcWeights());
//uncoveredToPatchMap.distribute(stencilWeights);
// Target side patch centres
tmp<pointField> totherFcs;
if (AMIPtr_->distributed())
{
totherFcs = new pointField(tgtPatch.faceCentres());
AMIPtr_->tgtMap().distribute(totherFcs.ref());
}
else
{
totherFcs = tgtPatch.faceCentres();
}
const pointField& otherFcs = totherFcs();
//forAll(uncoveredFaces, i)
//{
// const label facei = uncoveredFaces[i];
// const labelList& covered = nearestCoveredFaces[i];
// Pout<< "Uncovered face:" << facei
// << " low weihgt:" << srcWeightsSum()[facei]
// << " at:" << srcPatch.faceCentres()[facei]
// << " has local donors:" << endl;
// for (const label coveredSlot : covered)
// {
// Pout<< " fc:" << stencilFcs[coveredSlot] << nl
// << " which has remotes:"
// << stencilAddressing[coveredSlot] << nl
// << " at:"
// << UIndirectList<point>
// (
// otherFcs,
// stencilAddressing[coveredSlot]
// ) << nl
// //<< " with weights:"
// //<< stencilWeights[coveredSlot] << nl
// << endl;
// }
//}
// Re-do interpolation on uncovered faces
forAll(uncoveredFaces, i)
{
const label facei = uncoveredFaces[i];
calculateStencil
(
facei,
srcPatch.faceCentres()[facei],
nearestCoveredFaces[i],
stencilAddressing,
srcAddress_,
srcWeights_,
srcWeightsSum_,
otherFcs
);
}
//OBJstream os
//(
// mesh.time().path()
// /mesh.boundaryMesh()[srcPatchi].name()+"_src.obj"
//);
//forAll(uncoveredFaces, i)
//{
// const label facei = uncoveredFaces[i];
// const point& fc = srcPatch.faceCentres()[facei];
// const labelList& slots = srcAddress_[facei];
// for (const label sloti : slots)
// {
// os.write(linePointRef(fc, otherFcs[sloti]));
// }
//}
}
// Extend target side
{
// Low weight faces
DynamicList<label> uncoveredFaces;
forAll(tgtWeightsSum(), facei)
{
if (tgtWeightsSum()[facei] < lowWeightCorrection_)
{
uncoveredFaces.append(facei);
}
}
uncoveredFaces.shrink();
// Global indexing for tgt faces
const globalIndex globalFaces(tgtPatch.size());
// Find nearest face with high weight
labelListList nearestCoveredFaces;
findNearest
(
mesh,
mesh.boundaryMesh()[tgtPatchi],
globalFaces,
uncoveredFaces,
nearestCoveredFaces
);
// Create map to get remote data into nearestCoveredFaces
// order
List<Map<label>> compactMap;
const mapDistribute uncoveredToPatchMap
(
globalFaces,
nearestCoveredFaces,
compactMap
);
// Get tgtPatch faceCentres in stencil ordering
pointField stencilFcs(tgtPatch.faceCentres());
uncoveredToPatchMap.distribute(stencilFcs);
// Get addressing (to donors) over in stencil ordering
labelListList stencilAddressing(tgtAddress());
uncoveredToPatchMap.distribute(stencilAddressing);
scalarListList stencilWeights(tgtWeights());
uncoveredToPatchMap.distribute(stencilWeights);
// Target side patch centres
tmp<pointField> totherFcs;
if (AMIPtr_->distributed())
{
totherFcs = new pointField(srcPatch.faceCentres());
AMIPtr_->srcMap().distribute(totherFcs.ref());
}
else
{
totherFcs = srcPatch.faceCentres();
}
const pointField& otherFcs = totherFcs();
//forAll(uncoveredFaces, i)
//{
// const label facei = uncoveredFaces[i];
// const labelList& covered = nearestCoveredFaces[i];
// Pout<< "Uncovered face:" << facei
// << " low weihgt:" << tgtWeights()[facei]
// << " at:" << tgtPatch.faceCentres()[facei]
// << " has local donors:" << endl;
// for (const label coveredSlot : covered)
// {
// Pout<< " fc:" << stencilFcs[coveredSlot] << nl
// << " which has remotes:"
// << stencilAddressing[coveredSlot] << nl
// << " at:"
// << UIndirectList<point>
// (
// otherFcs,
// stencilAddressing[coveredSlot]
// ) << nl
// << " with weights:"
// << stencilWeights[coveredSlot] << nl
// << endl;
// }
//}
// Re-do interpolation on uncovered faces
forAll(uncoveredFaces, i)
{
const label facei = uncoveredFaces[i];
calculateStencil
(
facei,
tgtPatch.faceCentres()[facei],
nearestCoveredFaces[i],
stencilAddressing,
tgtAddress_,
tgtWeights_,
tgtWeightsSum_,
otherFcs
);
}
//OBJstream os
//(
// mesh.time().path()
// /mesh.boundaryMesh()[srcPatchi].name()+"_tgt.obj"
//);
//forAll(uncoveredFaces, i)
//{
// const label facei = uncoveredFaces[i];
// const point& fc = tgtPatch.faceCentres()[facei];
// const labelList& slots = tgtAddress_[facei];
// for (const label sloti : slots)
// {
// os.write(linePointRef(fc, otherFcs[sloti]));
// }
//}
}
////- Write face connectivity as OBJ file
//writeFaceConnectivity
//(
// srcPatch,
// tgtPatch,
// srcAddress_
//);
}
return upToDate_;
}
void Foam::lowWeightCorrection::write(Ostream& os) const
{
AMIInterpolation::write(os);
os.writeEntry("nDonors", nDonors_);
os.writeEntry("nIters", nIters_);
os.beginBlock(word(this->type() + "Coeffs"));
AMIPtr_->write(os);
os.endBlock();
}
// ************************************************************************* //

View File

@ -1,216 +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::lowWeightCorrection
Description
Arbitrary Mesh Interface (AMI) method wrapper that extends low-weight
faces to use donors of local neighbouring (non-low weight) faces.
It collects valid nearby faces and uses their stencil instead.
Example of the boundary specification:
\verbatim
<patchName>
{
type cyclicAMI;
AMIMethod lowWeightCorrection;
// Low weight value; which faces to override
lowWeightCorrection 0.1;
// How far to walk out from valid faces. 0 means no change.
nIters 2;
// Limit amount of valid faces to store.
nDonors 2;
// Underlying AMI method to use.
lowWeightCorrectionCoeffs
{
AMIMethod faceAreaWeightAMI;
}
}
\endverbatim
This version walks out the local faces and then collects all their
remote donors. Hence even for e.g. 2 local faces (nDonors) the stencil
might still include lots of remote faces.
The number of iterations to walk out might be set to infinite if one
wants a value on all faces.
SourceFiles
lowWeightCorrection.C
\*---------------------------------------------------------------------------*/
#ifndef lowWeightCorrection_H
#define lowWeightCorrection_H
#include "AMIInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class lowWeightCorrection Declaration
\*---------------------------------------------------------------------------*/
class lowWeightCorrection
:
public AMIInterpolation
{
private:
// Private Data
//- Threshold weight below which interpolation switches to distance
// weighted
const scalar lowWeightCorrection_;
//- Number of donors to weigh
const label nDonors_;
//- Number of iterations to walk out to search for donors
const label nIters_;
//- Uncorrected AMI
autoPtr<AMIInterpolation> AMIPtr_;
// Private Member Functions
//- Find (local) donor faces for all uncovered faces
void findNearest
(
const polyMesh& mesh,
const primitivePatch& pp,
const globalIndex& globalFaces,
const labelList& uncoveredFaces,
labelListList& nearestCoveredFaces
) const;
//- Determine stencil for single face. Gets list of (local) faces
// whose addressing can be used for calculating the stencil
void calculateStencil
(
const label facei,
const point& sample,
const labelList& nearestCovered,
const labelListList& stencilAddressing,
labelListList& addressing,
scalarListList& weights,
scalarField& sumWeights,
const pointField& faceCentres
) const;
//- No copy assignment
void operator=(const lowWeightCorrection&) = delete;
public:
//- Runtime type information
TypeName("lowWeightCorrection");
// Constructors
//- Construct from dictionary
lowWeightCorrection
(
const dictionary& dict,
const bool reverseTarget = false
);
//- Construct from components
lowWeightCorrection
(
const bool requireMatch = true,
const bool reverseTarget = false,
const scalar lowWeightCorrection = -1
);
//- Construct as copy
lowWeightCorrection(const lowWeightCorrection& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return autoPtr<AMIInterpolation>(new lowWeightCorrection(*this));
}
//- Destructor
virtual ~lowWeightCorrection() = default;
// Member Functions
//- Update addressing and weights
virtual bool calculate
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
)
{
NotImplemented;
return false;
}
//- Update addressing and weights
virtual bool calculate
(
const polyMesh& mesh,
const label srcPatchi,
const primitivePatch& srcPatch,
const label tgtPatchi,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
);
// I-O
//- Write
virtual void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -435,15 +435,7 @@ void Foam::cyclicAMIPolyPatch::resetAMI(const UList<point>& points) const
// Construct/apply AMI interpolation to determine addressing and weights
AMIPtr_->upToDate() = false;
AMIPtr_->calculate
(
boundaryMesh().mesh(),
index(),
patch0,
nbr.index(),
nbrPatch0,
surfPtr()
);
AMIPtr_->calculate(patch0, nbrPatch0, surfPtr());
if (debug)
{

View File

@ -293,7 +293,6 @@ $(AMI)/GAMG/interfaceFields/cyclicACMIGAMGInterfaceField/cyclicACMIGAMGInterface
$(AMI)/triangle2D/triangle2D.C
$(AMI)/AMIInterpolation/faceAreaWeightAMI2D/faceAreaWeightAMI2D.C
$(AMI)/AMIInterpolation/lowWeightCorrection/lowWeightCorrection.C
AMICycPatches=$(AMI)/patches/cyclicAMI