1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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_
65 if (split.parent_ >= 0)
67 Pout<< "parent data:" << endl;
69 string oldPrefix = Pout.prefix();
70 Pout.prefix() = " " + oldPrefix;
71 writeEntry(splitCells, splitCells[split.parent_]);
72 Pout.prefix() = oldPrefix;
77 void Foam::refinementHistory::writeDebug
79 const labelList& visibleCells,
80 const List<splitCell8>& splitCells
83 string oldPrefix = Pout.prefix();
86 forAll(visibleCells, cellI)
88 label index = visibleCells[cellI];
92 Pout<< "Cell from refinement:" << cellI << " index:" << index
95 string oldPrefix = Pout.prefix();
96 Pout.prefix() = " " + oldPrefix;
97 writeEntry(splitCells, splitCells[index]);
98 Pout.prefix() = oldPrefix;
102 Pout<< "Unrefined cell:" << cellI << " index:" << index << endl;
105 Pout.prefix() = oldPrefix;
109 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112 Foam::refinementHistory::splitCell8::splitCell8()
119 //- Construct as child element of parent
120 Foam::refinementHistory::splitCell8::splitCell8(const label parent)
127 //- Construct from Istream
128 Foam::refinementHistory::splitCell8::splitCell8(Istream& is)
134 //- Construct as (deep) copy.
135 Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc)
140 sc.addedCellsPtr_.valid()
141 ? new FixedList<label, 8>(sc.addedCellsPtr_())
147 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
149 Foam::Istream& Foam::operator>>(Istream& is, refinementHistory::splitCell8& sc)
151 labelList addedCells;
153 is >> sc.parent_ >> addedCells;
155 if (addedCells.size() > 0)
157 sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
161 sc.addedCellsPtr_.reset(NULL);
168 Foam::Ostream& Foam::operator<<
171 const refinementHistory::splitCell8& sc
174 // Output as labelList so we can have 0 sized lists. Alternative is to
175 // output as fixedlist with e.g. -1 elements and check for this upon
176 // reading. However would cause much more data to be transferred.
178 if (sc.addedCellsPtr_.valid())
183 << labelList(sc.addedCellsPtr_());
187 return os << sc.parent_ << token::SPACE << labelList(0);
192 void Foam::refinementHistory::checkIndices() const
195 forAll(visibleCells_, i)
197 if (visibleCells_[i] < 0 && visibleCells_[i] >= splitCells_.size())
199 FatalErrorIn("refinementHistory::checkIndices() const")
200 << "Illegal entry " << visibleCells_[i]
201 << " in visibleCells at location" << i << nl
202 << "It points outside the range of splitCells : 0.."
203 << splitCells_.size()-1
204 << abort(FatalError);
210 Foam::label Foam::refinementHistory::allocateSplitCell
218 if (freeSplitCells_.size() > 0)
220 index = freeSplitCells_.remove();
222 splitCells_[index] = splitCell8(parent);
226 index = splitCells_.size();
228 splitCells_.append(splitCell8(parent));
232 // Update the parent field
235 splitCell8& parentSplit = splitCells_[parent];
237 if (!parentSplit.addedCellsPtr_.valid())
239 // Allocate storage on parent for the 8 subcells.
240 parentSplit.addedCellsPtr_.reset(new FixedList<label, 8>(-1));
244 // Store me on my parent
245 FixedList<label, 8>& parentSplits = parentSplit.addedCellsPtr_();
247 parentSplits[i] = index;
254 void Foam::refinementHistory::freeSplitCell(const label index)
256 splitCell8& split = splitCells_[index];
258 // Make sure parent does not point to me anymore.
259 if (split.parent_ >= 0)
261 autoPtr<FixedList<label, 8> >& subCellsPtr =
262 splitCells_[split.parent_].addedCellsPtr_;
264 if (subCellsPtr.valid())
266 FixedList<label, 8>& subCells = subCellsPtr();
268 label myPos = findIndex(subCells, index);
272 FatalErrorIn("refinementHistory::freeSplitCell")
273 << "Problem: cannot find myself in"
274 << " parents' children" << abort(FatalError);
278 subCells[myPos] = -1;
283 // Mark splitCell as free
286 // Add to cache of free splitCells
287 freeSplitCells_.append(index);
291 // Mark entry in splitCells. Recursively mark its parent and subs.
292 void Foam::refinementHistory::markSplit
296 DynamicList<splitCell8>& newSplitCells
299 if (oldToNew[index] == -1)
301 // Not yet compacted.
303 const splitCell8& split = splitCells_[index];
305 oldToNew[index] = newSplitCells.size();
306 newSplitCells.append(split);
308 if (split.parent_ >= 0)
310 markSplit(split.parent_, oldToNew, newSplitCells);
312 if (split.addedCellsPtr_.valid())
314 const FixedList<label, 8>& splits = split.addedCellsPtr_();
320 markSplit(splits[i], oldToNew, newSplitCells);
328 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
330 Foam::refinementHistory::refinementHistory(const IOobject& io)
336 io.readOpt() == IOobject::MUST_READ
337 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
340 readStream(typeName) >> *this;
346 Pout<< "refinementHistory::refinementHistory :"
347 << " constructed history from IOobject :"
348 << " splitCells:" << splitCells_.size()
349 << " visibleCells:" << visibleCells_.size()
355 //- Read or construct
356 Foam::refinementHistory::refinementHistory
359 const List<splitCell8>& splitCells,
360 const labelList& visibleCells
364 splitCells_(splitCells),
366 visibleCells_(visibleCells)
370 io.readOpt() == IOobject::MUST_READ
371 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
374 readStream(typeName) >> *this;
383 Pout<< "refinementHistory::refinementHistory :"
384 << " constructed history from IOobject or components :"
385 << " splitCells:" << splitCells_.size()
386 << " visibleCells:" << visibleCells_.size()
392 // Construct from initial number of cells (all visible)
393 Foam::refinementHistory::refinementHistory
404 io.readOpt() == IOobject::MUST_READ
405 || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
408 readStream(typeName) >> *this;
413 splitCells_.setSize(nCells, splitCell8());
414 visibleCells_ = identity(nCells);
422 Pout<< "refinementHistory::refinementHistory :"
423 << " constructed history from IOobject or initial size :"
424 << " splitCells:" << splitCells_.size()
425 << " visibleCells:" << visibleCells_.size()
432 Foam::refinementHistory::refinementHistory
435 const refinementHistory& rh
439 splitCells_(rh.splitCells()),
440 freeSplitCells_(rh.freeSplitCells()),
441 visibleCells_(rh.visibleCells())
445 Pout<< "refinementHistory::refinementHistory : constructed initial"
446 << " history." << endl;
451 // Construct from Istream
452 Foam::refinementHistory::refinementHistory(const IOobject& io, Istream& is)
464 Pout<< "refinementHistory::refinementHistory :"
465 << " constructed history from Istream"
466 << " splitCells:" << splitCells_.size()
467 << " visibleCells:" << visibleCells_.size()
473 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
475 void Foam::refinementHistory::resize(const label size)
477 label oldSize = visibleCells_.size();
481 Pout<< "refinementHistory::resize from " << oldSize << " to " << size
485 visibleCells_.setSize(size);
487 // Set additional elements to -1.
488 for (label i = oldSize; i < visibleCells_.size(); i++)
490 visibleCells_[i] = -1;
495 void Foam::refinementHistory::updateMesh(const mapPolyMesh& map)
499 const labelList& reverseCellMap = map.reverseCellMap();
501 // Note that only the live cells need to be renumbered.
503 labelList newVisibleCells(map.cellMap().size(), -1);
505 forAll(visibleCells_, cellI)
507 if (visibleCells_[cellI] != -1)
509 label index = visibleCells_[cellI];
512 if (splitCells_[index].addedCellsPtr_.valid())
516 "refinementHistory::updateMesh(const mapPolyMesh&)"
517 ) << "Problem" << abort(FatalError);
520 label newCellI = reverseCellMap[cellI];
524 newVisibleCells[newCellI] = index;
531 Pout<< "refinementHistory::updateMesh : from "
532 << visibleCells_.size()
533 << " to " << newVisibleCells.size()
537 visibleCells_.transfer(newVisibleCells);
542 // Update numbering for subsetting
543 void Foam::refinementHistory::subset
545 const labelList& pointMap,
546 const labelList& faceMap,
547 const labelList& cellMap
552 labelList newVisibleCells(cellMap.size(), -1);
554 forAll(newVisibleCells, cellI)
556 label oldCellI = cellMap[cellI];
558 label index = visibleCells_[oldCellI];
560 // Check that cell is live (so its parent has no refinement)
561 if (index >= 0 && splitCells_[index].addedCellsPtr_.valid())
565 "refinementHistory::subset"
566 "(const labelList&, const labelList&, const labelList&)"
567 ) << "Problem" << abort(FatalError);
570 newVisibleCells[cellI] = index;
575 Pout<< "refinementHistory::updateMesh : from "
576 << visibleCells_.size()
577 << " to " << newVisibleCells.size()
581 visibleCells_.transfer(newVisibleCells);
586 void Foam::refinementHistory::countProc
589 const label newProcNo,
590 labelList& splitCellProc,
591 labelList& splitCellNum
594 if (splitCellProc[index] != newProcNo)
596 // Different destination processor from other cells using this
597 // parent. Reset count.
598 splitCellProc[index] = newProcNo;
599 splitCellNum[index] = 1;
603 splitCellNum[index]++;
605 // Increment parent if whole splitCell moves to same processor
606 if (splitCellNum[index] == 8)
608 Pout<< "Moving " << splitCellNum[index]
609 << " cells originating from cell " << index
610 << " from processor " << Pstream::myProcNo()
611 << " to processor " << splitCellProc[index]
614 label parent = splitCells_[index].parent_;
618 string oldPrefix = Pout.prefix();
619 Pout.prefix() = " " + oldPrefix;
621 countProc(parent, newProcNo, splitCellProc, splitCellNum);
623 Pout.prefix() = oldPrefix;
630 void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
636 "refinementHistory::distribute(const mapDistributePolyMesh&)"
637 ) << "Calling distribute on inactive history" << abort(FatalError);
641 if (!Pstream::parRun())
646 // Remove unreferenced history.
649 Pout<< nl << "--BEFORE:" << endl;
651 Pout<< "---------" << nl << endl;
654 // Distribution is only partially functional.
655 // If all 8 cells resulting from a single parent are sent across in one
656 // go it will also send across that part of the refinement history.
657 // If however e.g. first 1 and then the other 7 are sent across the
658 // history will not be reconstructed.
660 // Determine clusters. This is per every entry in splitCells_ (that is
661 // a parent of some refinement) a label giving the processor it goes to
662 // if all its children are going to the same processor.
664 // Per visible cell the processor it goes to.
665 labelList destination(visibleCells_.size());
667 const labelListList& subCellMap = map.cellMap().subMap();
669 forAll(subCellMap, procI)
671 const labelList& newToOld = subCellMap[procI];
675 label oldCellI = newToOld[i];
677 destination[oldCellI] = procI;
681 //Pout<< "refinementHistory::distribute :"
682 // << " destination:" << destination << endl;
684 // Per splitCell entry the processor it moves to
685 labelList splitCellProc(splitCells_.size(), -1);
686 // Per splitCell entry the number of live cells that move to that processor
687 labelList splitCellNum(splitCells_.size(), 0);
689 forAll(visibleCells_, cellI)
691 label index = visibleCells_[cellI];
697 splitCells_[index].parent_,
705 Pout<< "refinementHistory::distribute :"
706 << " splitCellProc:" << splitCellProc << endl;
708 Pout<< "refinementHistory::distribute :"
709 << " splitCellNum:" << splitCellNum << endl;
712 // Create subsetted refinement tree consisting of all parents that
713 // move in their whole to other processor.
714 for (label procI = 0; procI < Pstream::nProcs(); procI++)
716 Pout<< "-- Subetting for processor " << procI << endl;
718 // From uncompacted to compacted splitCells.
719 labelList oldToNew(splitCells_.size(), -1);
721 // Compacted splitCells. Similar to subset routine below.
722 DynamicList<splitCell8> newSplitCells(splitCells_.size());
724 // Loop over all entries. Note: could recurse like countProc so only
725 // visit used entries but is probably not worth it.
727 forAll(splitCells_, index)
729 // Pout<< "oldCell:" << index
730 // << " proc:" << splitCellProc[index]
731 // << " nCells:" << splitCellNum[index]
734 if (splitCellProc[index] == procI && splitCellNum[index] == 8)
736 // Entry moves in its whole to procI
737 oldToNew[index] = newSplitCells.size();
738 newSplitCells.append(splitCells_[index]);
740 Pout<< "Added oldCell " << index
741 << " info " << newSplitCells[newSplitCells.size()-1]
742 << " at position " << newSplitCells.size()-1
747 // Add live cells that are subsetted.
748 forAll(visibleCells_, cellI)
750 label index = visibleCells_[cellI];
752 if (index >= 0 && destination[cellI] == procI)
754 label parent = splitCells_[index].parent_;
756 Pout<< "Adding refined cell " << cellI
757 << " since moves to "
758 << procI << " old parent:" << parent << endl;
760 // Create new splitCell with parent
761 oldToNew[index] = newSplitCells.size();
762 newSplitCells.append(splitCell8(parent));
766 //forAll(oldToNew, index)
768 // Pout<< "old:" << index << " new:" << oldToNew[index]
772 newSplitCells.shrink();
774 // Renumber contents of newSplitCells
775 forAll(newSplitCells, index)
777 splitCell8& split = newSplitCells[index];
779 if (split.parent_ >= 0)
781 split.parent_ = oldToNew[split.parent_];
783 if (split.addedCellsPtr_.valid())
785 FixedList<label, 8>& splits = split.addedCellsPtr_();
791 splits[i] = oldToNew[splits[i]];
798 const labelList& subMap = subCellMap[procI];
800 // New visible cells.
801 labelList newVisibleCells(subMap.size(), -1);
803 forAll(subMap, newCellI)
805 label oldCellI = subMap[newCellI];
807 label oldIndex = visibleCells_[oldCellI];
811 newVisibleCells[newCellI] = oldToNew[oldIndex];
815 //Pout<< nl << "--Subset for domain:" << procI << endl;
816 //writeDebug(newVisibleCells, newSplitCells);
817 //Pout<< "---------" << nl << endl;
820 // Send to neighbours
821 OPstream toNbr(Pstream::blocking, procI);
822 toNbr << newSplitCells << newVisibleCells;
826 // Receive from neighbours and merge
827 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
829 // Remove all entries. Leave storage intact.
832 visibleCells_.setSize(map.mesh().nCells());
835 for (label procI = 0; procI < Pstream::nProcs(); procI++)
837 IPstream fromNbr(Pstream::blocking, procI);
838 List<splitCell8> newSplitCells(fromNbr);
839 labelList newVisibleCells(fromNbr);
841 //Pout<< nl << "--Received from domain:" << procI << endl;
842 //writeDebug(newVisibleCells, newSplitCells);
843 //Pout<< "---------" << nl << endl;
846 // newSplitCells contain indices only into newSplitCells so
847 // renumbering can be done here.
848 label offset = splitCells_.size();
850 Pout<< "**Renumbering data from proc " << procI << " with offset "
853 forAll(newSplitCells, index)
855 splitCell8& split = newSplitCells[index];
857 if (split.parent_ >= 0)
859 split.parent_ += offset;
861 if (split.addedCellsPtr_.valid())
863 FixedList<label, 8>& splits = split.addedCellsPtr_();
874 splitCells_.append(split);
878 // Combine visibleCell.
879 const labelList& constructMap = map.cellMap().constructMap()[procI];
881 forAll(newVisibleCells, i)
883 visibleCells_[constructMap[i]] = newVisibleCells[i] + offset;
886 splitCells_.shrink();
888 Pout<< nl << "--AFTER:" << endl;
890 Pout<< "---------" << nl << endl;
894 void Foam::refinementHistory::compact()
898 Pout<< "refinementHistory::compact() Entering with:"
899 << " freeSplitCells_:" << freeSplitCells_.size()
900 << " splitCells_:" << splitCells_.size()
901 << " visibleCells_:" << visibleCells_.size()
904 // Check all free splitCells are marked as such
905 forAll(freeSplitCells_, i)
907 label index = freeSplitCells_[i];
909 if (splitCells_[index].parent_ != -2)
911 FatalErrorIn("refinementHistory::compact()")
912 << "Problem index:" << index
913 << abort(FatalError);
917 // Check none of the visible cells are marked as free
918 forAll(visibleCells_, cellI)
922 visibleCells_[cellI] >= 0
923 && splitCells_[visibleCells_[cellI]].parent_ == -2
926 FatalErrorIn("refinementHistory::compact()")
927 << "Problem : visible cell:" << cellI
928 << " is marked as being free." << abort(FatalError);
933 DynamicList<splitCell8> newSplitCells(splitCells_.size());
935 // From uncompacted to compacted splitCells.
936 labelList oldToNew(splitCells_.size(), -1);
938 // Mark all used splitCell entries. These are either indexed by visibleCells
939 // or indexed from other splitCell entries.
941 // Mark from visibleCells
942 forAll(visibleCells_, cellI)
944 label index = visibleCells_[cellI];
948 // Make sure we only mark visible indices if they either have a
949 // parent or subsplits.
952 splitCells_[index].parent_ != -1
953 || splitCells_[index].addedCellsPtr_.valid()
956 markSplit(index, oldToNew, newSplitCells);
961 // Mark from splitCells
962 forAll(splitCells_, index)
964 if (splitCells_[index].parent_ == -2)
970 splitCells_[index].parent_ == -1
971 && !splitCells_[index].addedCellsPtr_.valid()
974 // recombined cell. No need to keep since no parent and no subsplits
975 // Note that gets marked if reachable from other index!
980 markSplit(index, oldToNew, newSplitCells);
985 // Now oldToNew is fully complete and compacted elements are in
987 // Renumber contents of newSplitCells and visibleCells.
988 forAll(newSplitCells, index)
990 splitCell8& split = newSplitCells[index];
992 if (split.parent_ >= 0)
994 split.parent_ = oldToNew[split.parent_];
996 if (split.addedCellsPtr_.valid())
998 FixedList<label, 8>& splits = split.addedCellsPtr_();
1004 splits[i] = oldToNew[splits[i]];
1013 Pout<< "refinementHistory::compact : compacted splitCells from "
1014 << splitCells_.size() << " to " << newSplitCells.size() << endl;
1017 splitCells_.transfer(newSplitCells);
1018 freeSplitCells_.clear();
1019 freeSplitCells_.labelList::clear();
1024 Pout<< "refinementHistory::compact() NOW:"
1025 << " freeSplitCells_:" << freeSplitCells_.size()
1026 << " splitCells_:" << splitCells_.size()
1027 << " newSplitCells:" << newSplitCells.size()
1028 << " visibleCells_:" << visibleCells_.size()
1033 // Adapt indices in visibleCells_
1034 forAll(visibleCells_, cellI)
1036 label index = visibleCells_[cellI];
1040 // Note that oldToNew can be -1 so it resets newVisibleCells.
1041 visibleCells_[cellI] = oldToNew[index];
1051 void Foam::refinementHistory::writeDebug() const
1053 writeDebug(visibleCells_, splitCells_);
1057 void Foam::refinementHistory::storeSplit
1060 const labelList& addedCells
1063 label parentIndex = -1;
1065 if (visibleCells_[cellI] != -1)
1067 // Was already live. The current live cell becomes the
1068 // parent of the cells split off from it.
1070 parentIndex = visibleCells_[cellI];
1072 // It is no longer live (note that actually cellI gets alive
1073 // again below since is addedCells[0])
1074 visibleCells_[cellI] = -1;
1078 // Create 0th level. -1 parent to denote this.
1079 parentIndex = allocateSplitCell(-1, -1);
1082 // Create live entries for added cells that point to the
1083 // cell they were created from (parentIndex)
1084 forAll(addedCells, i)
1086 label addedCellI = addedCells[i];
1088 // Create entries for the split off cells. All of them
1090 visibleCells_[addedCellI] = allocateSplitCell(parentIndex, i);
1095 void Foam::refinementHistory::combineCells
1097 const label masterCellI,
1098 const labelList& combinedCells
1101 // Save the parent structure
1102 label parentIndex = splitCells_[visibleCells_[masterCellI]].parent_;
1104 // Remove the information for the combined cells
1105 forAll(combinedCells, i)
1107 label cellI = combinedCells[i];
1109 freeSplitCell(visibleCells_[cellI]);
1110 visibleCells_[cellI] = -1;
1113 splitCell8& parentSplit = splitCells_[parentIndex];
1114 parentSplit.addedCellsPtr_.reset(NULL);
1115 visibleCells_[masterCellI] = parentIndex;
1119 bool Foam::refinementHistory::readData(Istream& is)
1126 bool Foam::refinementHistory::writeData(Ostream& os) const
1134 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
1136 Foam::Istream& Foam::operator>>(Istream& is, refinementHistory& rh)
1138 rh.freeSplitCells_.clear();
1140 is >> rh.splitCells_ >> rh.visibleCells_;
1149 Foam::Ostream& Foam::operator<<(Ostream& os, const refinementHistory& rh)
1151 const_cast<refinementHistory&>(rh).compact();
1153 return os << "// splitCells" << nl
1154 << rh.splitCells_ << nl
1155 << "// visibleCells" << nl
1156 << rh.visibleCells_;
1160 // ************************************************************************* //