58void Foam::cyclicPeriodicAMIPolyPatch::syncTransforms()
const
91 if (periodicPatch.separation().size() > 1)
95 <<
" has non-uniform separation vector "
96 << periodicPatch.separation()
97 <<
"This is not allowed inside " <<
type()
98 <<
" patch " <<
name()
102 if (periodicPatch.forwardT().size() > 1)
106 <<
" has non-uniform transformation tensor "
107 << periodicPatch.forwardT()
108 <<
"This is not allowed inside " <<
type()
109 <<
" patch " <<
name()
127 periodicPatch.size() && periodicPatch.parallel()
142 if (!periodicPatch.size())
146 if (sep[procI].
size())
150 periodicPatch.separation()
154 periodicPatch.collocated()
175 if (!periodicPatch.size())
183 periodicPatch.forwardT()
187 periodicPatch.reverseT()
200void Foam::cyclicPeriodicAMIPolyPatch::writeOBJ
220 str.write(allFaces, allPoints);
243 pointField nbrPoints0(neighbPatch().localPoints());
244 transformPosition(nbrPoints0);
250 if (nTransforms_ > nSectors_/2)
252 nTransforms_ -= nSectors_;
254 else if (nTransforms_ < - nSectors_/2)
256 nTransforms_ += nSectors_;
261 for (label i = 0; i < nTransforms_; ++ i)
263 periodicPatch.transformPosition(thisPoints0);
265 for (label i = 0; i > nTransforms_; -- i)
267 periodicPatch.transformPosition(nbrPoints0);
280 neiStr.reset(
new OBJstream(dir/neighbPatch().
name() + postfix));
283 <<
"patch:" <<
name()
284 <<
" writing accumulated AMI to "
285 << ownStr().name().relative(dir)
286 <<
" and " << neiStr().name().relative(dir) <<
endl;
310 SubList<face>(neighbPatch().localFaces(), neighbPatch().size()),
316 SubList<face>(neighbPatch().localFaces(), neighbPatch().size()),
321 AMIPtr_->setRequireMatch(
false);
322 AMIPtr_->calculate(thisPatch0, nbrPatch0, surfPtr());
326 label nTransformsOld(nTransforms_);
339 scalar srcSum(
gAverage(AMIPtr_->srcWeightsSum()));
340 scalar tgtSum(
gAverage(AMIPtr_->tgtWeightsSum()));
351 scalar srcSumDiff = 0;
354 <<
"patch:" <<
name()
355 <<
" srcSum:" << srcSum
356 <<
" tgtSum:" << tgtSum
365 (1 - srcSum > matchTolerance())
366 || (1 - tgtSum > matchTolerance())
372 periodicPatch.transformPosition(thisPoints);
375 <<
"patch:" <<
name()
376 <<
" moving this side from:"
380 thisPatch.movePoints(thisPoints);
383 <<
"patch:" <<
name()
384 <<
" appending weights with untransformed slave side"
387 AMIPtr_->append(thisPatch, nbrPatch0);
396 periodicPatch.transformPosition(nbrPoints);
399 <<
"patch:" <<
name()
400 <<
" moving neighbour side from:"
404 nbrPatch.movePoints(nbrPoints);
406 AMIPtr_->append(thisPatch0, nbrPatch);
414 const scalar srcSumNew =
gAverage(AMIPtr_->srcWeightsSum());
415 const scalar srcSumDiffNew = srcSumNew - srcSum;
417 if (srcSumDiffNew < srcSumDiff || srcSumDiffNew < SMALL)
421 srcSumDiff = srcSumDiffNew;
425 tgtSum =
gAverage(AMIPtr_->tgtWeightsSum());
432 <<
"patch:" <<
name()
433 <<
" iteration:" << iter
434 <<
" srcSum:" << srcSum
435 <<
" tgtSum:" << tgtSum
442 ownStr.reset(
nullptr);
443 neiStr.reset(
nullptr);
447 nTransforms_ = (nTransforms_ + nTransformsOld)/2;
450 if (iter == maxIter_)
461 <<
"Patches " <<
name() <<
" and " << neighbPatch().name()
462 <<
" do not couple to within a tolerance of "
464 <<
" when transformed according to the periodic patch "
465 << periodicPatch.name() <<
"." <<
nl
466 <<
"The current sum of weights are for owner " <<
name()
467 <<
" : " << srcSum <<
" and for neighbour "
468 << neighbPatch().name() <<
" : " << tgtSum <<
nl
469 <<
"This is only acceptable during post-processing"
470 <<
"; not during running. Improve your mesh or increase"
471 <<
" the 'matchTolerance' setting in the patch specification."
478 mag(srcSum - floor(srcSum + 0.5)) > srcSum*matchTolerance()
479 ||
mag(tgtSum - floor(tgtSum + 0.5)) > tgtSum*matchTolerance()
488 <<
"Patches " <<
name() <<
" and " << neighbPatch().name()
489 <<
" do not overlap an integer number of times when transformed"
490 <<
" according to the periodic patch "
491 << periodicPatch.name() <<
"." <<
nl
492 <<
"The current matchTolerance : " << matchTolerance()
493 <<
", sum of owner weights : " << srcSum
494 <<
", sum of neighbour weights : " << tgtSum
496 <<
"This is only acceptable during post-processing"
497 <<
"; not during running. Improve your mesh or increase"
498 <<
" the 'matchTolerance' setting in the patch specification."
508 srcWghtSum[faceI] =
sum(AMIPtr_->srcWeights()[faceI]);
513 tgtWghtSum[faceI] =
sum(AMIPtr_->tgtWeights()[faceI]);
521 <<
"AMI: Patch " <<
name()
523 <<
" min:" <<
limits.min()
524 <<
" max:" <<
limits.max()
525 <<
" average:" << avg <<
nl;
533 <<
"AMI: Patch " << neighbPatch().name()
535 <<
" min:" <<
limits.min()
536 <<
" max:" <<
limits.max()
537 <<
" average:" << avg <<
nl;
553 const word& patchType,
572 AMIPtr_->setRequireMatch(
false);
582 const word& patchType
594 nTransforms_(
dict.getOrDefault<label>(
"nTransforms", 0)),
595 nSectors_(
dict.getOrDefault<label>(
"nSectors", 0)),
596 maxIter_(
dict.getOrDefault<label>(
"maxIter", 36))
598 AMIPtr_->setRequireMatch(
false);
609 nTransforms_(
pp.nTransforms_),
610 nSectors_(
pp.nSectors_),
611 maxIter_(
pp.maxIter_)
613 AMIPtr_->setRequireMatch(
false);
623 const label newStart,
624 const word& nbrPatchName
628 nTransforms_(
pp.nTransforms_),
629 nSectors_(
pp.nSectors_),
630 maxIter_(
pp.maxIter_)
632 AMIPtr_->setRequireMatch(
false);
646 nTransforms_(
pp.nTransforms_),
647 nSectors_(
pp.nSectors_),
648 maxIter_(
pp.maxIter_)
650 AMIPtr_->setRequireMatch(
false);
666 os.writeEntryIfDifferent<label>(
"nTransforms", 0, nTransforms_);
667 os.writeEntryIfDifferent<label>(
"nSectors", 0, nSectors_);
668 os.writeEntryIfDifferent<label>(
"maxIter", 36, maxIter_);
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
static void allGatherList(UList< T > &values, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Gather data, but keep individual values separate. Uses MPI_Allgather or manual communication.
A non-owning sub-view of a List (allocated or unallocated storage).
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
fileName globalPath() const
The global path for the case = rootPath/globalCaseName.
label size() const noexcept
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
const bMesh & mesh() const
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual const tensorField & reverseT() const
Return neighbour-cell transformation tensor.
coupledPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform)
Construct from components.
virtual const tensorField & forwardT() const
Return face transformation tensor.
Cyclic patch for Arbitrary Mesh Interface (AMI).
virtual void resetAMI() const
Reset the AMI interpolator, use current patch points.
virtual bool owner() const
Does this side own the patch?
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
word periodicPatchName_
Periodic patch name.
cyclicAMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN, const word &defaultAMIMethod=faceAreaWeightAMI::typeName)
Construct from (base coupled patch) components.
autoPtr< AMIPatchToPatchInterpolation > AMIPtr_
AMI interpolation class.
label periodicPatchID() const
Periodic patch ID (or -1).
Cyclic patch for periodic Arbitrary Mesh Interface (AMI).
virtual void write(Ostream &) const
Write the polyPatch data as a dictionary.
cyclicPeriodicAMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN)
Construct from (base coupled patch) components.
virtual ~cyclicPeriodicAMIPolyPatch()
Destructor.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Face area weighted Arbitrary Mesh Interface (AMI) method.
A class for handling file names.
label index() const noexcept
The index of this patch in the boundaryMesh.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
A patch is a list of labels that address the faces in the global face list.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundaryMesh reference.
label start() const noexcept
Return start label of this patch in the polyMesh face list.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
#define DebugInFunction
Report an information message using Foam::Info.
#define InfoInFunction
Report an information message using Foam::Info.
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
Namespace for handling debugging switches.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
messageStream Info
Information stream (stdout output on master, null elsewhere).
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
List< face > faceList
List of faces.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Ostream & indent(Ostream &os)
Indent stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< bool > boolList
A List of bools.
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1, const label comm)
static constexpr const zero Zero
Global zero (0).
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
UList< label > labelUList
A UList of labels.
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.