1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 Implementation of the topoPatchMapper class
32 University of Massachusetts Amherst
35 \*---------------------------------------------------------------------------*/
39 #include "topoMapper.H"
40 #include "mapPolyMesh.H"
41 #include "topoPatchMapper.H"
42 #include "demandDrivenData.H"
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 //- Clear out local storage
50 void topoPatchMapper::clearOut()
52 deleteDemandDrivenData(directAddrPtr_);
53 deleteDemandDrivenData(interpolationAddrPtr_);
54 deleteDemandDrivenData(weightsPtr_);
55 deleteDemandDrivenData(insertedFaceLabelsPtr_);
56 deleteDemandDrivenData(insertedFaceIndexMapPtr_);
57 deleteDemandDrivenData(insertedFaceAddressingPtr_);
58 deleteDemandDrivenData(areasPtr_);
59 deleteDemandDrivenData(centresPtr_);
63 //- Calculate the insertedFaceLabels list
64 void topoPatchMapper::calcInsertedFaceAddressing() const
66 if (insertedFaceLabelsPtr_ || insertedFaceAddressingPtr_)
70 "void topoPatchMapper::calcInsertedFaceAddressing() const"
71 ) << " Inserted labels has already been calculated."
75 // Information from the old patch
76 const label oldPatchSize = sizeBeforeMapping();
77 const label oldPatchStart = mpm_.oldPatchStarts()[patch_.index()];
79 if (oldPatchSize == 0)
81 // Nothing to map from. Return empty.
82 insertedFaceLabelsPtr_ = new labelList(0);
83 insertedFaceIndexMapPtr_ = new labelList(0);
84 insertedFaceAddressingPtr_ = new labelListList(0);
88 // Allocate for inserted face labels and addressing
89 label nInsertedFaces = 0;
91 insertedFaceLabelsPtr_ = new labelList(patchSize(), -1);
92 labelList& insertedFaces = *insertedFaceLabelsPtr_;
94 insertedFaceIndexMapPtr_ = new labelList(patchSize(), -1);
95 labelList& insertedFacesMap = *insertedFaceIndexMapPtr_;
97 insertedFaceAddressingPtr_ = new labelListList(patchSize(), labelList(0));
98 labelListList& insertedAddressing = *insertedFaceAddressingPtr_;
100 // Fetch current patch start
101 label pStart = patch_.patch().start();
103 // Fetch the current boundary
104 const polyBoundaryMesh& boundary = mpm_.mesh().boundaryMesh();
106 // Loop through the facesFromFaces map, and ensure that
107 // inserted faces are only mapped from faces on the same patch.
108 const List<objectMap>& fff = mpm_.facesFromFacesMap();
112 const objectMap& fffI = fff[objectI];
114 // Only pick boundary faces in this patch
115 if (boundary.whichPatch(fffI.index()) == patch_.index())
117 if (fffI.masterObjects().empty())
119 // Write out for post-processing
124 + Foam::name(fffI.index()),
125 labelList(1, fffI.index()),
127 mpm_.mesh().points(),
134 "void topoPatchMapper::"
135 "calcInsertedFaceAddressing() const"
136 ) << " Mapping for inserted boundary face is incorrect."
137 << " Found an empty masterObjects list."
138 << nl << " Face: " << fffI.index()
139 << nl << " Patch: " << patch_.name()
140 << abort(FatalError);
144 // Make an entry for the inserted label,
145 // and renumber addressing to patch.
146 insertedFaces[nInsertedFaces] = fffI.index() - pStart;
148 // Add a mapping entry for facesFromFaces indices
149 insertedFacesMap[nInsertedFaces] = objectI;
151 // Make an entry for addressing
152 labelList& addr = insertedAddressing[nInsertedFaces];
154 // Check for illegal addressing
155 addr = fffI.masterObjects();
159 if (addr[faceI] < 0 || addr[faceI] >= oldPatchSize)
161 // Write out for post-processing
165 "patchFacePatchError_"
166 + Foam::name(fffI.index()),
167 labelList(1, fffI.index()),
169 mpm_.mesh().points(),
176 "void topoPatchMapper::"
177 "calcInsertedFaceAddressing() const"
179 << "Addressing into another patch is not allowed."
180 << nl << " Patch face index: " << faceI
181 << nl << " Patch: " << patch_.name()
182 << nl << " fffI.index: " << fffI.index()
183 << nl << " pStart: " << pStart
184 << nl << " addr: " << addr
185 << nl << " addr[faceI]: " << addr[faceI]
186 << nl << " oldPatchStart: " << oldPatchStart
187 << nl << " oldPatchSize: " << oldPatchSize
188 << abort(FatalError);
197 // Shorten inserted faces to actual size
198 insertedFaces.setSize(nInsertedFaces);
199 insertedFacesMap.setSize(nInsertedFaces);
200 insertedAddressing.setSize(nInsertedFaces);
204 //- Calculate addressing for mapping
205 void topoPatchMapper::calcAddressing() const
207 if (directAddrPtr_ || interpolationAddrPtr_)
209 FatalErrorIn("void topoPatchMapper::calcAddressing() const")
210 << "Addressing already calculated."
211 << abort(FatalError);
214 // Information from the old patch
215 const label oldPatchSize = sizeBeforeMapping();
216 const label oldPatchStart = mpm_.oldPatchStarts()[patch_.index()];
217 const label oldPatchEnd = oldPatchStart + oldPatchSize;
219 // Assemble the maps: slice to patch
222 if (oldPatchSize == 0)
224 // Nothing to map from. Return empty.
225 directAddrPtr_ = new labelList(0);
229 // Direct mapping - slice to size
232 new labelList(patch_.patch().patchSlice(mpm_.faceMap()))
235 labelList& addr = *directAddrPtr_;
237 // Shift to local patch indices.
238 // Also, check mapping for hits into other patches / internal faces.
243 addr[faceI] >= oldPatchStart
244 && addr[faceI] < oldPatchEnd
247 addr[faceI] -= oldPatchStart;
251 // Relax addressing requirement for
252 // processor patch faces. These require
253 // cell-to-face interpolation anyway.
254 if (isA<processorPolyPatch>(patch_.patch()))
256 // Artificially map from face[0] of this patch.
261 // Write out for post-processing
265 "patchFacePatchError_"
269 mpm_.mesh().points(),
276 "void topoPatchMapper::calcAddressing() const"
278 << "Addressing into another patch is not allowed."
279 << nl << " Patch: " << patch_.name()
280 << nl << " Patch index: " << patch_.index()
281 << nl << " Patch face index: " << faceI
282 << nl << " addr[faceI]: " << addr[faceI]
283 << nl << " oldPatchStart: " << oldPatchStart
284 << nl << " oldPatchSize: " << oldPatchSize
285 << nl << " oldPatchEnd: " << oldPatchEnd
286 << nl << " nInserted: " << insertedObjectLabels().size()
287 << abort(FatalError);
293 if (oldPatchSize == 0)
295 // Nothing to map from. Return empty.
296 interpolationAddrPtr_ = new labelListList(0);
300 // Interpolative addressing
301 interpolationAddrPtr_ = new labelListList(patchSize(), labelList(0));
302 labelListList& addr = *interpolationAddrPtr_;
304 // Fetch the list of inserted faces / addressing
305 const labelList& insertedFaces = insertedObjectLabels();
306 const labelListList& insertedAddressing = insertedFaceAddressing();
309 forAll(insertedFaces, faceI)
311 addr[insertedFaces[faceI]] = insertedAddressing[faceI];
314 // Do mapped faces. Note that this can already be set by insertedFaces
315 // so check if addressing size still zero.
316 const labelList::subList fm = patch_.patch().patchSlice(mpm_.faceMap());
320 if (fm[faceI] > -1 && addr[faceI].size() == 0)
322 // Mapped from a single face
323 label oldFace = fm[faceI];
327 oldFace >= oldPatchStart
328 && oldFace < oldPatchEnd
331 oldFace -= oldPatchStart;
337 "void topoPatchMapper::calcAddressing() const"
339 << "Addressing into another patch is not allowed."
340 << nl << " Patch: " << patch_.name()
341 << nl << " Patch index: " << patch_.index()
342 << nl << " Patch face index: " << faceI
343 << nl << " faceMap[faceI]: " << oldFace
344 << nl << " oldPatchStart: " << oldPatchStart
345 << nl << " oldPatchSize: " << oldPatchSize
346 << nl << " oldPatchEnd: " << oldPatchEnd
347 << abort(FatalError);
350 addr[faceI] = labelList(1, oldFace);
354 // Check if we missed anything
357 if (addr[faceI].empty())
359 // Relax addressing requirement for
360 // processor patch faces. These require
361 // cell-to-face interpolation anyway.
362 if (isA<processorPolyPatch>(patch_.patch()))
364 // Artificially map from face[0] of this patch.
365 addr[faceI] = labelList(1, 0);
370 label oldFace = (faceI < fm.size() ? fm[faceI] : -1);
374 "void topoPatchMapper::calcAddressing() const"
376 << "Addressing is missing." << nl
377 << " Patch face index: " << faceI << nl
378 << " nInsertedFaces: " << insertedFaces.size() << nl
379 << " faceMap[faceI]: " << oldFace << nl
380 << " patch faceMap size: " << fm.size() << nl
381 << " Patch: " << patch_.name() << nl
382 << " polyPatch: " << nl << patch_.patch() << nl
383 << " faceMap size: " << mpm_.faceMap().size() << nl
384 << abort(FatalError);
391 //- Calculate inverse-distance weights for interpolative mapping
392 void topoPatchMapper::calcInverseDistanceWeights() const
398 "void topoPatchMapper::calcInverseDistanceWeights() const"
400 << "Weights already calculated."
401 << abort(FatalError);
404 // Fetch interpolative addressing
405 const labelListList& addr = addressing();
409 // Nothing to map from. Return empty.
410 weightsPtr_ = new scalarListList(0);
415 weightsPtr_ = new scalarListList(patchSize());
416 scalarListList& w = *weightsPtr_;
418 // Obtain face-centre information from old/new meshes
419 const vectorField& oldCentres = tMapper_.patchCentres(patch_.index());
420 const vectorField& newCentres = patch_.patch().faceCentres();
424 const labelList& mo = addr[faceI];
429 w[faceI] = scalarList(1, 1.0);
433 // Map from masters, inverse-distance weights
434 scalar totalWeight = 0.0;
435 w[faceI] = scalarList(mo.size(), 0.0);
437 forAll (mo, oldFaceI)
446 - oldCentres[mo[oldFaceI]]
452 totalWeight += w[faceI][oldFaceI];
456 scalar normFactor = (1.0/totalWeight);
458 forAll (mo, oldFaceI)
460 w[faceI][oldFaceI] *= normFactor;
467 //- Calculate intersection weights for conservative mapping
468 void topoPatchMapper::calcIntersectionWeightsAndCentres() const
470 if (areasPtr_ || centresPtr_)
474 "void topoPatchMapper::"
475 "calcIntersectionWeightsAndCentres() const"
477 << "Weights already calculated."
478 << abort(FatalError);
481 // Fetch interpolative addressing
482 const labelListList& addr = addressing();
486 // Nothing to map from. Return empty.
487 areasPtr_ = new List<scalarList>(0);
488 centresPtr_ = new List<vectorList>(0);
493 areasPtr_ = new List<scalarList>(patchSize(), scalarList(0));
494 List<scalarList>& a = *areasPtr_;
496 centresPtr_ = new List<vectorList>(patchSize(), vectorList(0));
497 List<vectorList>& x = *centresPtr_;
499 // Obtain stored face-centres
500 const vectorField& faceCentres = tMapper_.patchCentres(patch_.index());
503 const List<vectorField>& mapFaceCentres = tMapper_.faceCentres();
504 const List<scalarField>& mapFaceWeights = tMapper_.faceWeights();
506 // Fill in maps first
507 const labelList& insertedFaces = insertedObjectLabels();
508 const labelList& insertedFacesMap = insertedObjectMap();
510 forAll(insertedFaces, faceI)
512 a[insertedFaces[faceI]] = mapFaceWeights[insertedFacesMap[faceI]];
513 x[insertedFaces[faceI]] = mapFaceCentres[insertedFacesMap[faceI]];
516 // Now do mapped faces
519 const labelList& mo = addr[faceI];
521 // Check if this is indeed a mapped face
522 if (mo.size() == 1 && x[faceI].empty() && a[faceI].empty())
524 x[faceI] = vectorList(1, faceCentres[mo[0]]);
525 a[faceI] = scalarList(1, 1.0);
529 // Final check to ensure everything went okay
532 if (a[faceI].empty())
536 "void topoPatchMapper::"
537 "calcIntersectionWeightsAndCentres() const"
539 << "Weights / centres is missing."
540 << nl << " Patch face index: " << faceI
541 << abort(FatalError);
547 const List<scalarList>& topoPatchMapper::intersectionWeights() const
553 "const List<scalarList>& "
554 "topoPatchMapper::intersectionWeights() const"
555 ) << "Requested interpolative weights for a direct mapper."
556 << abort(FatalError);
561 calcIntersectionWeightsAndCentres();
568 const List<vectorList>& topoPatchMapper::intersectionCentres() const
574 "const List<vectorList>& "
575 "topoPatchMapper::intersectionCentres() const"
576 ) << "Requested interpolative weights for a direct mapper."
577 << abort(FatalError);
582 calcIntersectionWeightsAndCentres();
589 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
591 // Construct from components
592 topoPatchMapper::topoPatchMapper
594 const fvPatch& patch,
595 const mapPolyMesh& mpm,
596 const topoMapper& mapper
603 sizeBeforeMapping_(0),
604 conservative_(false),
605 directAddrPtr_(NULL),
606 interpolationAddrPtr_(NULL),
608 insertedFaceLabelsPtr_(NULL),
609 insertedFaceIndexMapPtr_(NULL),
610 insertedFaceAddressingPtr_(NULL),
614 // Compute sizeBeforeMapping.
615 // - This needs to be done before insertedObjects
616 // is computed to determine direct mapping
617 if (isA<emptyPolyPatch>(patch_.patch()))
619 sizeBeforeMapping_ = 0;
623 label patchIndex = patch_.index();
624 label totalSize = mpm_.oldPatchSizes()[patchIndex];
626 // Fetch offset sizes from topoMapper
627 const labelListList& sizes = tMapper_.patchSizes();
632 // Fetch number of physical patches
633 label nPhysical = sizes[0].size();
635 if (patchIndex < nPhysical)
639 totalSize += sizes[pI][patchIndex];
644 sizeBeforeMapping_ = totalSize;
647 // Check for the possibility of direct mapping
648 if (insertedObjects())
658 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
660 topoPatchMapper::~topoPatchMapper()
665 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
667 //- Return the polyPatch size
668 label topoPatchMapper::patchSize() const
670 return patch_.patch().size();
675 label topoPatchMapper::size() const
677 return patch_.size();
681 //- Return size before mapping
682 label topoPatchMapper::sizeBeforeMapping() const
684 return sizeBeforeMapping_;
688 //- Is the mapping direct
689 bool topoPatchMapper::direct() const
695 //- Return direct addressing
696 const unallocLabelList& topoPatchMapper::directAddressing() const
702 "const unallocLabelList& "
703 "topoPatchMapper::directAddressing() const"
704 ) << "Requested direct addressing for an interpolative mapper."
705 << abort(FatalError);
713 return *directAddrPtr_;
717 //- Return interpolation addressing
718 const labelListList& topoPatchMapper::addressing() const
724 "const labelListList& "
725 "topoPatchMapper::addressing() const"
726 ) << "Requested interpolative addressing for a direct mapper."
727 << abort(FatalError);
730 if (!interpolationAddrPtr_)
735 return *interpolationAddrPtr_;
740 const scalarListList& topoPatchMapper::weights() const
746 "const scalarListList& "
747 "topoPatchMapper::weights() const"
748 ) << "Requested interpolative weights for a direct mapper."
749 << abort(FatalError);
754 if (!areasPtr_ && !centresPtr_)
756 calcIntersectionWeightsAndCentres();
764 calcInverseDistanceWeights();
771 //- Are there any inserted faces
772 bool topoPatchMapper::insertedObjects() const
774 return insertedObjectLabels().size();
778 //- Return list of inserted faces
779 const labelList& topoPatchMapper::insertedObjectLabels() const
781 if (!insertedFaceLabelsPtr_)
783 calcInsertedFaceAddressing();
786 return *insertedFaceLabelsPtr_;
790 //- Return addressing map for inserted faces
791 const labelList& topoPatchMapper::insertedObjectMap() const
793 if (!insertedFaceIndexMapPtr_)
795 calcInsertedFaceAddressing();
798 return *insertedFaceIndexMapPtr_;
802 //- Return addressing for inserted faces
803 const labelListList& topoPatchMapper::insertedFaceAddressing() const
805 if (!insertedFaceAddressingPtr_)
807 calcInsertedFaceAddressing();
810 return *insertedFaceAddressingPtr_;
814 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
816 void topoPatchMapper::operator=(const topoPatchMapper& rhs)
818 // Check for assignment to self
821 FatalErrorIn("void topoPatchMapper::operator=")
822 << "Attempted assignment to self"
823 << abort(FatalError);
827 } // End namespace Foam
829 // ************************************************************************* //