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 Functions specific to conservative mapping
32 University of Massachusetts Amherst
35 \*---------------------------------------------------------------------------*/
37 #include "dynamicTopoFvMesh.H"
43 #include "objectMap.H"
44 #include "faceSetAlgorithm.H"
45 #include "cellSetAlgorithm.H"
50 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
52 defineTemplateTypeNameAndDebugWithName(IOList<objectMap>, "objectMapIOList", 0);
54 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
56 // Compute mapping weights for modified entities
57 void dynamicTopoFvMesh::computeMapping
59 const scalar matchTol,
60 const bool skipMapping,
61 const bool mappingOutput,
62 const label faceStart,
64 const label cellStart,
68 // Convex-set algorithm for cells
69 cellSetAlgorithm cellAlgorithm
80 label nInconsistencies = 0;
81 scalar maxFaceError = 0.0, maxCellError = 0.0;
82 DynamicList<scalar> cellErrors(10), faceErrors(10);
83 DynamicList<objectMap> failedCells(10), failedFaces(10);
85 // Compute cell mapping
86 for (label cellI = cellStart; cellI < (cellStart + cellSize); cellI++)
88 label cIndex = cellsFromCells_[cellI].index();
89 labelList& masterObjects = cellsFromCells_[cellI].masterObjects();
93 // Dummy map from cell[0]
94 masterObjects = labelList(1, 0);
95 cellWeights_[cellI].setSize(1, 1.0);
96 cellCentres_[cellI].setSize(1, vector::zero);
100 // Obtain weighting factors for this cell.
101 cellAlgorithm.computeWeights
105 cellParents_[cIndex],
106 polyMesh::cellCells(),
112 // Add contributions from subMeshes, if any.
113 computeCoupledWeights
116 cellAlgorithm.dimension(),
123 scalar error = mag(1.0 - sum(cellWeights_[cellI]));
125 if (error > matchTol)
127 bool consistent = false;
129 // Check whether any edges lie on boundary patches.
130 // These cells can have relaxed weights to account
131 // for mild convexity.
132 const cell& cellToCheck = cells_[cIndex];
136 const labelList& parents = cellParents_[cIndex];
140 const cell& pCell = polyMesh::cells()[parents[cI]];
144 const face& pFace = polyMesh::faces()[pCell[fI]];
146 if (pFace.size() == 3)
151 label fP = boundaryMesh().whichPatch(pCell[fI]);
153 // Disregard processor patches
154 if (getNeighbourProcessor(fP) > -1)
174 forAll(cellToCheck, fI)
176 const labelList& fE = faceEdges_[cellToCheck[fI]];
180 label eP = whichEdgePatch(fE[eI]);
182 // Disregard processor patches
183 if (getNeighbourProcessor(eP) > -1)
207 cellErrors.append(error);
209 // Accumulate error stats
210 maxCellError = Foam::max(maxCellError, error);
225 // Convex-set algorithm for faces
226 faceSetAlgorithm faceAlgorithm
237 // Compute face mapping
238 for (label faceI = faceStart; faceI < (faceStart + faceSize); faceI++)
240 label fIndex = facesFromFaces_[faceI].index();
241 labelList& masterObjects = facesFromFaces_[faceI].masterObjects();
243 label patchIndex = whichPatch(fIndex);
244 label neiProc = getNeighbourProcessor(patchIndex);
246 // Skip mapping for internal / processor faces.
247 if (patchIndex == -1 || neiProc > -1)
249 // Set dummy masters, so that the conventional
250 // faceMapper doesn't crash-and-burn
251 masterObjects = labelList(1, 0);
258 // Dummy map from patch[0]
259 masterObjects = labelList(1, 0);
260 faceWeights_[faceI].setSize(1, 1.0);
261 faceCentres_[faceI].setSize(1, vector::zero);
265 // Obtain weighting factors for this face.
266 faceAlgorithm.computeWeights
269 boundaryMesh()[patchIndex].start(),
270 faceParents_[fIndex],
271 boundaryMesh()[patchIndex].faceFaces(),
277 // Add contributions from subMeshes, if any.
278 computeCoupledWeights
281 faceAlgorithm.dimension(),
288 scalar error = mag(1.0 - sum(faceWeights_[faceI]));
290 if (error > matchTol)
292 bool consistent = false;
294 // Check whether any edges lie on bounding curves.
295 // These faces can have relaxed weights to account
296 // for addressing into patches on the other side
298 const labelList& fEdges = faceEdges_[fIndex];
302 if (checkBoundingCurve(fEdges[eI]))
313 faceErrors.append(error);
315 // Accumulate error stats
316 maxFaceError = Foam::max(maxFaceError, error);
331 if (nInconsistencies)
333 Pout<< " Mapping errors: "
334 << " max cell error: " << maxCellError
335 << " max face error: " << maxFaceError
338 if (debug || mappingOutput)
340 if (failedCells.size())
342 Pout<< " failedCells: " << endl;
344 forAll(failedCells, cellI)
346 label index = failedCells[cellI].index();
348 Pout<< " Cell: " << index
349 << " Error: " << cellErrors[cellI]
354 if (failedFaces.size())
356 Pout<< " failedFaces: " << endl;
358 forAll(failedFaces, faceI)
360 label index = failedFaces[faceI].index();
361 label patchIndex = whichPatch(index);
363 const polyBoundaryMesh& boundary = boundaryMesh();
365 Pout<< " Face: " << index
366 << " Patch: " << boundary[patchIndex].name()
367 << " Error: " << faceErrors[faceI]
372 if (debug > 3 || mappingOutput)
379 if (failedCells.size())
381 forAll(failedCells, cellI)
383 label cIndex = failedCells[cellI].index();
385 cellAlgorithm.computeWeights
389 cellParents_[cIndex],
390 polyMesh::cellCells(),
397 computeCoupledWeights
400 cellAlgorithm.dimension(),
414 if (failedFaces.size())
416 forAll(failedFaces, faceI)
418 label fIndex = failedFaces[faceI].index();
419 label patchIndex = whichPatch(fIndex);
421 const polyBoundaryMesh& boundary = boundaryMesh();
423 faceAlgorithm.computeWeights
426 boundary[patchIndex].start(),
427 faceParents_[fIndex],
428 boundary[patchIndex].faceFaces(),
435 computeCoupledWeights
438 faceAlgorithm.dimension(),
457 // Static equivalent for multiThreading
458 void dynamicTopoFvMesh::computeMappingThread(void *argument)
460 // Recast the argument
461 meshHandler *thread = static_cast<meshHandler*>(argument);
465 thread->sendSignal(meshHandler::START);
468 dynamicTopoFvMesh& mesh = thread->reference();
470 // Recast the pointers for the argument
471 scalar& matchTol = *(static_cast<scalar*>(thread->operator()(0)));
472 bool& skipMapping = *(static_cast<bool*>(thread->operator()(1)));
473 bool& mappingOutput = *(static_cast<bool*>(thread->operator()(2)));
474 label& faceStart = *(static_cast<label*>(thread->operator()(3)));
475 label& faceSize = *(static_cast<label*>(thread->operator()(4)));
476 label& cellStart = *(static_cast<label*>(thread->operator()(5)));
477 label& cellSize = *(static_cast<label*>(thread->operator()(6)));
479 // Now calculate addressing
491 thread->sendSignal(meshHandler::STOP);
496 // Routine to invoke threaded mapping
497 void dynamicTopoFvMesh::threadedMapping
504 label nThreads = threader_->getNumThreads();
506 // If mapping is being skipped, issue a warning.
509 Info<< " *** Mapping is being skipped *** " << endl;
512 // Check if single-threaded
520 0, facesFromFaces_.size(),
521 0, cellsFromCells_.size()
527 // Set one handler per thread
528 PtrList<meshHandler> hdl(nThreads);
532 hdl.set(i, new meshHandler(*this, threader()));
535 // Simple load-balancing scheme
536 FixedList<label, 2> index(-1);
537 FixedList<labelList, 2> tStarts(labelList(nThreads, 0));
538 FixedList<labelList, 2> tSizes(labelList(nThreads, 0));
540 index[0] = facesFromFaces_.size();
541 index[1] = cellsFromCells_.size();
545 Pout<< " Mapping Faces: " << index[0] << nl
546 << " Mapping Cells: " << index[1] << endl;
549 forAll(index, indexI)
551 label j = 0, total = 0;
553 while (index[indexI]--)
555 tSizes[indexI][(j = tSizes[indexI].fcIndex(j))]++;
558 for (label i = 1; i < tStarts[indexI].size(); i++)
560 tStarts[indexI][i] = tSizes[indexI][i-1] + total;
562 total += tSizes[indexI][i-1];
567 Pout<< " Load starts: " << tStarts[indexI] << nl
568 << " Load sizes: " << tSizes[indexI] << endl;
572 // Set the argument list for each thread
575 // Size up the argument list
578 // Set match tolerance
579 hdl[i].set(0, &matchTol);
581 // Set the skipMapping flag
582 hdl[i].set(1, &skipMapping);
584 // Set the mappingOutput flag
585 hdl[i].set(2, &mappingOutput);
587 // Set the start/size indices
588 hdl[i].set(3, &(tStarts[0][i]));
589 hdl[i].set(4, &(tSizes[0][i]));
590 hdl[i].set(5, &(tStarts[1][i]));
591 hdl[i].set(6, &(tSizes[1][i]));
594 // Prior to multi-threaded operation,
595 // force calculation of demand-driven data.
597 primitiveMesh::cellCells();
599 const polyBoundaryMesh& boundary = boundaryMesh();
601 forAll(boundary, patchI)
603 boundary[patchI].faceFaces();
606 // Force calculation of demand-driven data on subMeshes
607 initCoupledWeights();
609 // Execute threads in linear sequence
610 executeThreads(identity(nThreads), hdl, &computeMappingThread);
614 // Set fill-in mapping information for a particular cell
615 void dynamicTopoFvMesh::setCellMapping
618 const labelList& mapCells,
626 Pout<< "Inserting mapping cell: " << cIndex
627 << " mapCells: " << mapCells
631 // Insert index into the list, and overwrite if necessary
634 forAll(cellsFromCells_, indexI)
636 if (cellsFromCells_[indexI].index() == cIndex)
647 objectMap(cIndex, labelList(0)),
653 cellsFromCells_[index].masterObjects() = labelList(0);
657 // Update cell-parents information
658 dynamicLabelList masterCells(5);
660 forAll(mapCells, cellI)
662 if (mapCells[cellI] < 0)
667 if (mapCells[cellI] < nOldCells_)
669 if (findIndex(masterCells, mapCells[cellI]) == -1)
671 masterCells.append(mapCells[cellI]);
675 if (cellParents_.found(mapCells[cellI]))
677 const labelList& nParents = cellParents_[mapCells[cellI]];
681 if (findIndex(masterCells, nParents[cI]) == -1)
683 masterCells.append(nParents[cI]);
689 cellParents_.set(cIndex, masterCells);
693 // Set fill-in mapping information for a particular face
694 void dynamicTopoFvMesh::setFaceMapping
697 const labelList& mapFaces
700 label patch = whichPatch(fIndex);
701 label neiProc = getNeighbourProcessor(patch);
705 const polyBoundaryMesh& boundary = boundaryMesh();
714 if (patch < boundary.size())
716 pName = boundaryMesh()[patch].name();
720 pName = "New patch: " + Foam::name(patch);
723 Pout<< "Inserting mapping face: " << fIndex
724 << " patch: " << pName
725 << " mapFaces: " << mapFaces
726 << " neiProc: " << neiProc
730 bool foundError = false;
732 // Check to ensure that internal faces are not mapped
733 // from any faces in the mesh
734 if (patch == -1 && mapFaces.size())
739 // Check to ensure that mapFaces is non-empty for physical patches
740 if (patch > -1 && mapFaces.empty() && neiProc == -1)
747 writeVTK("mapFace_" + Foam::name(fIndex), fIndex, 2);
752 "void dynamicTopoFvMesh::setFaceMapping\n"
754 " const label fIndex,\n"
755 " const labelList& mapFaces\n"
758 << nl << " Incompatible mapping. " << nl
759 << " Possible reasons: " << nl
760 << " 1. No mapping specified for a boundary face; " << nl
761 << " 2. Mapping specified for an internal face, " << nl
762 << " when none was expected." << nl << nl
763 << " Face: " << fIndex << nl
765 << (patch > -1 ? boundaryMesh()[patch].name() : "Internal") << nl
766 << " Owner: " << owner_[fIndex] << nl
767 << " Neighbour: " << neighbour_[fIndex] << nl
768 << " mapFaces: " << mapFaces << nl
769 << abort(FatalError);
772 // Insert addressing into the list, and overwrite if necessary
775 forAll(facesFromFaces_, indexI)
777 if (facesFromFaces_[indexI].index() == fIndex)
788 objectMap(fIndex, labelList(0)),
794 facesFromFaces_[index].masterObjects() = labelList(0);
797 // For internal / processor faces, bail out
798 if (patch == -1 || neiProc > -1)
803 // Update face-parents information
804 dynamicLabelList masterFaces(5);
806 forAll(mapFaces, faceI)
808 if (mapFaces[faceI] < 0)
813 if (mapFaces[faceI] < nOldFaces_)
815 if (findIndex(masterFaces, mapFaces[faceI]) == -1)
817 masterFaces.append(mapFaces[faceI]);
821 if (faceParents_.found(mapFaces[faceI]))
823 const labelList& nParents = faceParents_[mapFaces[faceI]];
827 if (findIndex(masterFaces, nParents[fI]) == -1)
829 masterFaces.append(nParents[fI]);
835 faceParents_.set(fIndex, masterFaces);
839 } // End namespace Foam
841 // ************************************************************************* //