initial commit for version 1.5.x patch release
[OpenFOAM-1.5.x.git] / src / dynamicMesh / polyTopoChange / polyTopoChange / refinementHistory.C
blob15d28b5b602dfe1cb1a9494bc26248558dbfcbb4
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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"
29 #include "ListOps.H"
30 #include "mapPolyMesh.H"
31 #include "mapDistributePolyMesh.H"
32 #include "polyMesh.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 namespace Foam
39 defineTypeNameAndDebug(refinementHistory, 0);
44 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
46 void Foam::refinementHistory::writeEntry
48     const List<splitCell8>& splitCells,
49     const splitCell8& split
52     // Write me:
53     if (split.addedCellsPtr_.valid())
54     {
55         Pout<< "parent:" << split.parent_
56             << " subCells:" << split.addedCellsPtr_()
57             << endl;
58     }
59     else
60     {
61         Pout<< "parent:" << split.parent_
62             << " no subcells"
63             << endl;
64     }
65     if (split.parent_ >= 0)
66     {
67         Pout<< "parent data:" << endl;
68         // Write my parent
69         string oldPrefix = Pout.prefix();
70         Pout.prefix() = "  " + oldPrefix;
71         writeEntry(splitCells, splitCells[split.parent_]);
72         Pout.prefix() = oldPrefix;
73     }
77 void Foam::refinementHistory::writeDebug
79     const labelList& visibleCells,
80     const List<splitCell8>& splitCells
83     string oldPrefix = Pout.prefix();
84     Pout.prefix() = "";
86     forAll(visibleCells, cellI)
87     {
88         label index = visibleCells[cellI];
90         if (index >= 0)
91         {
92             Pout<< "Cell from refinement:" << cellI << " index:" << index
93                 << endl;
95             string oldPrefix = Pout.prefix();
96             Pout.prefix() = "  " + oldPrefix;
97             writeEntry(splitCells, splitCells[index]);
98             Pout.prefix() = oldPrefix;
99         }
100         else
101         {
102             Pout<< "Unrefined cell:" << cellI << " index:" << index << endl;
103         }
104     }
105     Pout.prefix() = oldPrefix;
109 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
111 //- Construct null
112 Foam::refinementHistory::splitCell8::splitCell8()
114     parent_(-1),
115     addedCellsPtr_(NULL)
119 //- Construct as child element of parent
120 Foam::refinementHistory::splitCell8::splitCell8(const label parent)
122     parent_(parent),
123     addedCellsPtr_(NULL)
127 //- Construct from Istream
128 Foam::refinementHistory::splitCell8::splitCell8(Istream& is)
130     is >> *this;
134 //- Construct as (deep) copy.
135 Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc)
137     parent_(sc.parent_),
138     addedCellsPtr_
139     (
140         sc.addedCellsPtr_.valid()
141       ? new FixedList<label, 8>(sc.addedCellsPtr_())
142       : NULL
143     )
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)
156     {
157         sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
158     }
159     else
160     {
161         sc.addedCellsPtr_.reset(NULL);
162     }
164     return is;
168 Foam::Ostream& Foam::operator<<
170     Ostream& os,
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())
179     {
180         return os
181             << sc.parent_
182             << token::SPACE
183             << labelList(sc.addedCellsPtr_());
184     }
185     else
186     {
187         return os << sc.parent_ << token::SPACE << labelList(0);
188     }
192 void Foam::refinementHistory::checkIndices() const
194     // Check indices.
195     forAll(visibleCells_, i)
196     {
197         if (visibleCells_[i] < 0 && visibleCells_[i] >= splitCells_.size())
198         {
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);
205         }
206     }
210 Foam::label Foam::refinementHistory::allocateSplitCell
212     const label parent,
213     const label i
216     label index = -1;
218     if (freeSplitCells_.size() > 0)
219     {
220         index = freeSplitCells_.remove();
222         splitCells_[index] = splitCell8(parent);
223     }
224     else
225     {
226         index = splitCells_.size();
228         splitCells_.append(splitCell8(parent));
229     }
232     // Update the parent field
233     if (parent >= 0)
234     {
235         splitCell8& parentSplit = splitCells_[parent];
237         if (!parentSplit.addedCellsPtr_.valid())
238         {
239             // Allocate storage on parent for the 8 subcells.
240             parentSplit.addedCellsPtr_.reset(new FixedList<label, 8>(-1));
241         }
244         // Store me on my parent
245         FixedList<label, 8>& parentSplits = parentSplit.addedCellsPtr_();
247         parentSplits[i] = index;
248     }
250     return 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)
260     {
261         autoPtr<FixedList<label, 8> >& subCellsPtr =
262             splitCells_[split.parent_].addedCellsPtr_;
264         if (subCellsPtr.valid())
265         {
266             FixedList<label, 8>& subCells = subCellsPtr();
268             label myPos = findIndex(subCells, index);
270             if (myPos == -1)
271             {
272                 FatalErrorIn("refinementHistory::freeSplitCell")
273                     << "Problem: cannot find myself in"
274                     << " parents' children" << abort(FatalError);
275             }
276             else
277             {
278                 subCells[myPos] = -1;
279             }
280         }
281     }
283     // Mark splitCell as free
284     split.parent_ = -2;
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
294     const label index,
295     labelList& oldToNew,
296     DynamicList<splitCell8>& newSplitCells
297 ) const
299     if (oldToNew[index] == -1)
300     {
301         // Not yet compacted.
303         const splitCell8& split = splitCells_[index];
305         oldToNew[index] = newSplitCells.size();
306         newSplitCells.append(split);
308         if (split.parent_ >= 0)
309         {
310             markSplit(split.parent_, oldToNew, newSplitCells);
311         }
312         if (split.addedCellsPtr_.valid())
313         {
314             const FixedList<label, 8>& splits = split.addedCellsPtr_();
316             forAll(splits, i)
317             {
318                 if (splits[i] >= 0)
319                 {
320                     markSplit(splits[i], oldToNew, newSplitCells);
321                 }
322             }
323         }
324     }
328 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
330 Foam::refinementHistory::refinementHistory(const IOobject& io)
332     regIOobject(io)
334     if
335     (
336         io.readOpt() == IOobject::MUST_READ
337      || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
338     )
339     {
340         readStream(typeName) >> *this;
341         close();
342     }
344     if (debug)
345     {
346         Pout<< "refinementHistory::refinementHistory :"
347             << " constructed history from IOobject :"
348             << " splitCells:" << splitCells_.size()
349             << " visibleCells:" << visibleCells_.size()
350             << endl;
351     }
355 //- Read or construct
356 Foam::refinementHistory::refinementHistory
358     const IOobject& io,
359     const List<splitCell8>& splitCells,
360     const labelList& visibleCells
363     regIOobject(io),
364     splitCells_(splitCells),
365     freeSplitCells_(0),
366     visibleCells_(visibleCells)
368     if
369     (
370         io.readOpt() == IOobject::MUST_READ
371      || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
372     )
373     {
374         readStream(typeName) >> *this;
375         close();
376     }
378     // Check indices.
379     checkIndices();
381     if (debug)
382     {
383         Pout<< "refinementHistory::refinementHistory :"
384             << " constructed history from IOobject or components :"
385             << " splitCells:" << splitCells_.size()
386             << " visibleCells:" << visibleCells_.size()
387             << endl;
388     }
392 // Construct from initial number of cells (all visible)
393 Foam::refinementHistory::refinementHistory
395     const IOobject& io,
396     const label nCells
399     regIOobject(io),
400     freeSplitCells_(0)
402     if
403     (
404         io.readOpt() == IOobject::MUST_READ
405      || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
406     )
407     {
408         readStream(typeName) >> *this;
409         close();        
410     }
411     else
412     {
413         splitCells_.setSize(nCells, splitCell8());
414         visibleCells_ = identity(nCells);
415     }
417     // Check indices.
418     checkIndices();
420     if (debug)
421     {
422         Pout<< "refinementHistory::refinementHistory :"
423             << " constructed history from IOobject or initial size :"
424             << " splitCells:" << splitCells_.size()
425             << " visibleCells:" << visibleCells_.size()
426             << endl;
427     }
431 // Construct as copy
432 Foam::refinementHistory::refinementHistory
434     const IOobject& io,
435     const refinementHistory& rh
438     regIOobject(io),
439     splitCells_(rh.splitCells()),
440     freeSplitCells_(rh.freeSplitCells()),
441     visibleCells_(rh.visibleCells())
443     if (debug)
444     {
445         Pout<< "refinementHistory::refinementHistory : constructed initial"
446             << " history." << endl;
447     }
451 // Construct from Istream
452 Foam::refinementHistory::refinementHistory(const IOobject& io, Istream& is)
454     regIOobject(io),
455     splitCells_(is),
456     freeSplitCells_(0),
457     visibleCells_(is)
459     // Check indices.
460     checkIndices();
462     if (debug)
463     {
464         Pout<< "refinementHistory::refinementHistory :"
465             << " constructed history from Istream"
466             << " splitCells:" << splitCells_.size()
467             << " visibleCells:" << visibleCells_.size()
468             << endl;
469     }
473 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
475 void Foam::refinementHistory::resize(const label size)
477     label oldSize = visibleCells_.size();
479     if (debug)
480     {
481         Pout<< "refinementHistory::resize from " << oldSize << " to " << size
482             << " cells" << endl;
483     }
485     visibleCells_.setSize(size);
487     // Set additional elements to -1.
488     for (label i = oldSize; i < visibleCells_.size(); i++)
489     {
490         visibleCells_[i] = -1;
491     }
494     
495 void Foam::refinementHistory::updateMesh(const mapPolyMesh& map)
497     if (active())
498     {
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)
506         {
507             if (visibleCells_[cellI] != -1)
508             {
509                 label index = visibleCells_[cellI];
511                 // Check
512                 if (splitCells_[index].addedCellsPtr_.valid())
513                 {
514                     FatalErrorIn
515                     (
516                         "refinementHistory::updateMesh(const mapPolyMesh&)"
517                     )   << "Problem" << abort(FatalError);
518                 }
520                 label newCellI = reverseCellMap[cellI];
522                 if (newCellI >= 0)
523                 {
524                     newVisibleCells[newCellI] = index;
525                 }
526             }
527         }
529         if (debug)
530         {
531             Pout<< "refinementHistory::updateMesh : from "
532                 << visibleCells_.size()
533                 << " to " << newVisibleCells.size()
534                 << " cells" << endl;
535         }
537         visibleCells_.transfer(newVisibleCells);
538     }
542 // Update numbering for subsetting
543 void Foam::refinementHistory::subset
545     const labelList& pointMap,
546     const labelList& faceMap,
547     const labelList& cellMap
550     if (active())
551     {
552         labelList newVisibleCells(cellMap.size(), -1);
554         forAll(newVisibleCells, cellI)
555         {
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())
562             {
563                 FatalErrorIn
564                 (
565                     "refinementHistory::subset"
566                     "(const labelList&, const labelList&, const labelList&)"
567                 )   << "Problem" << abort(FatalError);
568             }
570             newVisibleCells[cellI] = index;
571         }
573         if (debug)
574         {
575             Pout<< "refinementHistory::updateMesh : from "
576                 << visibleCells_.size()
577                 << " to " << newVisibleCells.size()
578                 << " cells" << endl;
579         }
581         visibleCells_.transfer(newVisibleCells);
582     }
586 void Foam::refinementHistory::countProc
588     const label index,
589     const label newProcNo,
590     labelList& splitCellProc,
591     labelList& splitCellNum
592 ) const
594     if (splitCellProc[index] != newProcNo)
595     {
596         // Different destination processor from other cells using this
597         // parent. Reset count.
598         splitCellProc[index] = newProcNo;
599         splitCellNum[index] = 1;
600     }
601     else
602     {
603         splitCellNum[index]++;
605         // Increment parent if whole splitCell moves to same processor
606         if (splitCellNum[index] == 8)
607         {
608             Pout<< "Moving " << splitCellNum[index]
609                 << " cells originating from cell " << index
610                 << " from processor " << Pstream::myProcNo()
611                 << " to processor " << splitCellProc[index]
612                 << endl;
614             label parent = splitCells_[index].parent_;
616             if (parent >= 0)
617             {
618                 string oldPrefix = Pout.prefix();
619                 Pout.prefix() = "  " + oldPrefix;
621                 countProc(parent, newProcNo, splitCellProc, splitCellNum);
623                 Pout.prefix() = oldPrefix;
624             }
625         }
626     }
630 void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
632     if (!active())
633     {
634         FatalErrorIn
635         (
636             "refinementHistory::distribute(const mapDistributePolyMesh&)"
637         )   << "Calling distribute on inactive history" << abort(FatalError);
638     }
641     if (!Pstream::parRun())
642     {
643         return;
644     }
646     // Remove unreferenced history.
647     compact();
649     Pout<< nl << "--BEFORE:" << endl;
650     writeDebug();
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)
670     {
671         const labelList& newToOld = subCellMap[procI];
673         forAll(newToOld, i)
674         {
675             label oldCellI = newToOld[i];
677             destination[oldCellI] = procI;
678         }
679     }
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)
690     {
691         label index = visibleCells_[cellI];
693         if (index >= 0)
694         {
695             countProc
696             (
697                 splitCells_[index].parent_,
698                 destination[cellI],
699                 splitCellProc,
700                 splitCellNum
701             );
702         }
703     }
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++)
715     {
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)
728         {
729 //            Pout<< "oldCell:" << index
730 //                << " proc:" << splitCellProc[index]
731 //                << " nCells:" << splitCellNum[index]
732 //                << endl;
734             if (splitCellProc[index] == procI && splitCellNum[index] == 8)
735             {
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
743                     << endl;
744             }
745         }
747         // Add live cells that are subsetted.
748         forAll(visibleCells_, cellI)
749         {
750             label index = visibleCells_[cellI];
752             if (index >= 0 && destination[cellI] == procI)
753             {
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));
763             }
764         }
766         //forAll(oldToNew, index)
767         //{
768         //    Pout<< "old:" << index << " new:" << oldToNew[index]
769         //        << endl;
770         //}
772         newSplitCells.shrink();
774         // Renumber contents of newSplitCells
775         forAll(newSplitCells, index)
776         {
777             splitCell8& split = newSplitCells[index];
779             if (split.parent_ >= 0)
780             {
781                 split.parent_ = oldToNew[split.parent_];
782             }
783             if (split.addedCellsPtr_.valid())
784             {
785                 FixedList<label, 8>& splits = split.addedCellsPtr_();
787                 forAll(splits, i)
788                 {
789                     if (splits[i] >= 0)
790                     {
791                         splits[i] = oldToNew[splits[i]];
792                     }
793                 }
794             }
795         }
798         const labelList& subMap = subCellMap[procI];
800         // New visible cells.
801         labelList newVisibleCells(subMap.size(), -1);
803         forAll(subMap, newCellI)
804         {
805             label oldCellI = subMap[newCellI];
807             label oldIndex = visibleCells_[oldCellI];
809             if (oldIndex >= 0)
810             {
811                 newVisibleCells[newCellI] = oldToNew[oldIndex];
812             }
813         }
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;
823     }
826     // Receive from neighbours and merge
827     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
829     // Remove all entries. Leave storage intact.
830     splitCells_.clear();
832     visibleCells_.setSize(map.mesh().nCells());
833     visibleCells_ = -1;
835     for (label procI = 0; procI < Pstream::nProcs(); procI++)
836     {
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 "
851             << offset << endl;
853         forAll(newSplitCells, index)
854         {
855             splitCell8& split = newSplitCells[index];
857             if (split.parent_ >= 0)
858             {
859                 split.parent_ += offset;
860             }
861             if (split.addedCellsPtr_.valid())
862             {
863                 FixedList<label, 8>& splits = split.addedCellsPtr_();
865                 forAll(splits, i)
866                 {
867                     if (splits[i] >= 0)
868                     {
869                         splits[i] += offset;
870                     }
871                 }
872             }
874             splitCells_.append(split);
875         }
878         // Combine visibleCell.
879         const labelList& constructMap = map.cellMap().constructMap()[procI];
881         forAll(newVisibleCells, i)
882         {
883             visibleCells_[constructMap[i]] = newVisibleCells[i] + offset;
884         }
885     }
886     splitCells_.shrink();
888     Pout<< nl << "--AFTER:" << endl;
889     writeDebug();
890     Pout<< "---------" << nl << endl;
894 void Foam::refinementHistory::compact()
896     if (debug)
897     {
898         Pout<< "refinementHistory::compact() Entering with:"
899             << " freeSplitCells_:" << freeSplitCells_.size()
900             << " splitCells_:" << splitCells_.size()
901             << " visibleCells_:" << visibleCells_.size()
902             << endl;
904         // Check all free splitCells are marked as such
905         forAll(freeSplitCells_, i)
906         {
907             label index = freeSplitCells_[i];
909             if (splitCells_[index].parent_ != -2)
910             {
911                 FatalErrorIn("refinementHistory::compact()")
912                     << "Problem index:" << index
913                     << abort(FatalError);
914             }
915         }
917         // Check none of the visible cells are marked as free
918         forAll(visibleCells_, cellI)
919         {
920             if
921             (
922                 visibleCells_[cellI] >= 0
923              && splitCells_[visibleCells_[cellI]].parent_ == -2
924             )
925             {
926                 FatalErrorIn("refinementHistory::compact()")
927                     << "Problem : visible cell:" << cellI
928                     << " is marked as being free." << abort(FatalError);
929             }
930         }
931     }
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)
943     {
944         label index = visibleCells_[cellI];
946         if (index >= 0)
947         {
948             // Make sure we only mark visible indices if they either have a
949             // parent or subsplits.
950             if
951             (
952                 splitCells_[index].parent_ != -1
953              || splitCells_[index].addedCellsPtr_.valid()
954             )
955             {
956                 markSplit(index, oldToNew, newSplitCells);
957             }
958         }
959     }
961     // Mark from splitCells
962     forAll(splitCells_, index)
963     {
964         if (splitCells_[index].parent_ == -2)
965         {
966             // freed cell.
967         }
968         else if
969         (
970             splitCells_[index].parent_ == -1
971          && !splitCells_[index].addedCellsPtr_.valid()
972         )
973         {
974             // recombined cell. No need to keep since no parent and no subsplits
975             // Note that gets marked if reachable from other index!
976         }
977         else
978         {
979             // Is used element.
980             markSplit(index, oldToNew, newSplitCells);
981         }
982     }
985     // Now oldToNew is fully complete and compacted elements are in
986     // newSplitCells. 
987     // Renumber contents of newSplitCells and visibleCells.
988     forAll(newSplitCells, index)
989     {
990         splitCell8& split = newSplitCells[index];
992         if (split.parent_ >= 0)
993         {
994             split.parent_ = oldToNew[split.parent_];
995         }
996         if (split.addedCellsPtr_.valid())
997         {
998             FixedList<label, 8>& splits = split.addedCellsPtr_();
1000             forAll(splits, i)
1001             {
1002                 if (splits[i] >= 0)
1003                 {
1004                     splits[i] = oldToNew[splits[i]];
1005                 }
1006             }
1007         }
1008     }
1011     if (debug)
1012     {
1013         Pout<< "refinementHistory::compact : compacted splitCells from "
1014             << splitCells_.size() << " to " << newSplitCells.size() << endl;
1015     }
1017     splitCells_.transfer(newSplitCells);
1018     freeSplitCells_.clear();
1019     freeSplitCells_.labelList::clear();
1022     if (debug)
1023     {
1024         Pout<< "refinementHistory::compact() NOW:"
1025             << " freeSplitCells_:" << freeSplitCells_.size()
1026             << " splitCells_:" << splitCells_.size()
1027             << " newSplitCells:" << newSplitCells.size()
1028             << " visibleCells_:" << visibleCells_.size()
1029             << endl;
1030     }
1033     // Adapt indices in visibleCells_
1034     forAll(visibleCells_, cellI)
1035     {
1036         label index = visibleCells_[cellI];
1038         if (index >= 0)
1039         {
1040             // Note that oldToNew can be -1 so it resets newVisibleCells.
1041             visibleCells_[cellI] = oldToNew[index];
1042         }
1043         else
1044         {
1045             // Keep -1 value.
1046         }
1047     }
1051 void Foam::refinementHistory::writeDebug() const
1053     writeDebug(visibleCells_, splitCells_);
1057 void Foam::refinementHistory::storeSplit
1059     const label cellI,
1060     const labelList& addedCells
1063     label parentIndex = -1;
1065     if (visibleCells_[cellI] != -1)
1066     {
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;
1075     }
1076     else
1077     {
1078         // Create 0th level. -1 parent to denote this.
1079         parentIndex = allocateSplitCell(-1, -1);
1080     }
1082     // Create live entries for added cells that point to the
1083     // cell they were created from (parentIndex)
1084     forAll(addedCells, i)
1085     {
1086         label addedCellI = addedCells[i];
1088         // Create entries for the split off cells. All of them
1089         // are visible.
1090         visibleCells_[addedCellI] = allocateSplitCell(parentIndex, i);
1091     }
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)
1106     {
1107         label cellI = combinedCells[i];
1109         freeSplitCell(visibleCells_[cellI]);
1110         visibleCells_[cellI] = -1;
1111     }
1113     splitCell8& parentSplit = splitCells_[parentIndex];
1114     parentSplit.addedCellsPtr_.reset(NULL);
1115     visibleCells_[masterCellI] = parentIndex;
1119 bool Foam::refinementHistory::readData(Istream& is)
1121     is >> *this;
1122     return !is.bad();
1126 bool Foam::refinementHistory::writeData(Ostream& os) const
1128     os << *this;
1130     return os.good();
1134 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
1136 Foam::Istream& Foam::operator>>(Istream& is, refinementHistory& rh)
1138     rh.freeSplitCells_.clear();
1140     is >> rh.splitCells_ >> rh.visibleCells_;
1142     // Check indices.
1143     rh.checkIndices();
1145     return is;
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 // ************************************************************************* //