1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "DynamicList.H"
28 #include "refinementHistory.H"
30 #include "mapPolyMesh.H"
31 #include "mapDistributePolyMesh.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(refinementHistory, 0);
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 void Foam::refinementHistory::writeEntry
48 const List<splitCell8>& splitCells,
49 const splitCell8& split
53 if (split.addedCellsPtr_.valid())
55 Pout<< "parent:" << split.parent_
56 << " subCells:" << split.addedCellsPtr_()
61 Pout<< "parent:" << split.parent_
66 if (split.parent_ >= 0)
68 Pout<< "parent data:" << endl;
70 string oldPrefix = Pout.prefix();
71 Pout.prefix() = " " + oldPrefix;
72 writeEntry(splitCells, splitCells[split.parent_]);
73 Pout.prefix() = oldPrefix;
78 void Foam::refinementHistory::writeDebug
80 const labelList& visibleCells,
81 const List<splitCell8>& splitCells
84 string oldPrefix = Pout.prefix();
87 forAll(visibleCells, cellI)
89 label index = visibleCells[cellI];
93 Pout<< "Cell from refinement:" << cellI << " index:" << index
96 string oldPrefix = Pout.prefix();
97 Pout.prefix() = " " + oldPrefix;
98 writeEntry(splitCells, splitCells[index]);
99 Pout.prefix() = oldPrefix;
103 Pout<< "Unrefined cell:" << cellI << " index:" << index << endl;
106 Pout.prefix() = oldPrefix;
110 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
113 Foam::refinementHistory::splitCell8::splitCell8()
120 //- Construct as child element of parent
121 Foam::refinementHistory::splitCell8::splitCell8(const label parent)
128 //- Construct from Istream
129 Foam::refinementHistory::splitCell8::splitCell8(Istream& is)
135 //- Construct as (deep) copy.
136 Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc)
141 sc.addedCellsPtr_.valid()
142 ? new FixedList<label, 8>(sc.addedCellsPtr_())
148 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
150 Foam::Istream& Foam::operator>>(Istream& is, refinementHistory::splitCell8& sc)
152 labelList addedCells;
154 is >> sc.parent_ >> addedCells;
156 if (addedCells.size())
158 sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
162 sc.addedCellsPtr_.reset(NULL);
169 Foam::Ostream& Foam::operator<<
172 const refinementHistory::splitCell8& sc
175 // Output as labelList so we can have 0 sized lists. Alternative is to
176 // output as fixedlist with e.g. -1 elements and check for this upon
177 // reading. However would cause much more data to be transferred.
179 if (sc.addedCellsPtr_.valid())
184 << labelList(sc.addedCellsPtr_());
188 return os << sc.parent_ << token::SPACE << labelList(0);
193 void Foam::refinementHistory::checkIndices() const
196 forAll(visibleCells_, i)
198 if (visibleCells_[i] < 0 && visibleCells_[i] >= splitCells_.size())
200 FatalErrorIn("refinementHistory::checkIndices() const")
201 << "Illegal entry " << visibleCells_[i]
202 << " in visibleCells at location" << i << nl
203 << "It points outside the range of splitCells : 0.."
204 << splitCells_.size()-1
205 << abort(FatalError);
211 Foam::label Foam::refinementHistory::allocateSplitCell
219 if (freeSplitCells_.size())
221 index = freeSplitCells_.remove();
223 splitCells_[index] = splitCell8(parent);
227 index = splitCells_.size();
229 splitCells_.append(splitCell8(parent));
233 // Update the parent field
236 splitCell8& parentSplit = splitCells_[parent];
238 if (parentSplit.addedCellsPtr_.empty())
240 // Allocate storage on parent for the 8 subcells.
241 parentSplit.addedCellsPtr_.reset(new FixedList<label, 8>(-1));
245 // Store me on my parent
246 FixedList<label, 8>& parentSplits = parentSplit.addedCellsPtr_();
248 parentSplits[i] = index;
255 void Foam::refinementHistory::freeSplitCell(const label index)
257 splitCell8& split = splitCells_[index];
259 // Make sure parent does not point to me anymore.
260 if (split.parent_ >= 0)
262 autoPtr<FixedList<label, 8> >& subCellsPtr =
263 splitCells_[split.parent_].addedCellsPtr_;
265 if (subCellsPtr.valid())
267 FixedList<label, 8>& subCells = subCellsPtr();
269 label myPos = findIndex(subCells, index);
273 FatalErrorIn("refinementHistory::freeSplitCell")
274 << "Problem: cannot find myself in"
275 << " parents' children" << abort(FatalError);
279 subCells[myPos] = -1;
284 // Mark splitCell as free
287 // Add to cache of free splitCells
288 freeSplitCells_.append(index);
292 // Mark entry in splitCells. Recursively mark its parent and subs.
293 void Foam::refinementHistory::markSplit
297 DynamicList<splitCell8>& newSplitCells
300 if (oldToNew[index] == -1)
302 // Not yet compacted.
304 const splitCell8& split = splitCells_[index];
306 oldToNew[index] = newSplitCells.size();
307 newSplitCells.append(split);
309 if (split.parent_ >= 0)
311 markSplit(split.parent_, oldToNew, newSplitCells);
313 if (split.addedCellsPtr_.valid())
315 const FixedList<label, 8>& splits = split.addedCellsPtr_();
321 markSplit(splits[i], oldToNew, newSplitCells);
329 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
331 Foam::refinementHistory::refinementHistory(const IOobject& io)
337 io.readOpt() == IOobject::MUST_READ
338 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
341 readStream(typeName) >> *this;
347 Pout<< "refinementHistory::refinementHistory :"
348 << " constructed history from IOobject :"
349 << " splitCells:" << splitCells_.size()
350 << " visibleCells:" << visibleCells_.size()
356 //- Read or construct
357 Foam::refinementHistory::refinementHistory
360 const List<splitCell8>& splitCells,
361 const labelList& visibleCells
365 splitCells_(splitCells),
367 visibleCells_(visibleCells)
371 io.readOpt() == IOobject::MUST_READ
372 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
375 readStream(typeName) >> *this;
384 Pout<< "refinementHistory::refinementHistory :"
385 << " constructed history from IOobject or components :"
386 << " splitCells:" << splitCells_.size()
387 << " visibleCells:" << visibleCells_.size()
393 // Construct from initial number of cells (all visible)
394 Foam::refinementHistory::refinementHistory
405 io.readOpt() == IOobject::MUST_READ
406 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
409 readStream(typeName) >> *this;
414 visibleCells_.setSize(nCells);
415 splitCells_.setCapacity(nCells);
417 for (label cellI = 0; cellI < nCells; cellI++)
419 visibleCells_[cellI] = cellI;
420 splitCells_.append(splitCell8());
429 Pout<< "refinementHistory::refinementHistory :"
430 << " constructed history from IOobject or initial size :"
431 << " splitCells:" << splitCells_.size()
432 << " visibleCells:" << visibleCells_.size()
439 Foam::refinementHistory::refinementHistory
442 const refinementHistory& rh
446 splitCells_(rh.splitCells()),
447 freeSplitCells_(rh.freeSplitCells()),
448 visibleCells_(rh.visibleCells())
452 Pout<< "refinementHistory::refinementHistory : constructed initial"
453 << " history." << endl;
458 // Construct from Istream
459 Foam::refinementHistory::refinementHistory(const IOobject& io, Istream& is)
471 Pout<< "refinementHistory::refinementHistory :"
472 << " constructed history from Istream"
473 << " splitCells:" << splitCells_.size()
474 << " visibleCells:" << visibleCells_.size()
480 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
482 void Foam::refinementHistory::resize(const label size)
484 label oldSize = visibleCells_.size();
488 Pout<< "refinementHistory::resize from " << oldSize << " to " << size
492 visibleCells_.setSize(size);
494 // Set additional elements to -1.
495 for (label i = oldSize; i < visibleCells_.size(); i++)
497 visibleCells_[i] = -1;
502 void Foam::refinementHistory::updateMesh(const mapPolyMesh& map)
506 const labelList& reverseCellMap = map.reverseCellMap();
508 // Note that only the live cells need to be renumbered.
510 labelList newVisibleCells(map.cellMap().size(), -1);
512 forAll(visibleCells_, cellI)
514 if (visibleCells_[cellI] != -1)
516 label index = visibleCells_[cellI];
518 // Check not already set
519 if (splitCells_[index].addedCellsPtr_.valid())
523 "refinementHistory::updateMesh(const mapPolyMesh&)"
524 ) << "Problem" << abort(FatalError);
527 label newCellI = reverseCellMap[cellI];
531 newVisibleCells[newCellI] = index;
538 Pout<< "refinementHistory::updateMesh : from "
539 << visibleCells_.size()
540 << " to " << newVisibleCells.size()
544 visibleCells_.transfer(newVisibleCells);
549 // Update numbering for subsetting
550 void Foam::refinementHistory::subset
552 const labelList& pointMap,
553 const labelList& faceMap,
554 const labelList& cellMap
559 labelList newVisibleCells(cellMap.size(), -1);
561 forAll(newVisibleCells, cellI)
563 label oldCellI = cellMap[cellI];
565 label index = visibleCells_[oldCellI];
567 // Check that cell is live (so its parent has no refinement)
568 if (index >= 0 && splitCells_[index].addedCellsPtr_.valid())
572 "refinementHistory::subset"
573 "(const labelList&, const labelList&, const labelList&)"
574 ) << "Problem" << abort(FatalError);
577 newVisibleCells[cellI] = index;
582 Pout<< "refinementHistory::updateMesh : from "
583 << visibleCells_.size()
584 << " to " << newVisibleCells.size()
588 visibleCells_.transfer(newVisibleCells);
593 void Foam::refinementHistory::countProc
596 const label newProcNo,
597 labelList& splitCellProc,
598 labelList& splitCellNum
601 if (splitCellProc[index] != newProcNo)
603 // Different destination processor from other cells using this
604 // parent. Reset count.
605 splitCellProc[index] = newProcNo;
606 splitCellNum[index] = 1;
610 splitCellNum[index]++;
612 // Increment parent if whole splitCell moves to same processor
613 if (splitCellNum[index] == 8)
615 Pout<< "Moving " << splitCellNum[index]
616 << " cells originating from cell " << index
617 << " from processor " << Pstream::myProcNo()
618 << " to processor " << splitCellProc[index]
621 label parent = splitCells_[index].parent_;
625 string oldPrefix = Pout.prefix();
626 Pout.prefix() = " " + oldPrefix;
628 countProc(parent, newProcNo, splitCellProc, splitCellNum);
630 Pout.prefix() = oldPrefix;
637 void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
643 "refinementHistory::distribute(const mapDistributePolyMesh&)"
644 ) << "Calling distribute on inactive history" << abort(FatalError);
648 if (!Pstream::parRun())
653 // Remove unreferenced history.
656 Pout<< nl << "--BEFORE:" << endl;
658 Pout<< "---------" << nl << endl;
661 // Distribution is only partially functional.
662 // If all 8 cells resulting from a single parent are sent across in one
663 // go it will also send across that part of the refinement history.
664 // If however e.g. first 1 and then the other 7 are sent across the
665 // history will not be reconstructed.
667 // Determine clusters. This is per every entry in splitCells_ (that is
668 // a parent of some refinement) a label giving the processor it goes to
669 // if all its children are going to the same processor.
671 // Per visible cell the processor it goes to.
672 labelList destination(visibleCells_.size());
674 const labelListList& subCellMap = map.cellMap().subMap();
676 forAll(subCellMap, procI)
678 const labelList& newToOld = subCellMap[procI];
682 label oldCellI = newToOld[i];
684 destination[oldCellI] = procI;
688 //Pout<< "refinementHistory::distribute :"
689 // << " destination:" << destination << endl;
691 // Per splitCell entry the processor it moves to
692 labelList splitCellProc(splitCells_.size(), -1);
693 // Per splitCell entry the number of live cells that move to that processor
694 labelList splitCellNum(splitCells_.size(), 0);
696 forAll(visibleCells_, cellI)
698 label index = visibleCells_[cellI];
704 splitCells_[index].parent_,
712 Pout<< "refinementHistory::distribute :"
713 << " splitCellProc:" << splitCellProc << endl;
715 Pout<< "refinementHistory::distribute :"
716 << " splitCellNum:" << splitCellNum << endl;
719 // Create subsetted refinement tree consisting of all parents that
720 // move in their whole to other processor.
721 for (label procI = 0; procI < Pstream::nProcs(); procI++)
723 Pout<< "-- Subetting for processor " << procI << endl;
725 // From uncompacted to compacted splitCells.
726 labelList oldToNew(splitCells_.size(), -1);
728 // Compacted splitCells. Similar to subset routine below.
729 DynamicList<splitCell8> newSplitCells(splitCells_.size());
731 // Loop over all entries. Note: could recurse like countProc so only
732 // visit used entries but is probably not worth it.
734 forAll(splitCells_, index)
736 // Pout<< "oldCell:" << index
737 // << " proc:" << splitCellProc[index]
738 // << " nCells:" << splitCellNum[index]
741 if (splitCellProc[index] == procI && splitCellNum[index] == 8)
743 // Entry moves in its whole to procI
744 oldToNew[index] = newSplitCells.size();
745 newSplitCells.append(splitCells_[index]);
747 Pout<< "Added oldCell " << index
748 << " info " << newSplitCells[newSplitCells.size()-1]
749 << " at position " << newSplitCells.size()-1
754 // Add live cells that are subsetted.
755 forAll(visibleCells_, cellI)
757 label index = visibleCells_[cellI];
759 if (index >= 0 && destination[cellI] == procI)
761 label parent = splitCells_[index].parent_;
763 Pout<< "Adding refined cell " << cellI
764 << " since moves to "
765 << procI << " old parent:" << parent << endl;
767 // Create new splitCell with parent
768 oldToNew[index] = newSplitCells.size();
769 newSplitCells.append(splitCell8(parent));
773 //forAll(oldToNew, index)
775 // Pout<< "old:" << index << " new:" << oldToNew[index]
779 newSplitCells.shrink();
781 // Renumber contents of newSplitCells
782 forAll(newSplitCells, index)
784 splitCell8& split = newSplitCells[index];
786 if (split.parent_ >= 0)
788 split.parent_ = oldToNew[split.parent_];
790 if (split.addedCellsPtr_.valid())
792 FixedList<label, 8>& splits = split.addedCellsPtr_();
798 splits[i] = oldToNew[splits[i]];
805 const labelList& subMap = subCellMap[procI];
807 // New visible cells.
808 labelList newVisibleCells(subMap.size(), -1);
810 forAll(subMap, newCellI)
812 label oldCellI = subMap[newCellI];
814 label oldIndex = visibleCells_[oldCellI];
818 newVisibleCells[newCellI] = oldToNew[oldIndex];
822 //Pout<< nl << "--Subset for domain:" << procI << endl;
823 //writeDebug(newVisibleCells, newSplitCells);
824 //Pout<< "---------" << nl << endl;
827 // Send to neighbours
828 OPstream toNbr(Pstream::blocking, procI);
829 toNbr << newSplitCells << newVisibleCells;
833 // Receive from neighbours and merge
834 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
836 // Remove all entries. Leave storage intact.
839 visibleCells_.setSize(map.mesh().nCells());
842 for (label procI = 0; procI < Pstream::nProcs(); procI++)
844 IPstream fromNbr(Pstream::blocking, procI);
845 List<splitCell8> newSplitCells(fromNbr);
846 labelList newVisibleCells(fromNbr);
848 //Pout<< nl << "--Received from domain:" << procI << endl;
849 //writeDebug(newVisibleCells, newSplitCells);
850 //Pout<< "---------" << nl << endl;
853 // newSplitCells contain indices only into newSplitCells so
854 // renumbering can be done here.
855 label offset = splitCells_.size();
857 Pout<< "**Renumbering data from proc " << procI << " with offset "
860 forAll(newSplitCells, index)
862 splitCell8& split = newSplitCells[index];
864 if (split.parent_ >= 0)
866 split.parent_ += offset;
868 if (split.addedCellsPtr_.valid())
870 FixedList<label, 8>& splits = split.addedCellsPtr_();
881 splitCells_.append(split);
885 // Combine visibleCell.
886 const labelList& constructMap = map.cellMap().constructMap()[procI];
888 forAll(newVisibleCells, i)
890 visibleCells_[constructMap[i]] = newVisibleCells[i] + offset;
893 splitCells_.shrink();
895 Pout<< nl << "--AFTER:" << endl;
897 Pout<< "---------" << nl << endl;
901 void Foam::refinementHistory::compact()
905 Pout<< "refinementHistory::compact() Entering with:"
906 << " freeSplitCells_:" << freeSplitCells_.size()
907 << " splitCells_:" << splitCells_.size()
908 << " visibleCells_:" << visibleCells_.size()
911 // Check all free splitCells are marked as such
912 forAll(freeSplitCells_, i)
914 label index = freeSplitCells_[i];
916 if (splitCells_[index].parent_ != -2)
918 FatalErrorIn("refinementHistory::compact()")
919 << "Problem index:" << index
920 << abort(FatalError);
924 // Check none of the visible cells are marked as free
925 forAll(visibleCells_, cellI)
929 visibleCells_[cellI] >= 0
930 && splitCells_[visibleCells_[cellI]].parent_ == -2
933 FatalErrorIn("refinementHistory::compact()")
934 << "Problem : visible cell:" << cellI
935 << " is marked as being free." << abort(FatalError);
940 DynamicList<splitCell8> newSplitCells(splitCells_.size());
942 // From uncompacted to compacted splitCells.
943 labelList oldToNew(splitCells_.size(), -1);
945 // Mark all used splitCell entries. These are either indexed by visibleCells
946 // or indexed from other splitCell entries.
948 // Mark from visibleCells
949 forAll(visibleCells_, cellI)
951 label index = visibleCells_[cellI];
955 // Make sure we only mark visible indices if they either have a
956 // parent or subsplits.
959 splitCells_[index].parent_ != -1
960 || splitCells_[index].addedCellsPtr_.valid()
963 markSplit(index, oldToNew, newSplitCells);
968 // Mark from splitCells
969 forAll(splitCells_, index)
971 if (splitCells_[index].parent_ == -2)
977 splitCells_[index].parent_ == -1
978 && splitCells_[index].addedCellsPtr_.empty()
981 // recombined cell. No need to keep since no parent and no subsplits
982 // Note that gets marked if reachable from other index!
987 markSplit(index, oldToNew, newSplitCells);
992 // Now oldToNew is fully complete and compacted elements are in
994 // Renumber contents of newSplitCells and visibleCells.
995 forAll(newSplitCells, index)
997 splitCell8& split = newSplitCells[index];
999 if (split.parent_ >= 0)
1001 split.parent_ = oldToNew[split.parent_];
1003 if (split.addedCellsPtr_.valid())
1005 FixedList<label, 8>& splits = split.addedCellsPtr_();
1011 splits[i] = oldToNew[splits[i]];
1020 Pout<< "refinementHistory::compact : compacted splitCells from "
1021 << splitCells_.size() << " to " << newSplitCells.size() << endl;
1024 splitCells_.transfer(newSplitCells);
1025 freeSplitCells_.clearStorage();
1030 Pout<< "refinementHistory::compact() NOW:"
1031 << " freeSplitCells_:" << freeSplitCells_.size()
1032 << " splitCells_:" << splitCells_.size()
1033 << " newSplitCells:" << newSplitCells.size()
1034 << " visibleCells_:" << visibleCells_.size()
1039 // Adapt indices in visibleCells_
1040 forAll(visibleCells_, cellI)
1042 label index = visibleCells_[cellI];
1046 // Note that oldToNew can be -1 so it resets newVisibleCells.
1047 visibleCells_[cellI] = oldToNew[index];
1057 void Foam::refinementHistory::writeDebug() const
1059 writeDebug(visibleCells_, splitCells_);
1063 void Foam::refinementHistory::storeSplit
1066 const labelList& addedCells
1069 label parentIndex = -1;
1071 if (visibleCells_[cellI] != -1)
1073 // Was already live. The current live cell becomes the
1074 // parent of the cells split off from it.
1076 parentIndex = visibleCells_[cellI];
1078 // It is no longer live (note that actually cellI gets alive
1079 // again below since is addedCells[0])
1080 visibleCells_[cellI] = -1;
1084 // Create 0th level. -1 parent to denote this.
1085 parentIndex = allocateSplitCell(-1, -1);
1088 // Create live entries for added cells that point to the
1089 // cell they were created from (parentIndex)
1090 forAll(addedCells, i)
1092 label addedCellI = addedCells[i];
1094 // Create entries for the split off cells. All of them
1096 visibleCells_[addedCellI] = allocateSplitCell(parentIndex, i);
1101 void Foam::refinementHistory::combineCells
1103 const label masterCellI,
1104 const labelList& combinedCells
1107 // Save the parent structure
1108 label parentIndex = splitCells_[visibleCells_[masterCellI]].parent_;
1110 // Remove the information for the combined cells
1111 forAll(combinedCells, i)
1113 label cellI = combinedCells[i];
1115 freeSplitCell(visibleCells_[cellI]);
1116 visibleCells_[cellI] = -1;
1119 splitCell8& parentSplit = splitCells_[parentIndex];
1120 parentSplit.addedCellsPtr_.reset(NULL);
1121 visibleCells_[masterCellI] = parentIndex;
1125 bool Foam::refinementHistory::readData(Istream& is)
1132 bool Foam::refinementHistory::writeData(Ostream& os) const
1140 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
1142 Foam::Istream& Foam::operator>>(Istream& is, refinementHistory& rh)
1144 rh.freeSplitCells_.clearStorage();
1146 is >> rh.splitCells_ >> rh.visibleCells_;
1155 Foam::Ostream& Foam::operator<<(Ostream& os, const refinementHistory& rh)
1157 const_cast<refinementHistory&>(rh).compact();
1159 return os << "// splitCells" << nl
1160 << rh.splitCells_ << nl
1161 << "// visibleCells" << nl
1162 << rh.visibleCells_;
1166 // ************************************************************************* //