refinementHistory.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "DynamicList.H"
27 #include "refinementHistory.H"
28 #include "ListOps.H"
29 #include "mapPolyMesh.H"
30 #include "mapDistributePolyMesh.H"
31 #include "polyMesh.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 defineTypeNameAndDebug(refinementHistory, 0);
39 
40 }
41 
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 void Foam::refinementHistory::writeEntry
46 (
47  const List<splitCell8>& splitCells,
48  const splitCell8& split
49 )
50 {
51  // Write me:
52  if (split.addedCellsPtr_.valid())
53  {
54  Pout<< "parent:" << split.parent_
55  << " subCells:" << split.addedCellsPtr_()
56  << endl;
57  }
58  else
59  {
60  Pout<< "parent:" << split.parent_
61  << " no subcells"
62  << endl;
63  }
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  }
74 }
75 
76 
78 (
79  const labelList& visibleCells,
80  const List<splitCell8>& splitCells
81 )
82 {
83  string oldPrefix = Pout.prefix();
84  Pout.prefix() = "";
85 
86  forAll(visibleCells, cellI)
87  {
88  label index = visibleCells[cellI];
89 
90  if (index >= 0)
91  {
92  Pout<< "Cell from refinement:" << cellI << " index:" << index
93  << endl;
94 
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;
106 }
107 
108 
109 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
110 
111 //- Construct null
113 :
114  parent_(-1),
115  addedCellsPtr_(NULL)
116 {}
117 
118 
119 //- Construct as child element of parent
121 :
122  parent_(parent),
123  addedCellsPtr_(NULL)
124 {}
125 
126 
127 //- Construct from Istream
129 {
130  is >> *this;
131 }
132 
133 
134 //- Construct as (deep) copy.
136 :
137  parent_(sc.parent_),
139  (
140  sc.addedCellsPtr_.valid()
141  ? new FixedList<label, 8>(sc.addedCellsPtr_())
142  : NULL
143  )
144 {}
145 
146 
147 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
148 
150 {
151  labelList addedCells;
152 
153  is >> sc.parent_ >> addedCells;
154 
155  if (addedCells.size())
156  {
157  sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
158  }
159  else
160  {
161  sc.addedCellsPtr_.reset(NULL);
162  }
163 
164  return is;
165 }
166 
167 
168 Foam::Ostream& Foam::operator<<
169 (
170  Ostream& os,
172 )
173 {
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.
177 
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  }
189 }
190 
191 
192 void Foam::refinementHistory::checkIndices() const
193 {
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  }
207 }
208 
209 
210 Foam::label Foam::refinementHistory::allocateSplitCell
211 (
212  const label parent,
213  const label i
214 )
215 {
216  label index = -1;
217 
218  if (freeSplitCells_.size())
219  {
220  index = freeSplitCells_.remove();
221 
222  splitCells_[index] = splitCell8(parent);
223  }
224  else
225  {
226  index = splitCells_.size();
227 
228  splitCells_.append(splitCell8(parent));
229  }
230 
231 
232  // Update the parent field
233  if (parent >= 0)
234  {
235  splitCell8& parentSplit = splitCells_[parent];
236 
237  if (parentSplit.addedCellsPtr_.empty())
238  {
239  // Allocate storage on parent for the 8 subcells.
240  parentSplit.addedCellsPtr_.reset(new FixedList<label, 8>(-1));
241  }
242 
243 
244  // Store me on my parent
245  FixedList<label, 8>& parentSplits = parentSplit.addedCellsPtr_();
246 
247  parentSplits[i] = index;
248  }
249 
250  return index;
251 }
252 
253 
254 void Foam::refinementHistory::freeSplitCell(const label index)
255 {
256  splitCell8& split = splitCells_[index];
257 
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_;
263 
264  if (subCellsPtr.valid())
265  {
266  FixedList<label, 8>& subCells = subCellsPtr();
267 
268  label myPos = findIndex(subCells, index);
269 
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  }
282 
283  // Mark splitCell as free
284  split.parent_ = -2;
285 
286  // Add to cache of free splitCells
287  freeSplitCells_.append(index);
288 }
289 
290 
291 // Mark entry in splitCells. Recursively mark its parent and subs.
292 void Foam::refinementHistory::markSplit
293 (
294  const label index,
295  labelList& oldToNew,
296  DynamicList<splitCell8>& newSplitCells
297 ) const
298 {
299  if (oldToNew[index] == -1)
300  {
301  // Not yet compacted.
302 
303  const splitCell8& split = splitCells_[index];
304 
305  oldToNew[index] = newSplitCells.size();
306  newSplitCells.append(split);
307 
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_();
315 
316  forAll(splits, i)
317  {
318  if (splits[i] >= 0)
319  {
320  markSplit(splits[i], oldToNew, newSplitCells);
321  }
322  }
323  }
324  }
325 }
326 
327 
328 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
329 
331 :
332  regIOobject(io)
333 {
334  // Temporary warning
336  {
337  WarningIn
338  (
339  "refinementHistory::refinementHistory(const IOobject&)"
340  ) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
341  << " does not support automatic rereading."
342  << endl;
343  }
344 
345  if
346  (
349  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
350  )
351  {
352  readStream(typeName) >> *this;
353  close();
354  }
355 
356  if (debug)
357  {
358  Pout<< "refinementHistory::refinementHistory :"
359  << " constructed history from IOobject :"
360  << " splitCells:" << splitCells_.size()
361  << " visibleCells:" << visibleCells_.size()
362  << endl;
363  }
364 }
365 
366 
367 //- Read or construct
369 (
370  const IOobject& io,
371  const List<splitCell8>& splitCells,
372  const labelList& visibleCells
373 )
374 :
375  regIOobject(io),
376  splitCells_(splitCells),
377  freeSplitCells_(0),
378  visibleCells_(visibleCells)
379 {
380  // Temporary warning
382  {
383  WarningIn
384  (
385  "refinementHistory::refinementHistory"
386  "(const IOobject&, const List<splitCell8>&, const labelList&)"
387  ) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
388  << " does not support automatic rereading."
389  << endl;
390  }
391 
392  if
393  (
396  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
397  )
398  {
399  readStream(typeName) >> *this;
400  close();
401  }
402 
403  // Check indices.
404  checkIndices();
405 
406  if (debug)
407  {
408  Pout<< "refinementHistory::refinementHistory :"
409  << " constructed history from IOobject or components :"
410  << " splitCells:" << splitCells_.size()
411  << " visibleCells:" << visibleCells_.size()
412  << endl;
413  }
414 }
415 
416 
417 // Construct from initial number of cells (all visible)
419 (
420  const IOobject& io,
421  const label nCells
422 )
423 :
424  regIOobject(io),
425  freeSplitCells_(0)
426 {
427  // Temporary warning
429  {
430  WarningIn
431  (
432  "refinementHistory::refinementHistory"
433  "(const IOobject&, const label)"
434  ) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
435  << " does not support automatic rereading."
436  << endl;
437  }
438 
439  if
440  (
443  || (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
444  )
445  {
446  readStream(typeName) >> *this;
447  close();
448  }
449  else
450  {
451  visibleCells_.setSize(nCells);
452  splitCells_.setCapacity(nCells);
453 
454  for (label cellI = 0; cellI < nCells; cellI++)
455  {
456  visibleCells_[cellI] = cellI;
457  splitCells_.append(splitCell8());
458  }
459  }
460 
461  // Check indices.
462  checkIndices();
463 
464  if (debug)
465  {
466  Pout<< "refinementHistory::refinementHistory :"
467  << " constructed history from IOobject or initial size :"
468  << " splitCells:" << splitCells_.size()
469  << " visibleCells:" << visibleCells_.size()
470  << endl;
471  }
472 }
473 
474 
475 // Construct as copy
477 (
478  const IOobject& io,
479  const refinementHistory& rh
480 )
481 :
482  regIOobject(io),
483  splitCells_(rh.splitCells()),
484  freeSplitCells_(rh.freeSplitCells()),
485  visibleCells_(rh.visibleCells())
486 {
487  if (debug)
488  {
489  Pout<< "refinementHistory::refinementHistory : constructed initial"
490  << " history." << endl;
491  }
492 }
493 
494 
495 // Construct from Istream
497 :
498  regIOobject(io),
499  splitCells_(is),
500  freeSplitCells_(0),
501  visibleCells_(is)
502 {
503  // Check indices.
504  checkIndices();
505 
506  if (debug)
507  {
508  Pout<< "refinementHistory::refinementHistory :"
509  << " constructed history from Istream"
510  << " splitCells:" << splitCells_.size()
511  << " visibleCells:" << visibleCells_.size()
512  << endl;
513  }
514 }
515 
516 
517 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
518 
520 {
521  label oldSize = visibleCells_.size();
522 
523  if (debug)
524  {
525  Pout<< "refinementHistory::resize from " << oldSize << " to " << size
526  << " cells" << endl;
527  }
528 
529  visibleCells_.setSize(size);
530 
531  // Set additional elements to -1.
532  for (label i = oldSize; i < visibleCells_.size(); i++)
533  {
534  visibleCells_[i] = -1;
535  }
536 }
537 
538 
540 {
541  if (active())
542  {
543  const labelList& reverseCellMap = map.reverseCellMap();
544 
545  // Note that only the live cells need to be renumbered.
546 
547  labelList newVisibleCells(map.cellMap().size(), -1);
548 
549  forAll(visibleCells_, cellI)
550  {
551  if (visibleCells_[cellI] != -1)
552  {
553  label index = visibleCells_[cellI];
554 
555  // Check not already set
556  if (splitCells_[index].addedCellsPtr_.valid())
557  {
559  (
560  "refinementHistory::updateMesh(const mapPolyMesh&)"
561  ) << "Problem" << abort(FatalError);
562  }
563 
564  label newCellI = reverseCellMap[cellI];
565 
566  if (newCellI >= 0)
567  {
568  newVisibleCells[newCellI] = index;
569  }
570  }
571  }
572 
573  if (debug)
574  {
575  Pout<< "refinementHistory::updateMesh : from "
576  << visibleCells_.size()
577  << " to " << newVisibleCells.size()
578  << " cells" << endl;
579  }
580 
581  visibleCells_.transfer(newVisibleCells);
582  }
583 }
584 
585 
586 // Update numbering for subsetting
588 (
589  const labelList& pointMap,
590  const labelList& faceMap,
591  const labelList& cellMap
592 )
593 {
594  if (active())
595  {
596  labelList newVisibleCells(cellMap.size(), -1);
597 
598  forAll(newVisibleCells, cellI)
599  {
600  label oldCellI = cellMap[cellI];
601 
602  label index = visibleCells_[oldCellI];
603 
604  // Check that cell is live (so its parent has no refinement)
605  if (index >= 0 && splitCells_[index].addedCellsPtr_.valid())
606  {
608  (
609  "refinementHistory::subset"
610  "(const labelList&, const labelList&, const labelList&)"
611  ) << "Problem" << abort(FatalError);
612  }
613 
614  newVisibleCells[cellI] = index;
615  }
616 
617  if (debug)
618  {
619  Pout<< "refinementHistory::updateMesh : from "
620  << visibleCells_.size()
621  << " to " << newVisibleCells.size()
622  << " cells" << endl;
623  }
624 
625  visibleCells_.transfer(newVisibleCells);
626  }
627 }
628 
629 
630 void Foam::refinementHistory::countProc
631 (
632  const label index,
633  const label newProcNo,
634  labelList& splitCellProc,
635  labelList& splitCellNum
636 ) const
637 {
638  if (splitCellProc[index] != newProcNo)
639  {
640  // Different destination processor from other cells using this
641  // parent. Reset count.
642  splitCellProc[index] = newProcNo;
643  splitCellNum[index] = 1;
644  }
645  else
646  {
647  splitCellNum[index]++;
648 
649  // Increment parent if whole splitCell moves to same processor
650  if (splitCellNum[index] == 8)
651  {
652  if (debug)
653  {
654  Pout<< "Moving " << splitCellNum[index]
655  << " cells originating from cell " << index
656  << " from processor " << Pstream::myProcNo()
657  << " to processor " << splitCellProc[index]
658  << endl;
659  }
660 
661  label parent = splitCells_[index].parent_;
662 
663  if (parent >= 0)
664  {
665  countProc(parent, newProcNo, splitCellProc, splitCellNum);
666  }
667  }
668  }
669 }
670 
671 
673 {
674  if (!active())
675  {
677  (
678  "refinementHistory::distribute(const mapDistributePolyMesh&)"
679  ) << "Calling distribute on inactive history" << abort(FatalError);
680  }
681 
682 
683  if (!Pstream::parRun())
684  {
685  return;
686  }
687 
688  // Remove unreferenced history.
689  compact();
690 
691  //Pout<< nl << "--BEFORE:" << endl;
692  //writeDebug();
693  //Pout<< "---------" << nl << endl;
694 
695 
696  // Distribution is only partially functional.
697  // If all 8 cells resulting from a single parent are sent across in one
698  // go it will also send across that part of the refinement history.
699  // If however e.g. first 1 and then the other 7 are sent across the
700  // history will not be reconstructed.
701 
702  // Determine clusters. This is per every entry in splitCells_ (that is
703  // a parent of some refinement) a label giving the processor it goes to
704  // if all its children are going to the same processor.
705 
706  // Per visible cell the processor it goes to.
707  labelList destination(visibleCells_.size());
708 
709  const labelListList& subCellMap = map.cellMap().subMap();
710 
711  forAll(subCellMap, procI)
712  {
713  const labelList& newToOld = subCellMap[procI];
714 
715  forAll(newToOld, i)
716  {
717  label oldCellI = newToOld[i];
718 
719  destination[oldCellI] = procI;
720  }
721  }
722 
723 //Pout<< "refinementHistory::distribute :"
724 // << " destination:" << destination << endl;
725 
726  // Per splitCell entry the processor it moves to
727  labelList splitCellProc(splitCells_.size(), -1);
728  // Per splitCell entry the number of live cells that move to that processor
729  labelList splitCellNum(splitCells_.size(), 0);
730 
731  forAll(visibleCells_, cellI)
732  {
733  label index = visibleCells_[cellI];
734 
735  if (index >= 0)
736  {
737  countProc
738  (
739  splitCells_[index].parent_,
740  destination[cellI],
741  splitCellProc,
742  splitCellNum
743  );
744  }
745  }
746 
747  //Pout<< "refinementHistory::distribute :"
748  // << " splitCellProc:" << splitCellProc << endl;
749  //
750  //Pout<< "refinementHistory::distribute :"
751  // << " splitCellNum:" << splitCellNum << endl;
752 
753 
754  // Create subsetted refinement tree consisting of all parents that
755  // move in their whole to other processor.
756  for (label procI = 0; procI < Pstream::nProcs(); procI++)
757  {
758  //Pout<< "-- Subetting for processor " << procI << endl;
759 
760  // From uncompacted to compacted splitCells.
761  labelList oldToNew(splitCells_.size(), -1);
762 
763  // Compacted splitCells. Similar to subset routine below.
764  DynamicList<splitCell8> newSplitCells(splitCells_.size());
765 
766  // Loop over all entries. Note: could recurse like countProc so only
767  // visit used entries but is probably not worth it.
768 
769  forAll(splitCells_, index)
770  {
771 // Pout<< "oldCell:" << index
772 // << " proc:" << splitCellProc[index]
773 // << " nCells:" << splitCellNum[index]
774 // << endl;
775 
776  if (splitCellProc[index] == procI && splitCellNum[index] == 8)
777  {
778  // Entry moves in its whole to procI
779  oldToNew[index] = newSplitCells.size();
780  newSplitCells.append(splitCells_[index]);
781 
782  //Pout<< "Added oldCell " << index
783  // << " info " << newSplitCells.last()
784  // << " at position " << newSplitCells.size()-1
785  // << endl;
786  }
787  }
788 
789  // Add live cells that are subsetted.
790  forAll(visibleCells_, cellI)
791  {
792  label index = visibleCells_[cellI];
793 
794  if (index >= 0 && destination[cellI] == procI)
795  {
796  label parent = splitCells_[index].parent_;
797 
798  //Pout<< "Adding refined cell " << cellI
799  // << " since moves to "
800  // << procI << " old parent:" << parent << endl;
801 
802  // Create new splitCell with parent
803  oldToNew[index] = newSplitCells.size();
804  newSplitCells.append(splitCell8(parent));
805  }
806  }
807 
808  //forAll(oldToNew, index)
809  //{
810  // Pout<< "old:" << index << " new:" << oldToNew[index]
811  // << endl;
812  //}
813 
814  newSplitCells.shrink();
815 
816  // Renumber contents of newSplitCells
817  forAll(newSplitCells, index)
818  {
819  splitCell8& split = newSplitCells[index];
820 
821  if (split.parent_ >= 0)
822  {
823  split.parent_ = oldToNew[split.parent_];
824  }
825  if (split.addedCellsPtr_.valid())
826  {
827  FixedList<label, 8>& splits = split.addedCellsPtr_();
828 
829  forAll(splits, i)
830  {
831  if (splits[i] >= 0)
832  {
833  splits[i] = oldToNew[splits[i]];
834  }
835  }
836  }
837  }
838 
839 
840  const labelList& subMap = subCellMap[procI];
841 
842  // New visible cells.
843  labelList newVisibleCells(subMap.size(), -1);
844 
845  forAll(subMap, newCellI)
846  {
847  label oldCellI = subMap[newCellI];
848 
849  label oldIndex = visibleCells_[oldCellI];
850 
851  if (oldIndex >= 0)
852  {
853  newVisibleCells[newCellI] = oldToNew[oldIndex];
854  }
855  }
856 
857  //Pout<< nl << "--Subset for domain:" << procI << endl;
858  //writeDebug(newVisibleCells, newSplitCells);
859  //Pout<< "---------" << nl << endl;
860 
861 
862  // Send to neighbours
863  OPstream toNbr(Pstream::blocking, procI);
864  toNbr << newSplitCells << newVisibleCells;
865  }
866 
867 
868  // Receive from neighbours and merge
869  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
870 
871  // Remove all entries. Leave storage intact.
872  splitCells_.clear();
873 
874  visibleCells_.setSize(map.mesh().nCells());
875  visibleCells_ = -1;
876 
877  for (label procI = 0; procI < Pstream::nProcs(); procI++)
878  {
879  IPstream fromNbr(Pstream::blocking, procI);
880  List<splitCell8> newSplitCells(fromNbr);
881  labelList newVisibleCells(fromNbr);
882 
883  //Pout<< nl << "--Received from domain:" << procI << endl;
884  //writeDebug(newVisibleCells, newSplitCells);
885  //Pout<< "---------" << nl << endl;
886 
887 
888  // newSplitCells contain indices only into newSplitCells so
889  // renumbering can be done here.
890  label offset = splitCells_.size();
891 
892  //Pout<< "**Renumbering data from proc " << procI << " with offset "
893  // << offset << endl;
894 
895  forAll(newSplitCells, index)
896  {
897  splitCell8& split = newSplitCells[index];
898 
899  if (split.parent_ >= 0)
900  {
901  split.parent_ += offset;
902  }
903  if (split.addedCellsPtr_.valid())
904  {
905  FixedList<label, 8>& splits = split.addedCellsPtr_();
906 
907  forAll(splits, i)
908  {
909  if (splits[i] >= 0)
910  {
911  splits[i] += offset;
912  }
913  }
914  }
915 
916  splitCells_.append(split);
917  }
918 
919 
920  // Combine visibleCell.
921  const labelList& constructMap = map.cellMap().constructMap()[procI];
922 
923  forAll(newVisibleCells, i)
924  {
925  if (newVisibleCells[i] >= 0)
926  {
927  visibleCells_[constructMap[i]] = newVisibleCells[i] + offset;
928  }
929  }
930  }
931  splitCells_.shrink();
932 
933  //Pout<< nl << "--AFTER:" << endl;
934  //writeDebug();
935  //Pout<< "---------" << nl << endl;
936 }
937 
938 
940 {
941  if (debug)
942  {
943  Pout<< "refinementHistory::compact() Entering with:"
944  << " freeSplitCells_:" << freeSplitCells_.size()
945  << " splitCells_:" << splitCells_.size()
946  << " visibleCells_:" << visibleCells_.size()
947  << endl;
948 
949  // Check all free splitCells are marked as such
950  forAll(freeSplitCells_, i)
951  {
952  label index = freeSplitCells_[i];
953 
954  if (splitCells_[index].parent_ != -2)
955  {
956  FatalErrorIn("refinementHistory::compact()")
957  << "Problem index:" << index
958  << abort(FatalError);
959  }
960  }
961 
962  // Check none of the visible cells are marked as free
963  forAll(visibleCells_, cellI)
964  {
965  if
966  (
967  visibleCells_[cellI] >= 0
968  && splitCells_[visibleCells_[cellI]].parent_ == -2
969  )
970  {
971  FatalErrorIn("refinementHistory::compact()")
972  << "Problem : visible cell:" << cellI
973  << " is marked as being free." << abort(FatalError);
974  }
975  }
976  }
977 
978  DynamicList<splitCell8> newSplitCells(splitCells_.size());
979 
980  // From uncompacted to compacted splitCells.
981  labelList oldToNew(splitCells_.size(), -1);
982 
983  // Mark all used splitCell entries. These are either indexed by visibleCells
984  // or indexed from other splitCell entries.
985 
986  // Mark from visibleCells
987  forAll(visibleCells_, cellI)
988  {
989  label index = visibleCells_[cellI];
990 
991  if (index >= 0)
992  {
993  // Make sure we only mark visible indices if they either have a
994  // parent or subsplits.
995  if
996  (
997  splitCells_[index].parent_ != -1
998  || splitCells_[index].addedCellsPtr_.valid()
999  )
1000  {
1001  markSplit(index, oldToNew, newSplitCells);
1002  }
1003  }
1004  }
1005 
1006  // Mark from splitCells
1007  forAll(splitCells_, index)
1008  {
1009  if (splitCells_[index].parent_ == -2)
1010  {
1011  // freed cell.
1012  }
1013  else if
1014  (
1015  splitCells_[index].parent_ == -1
1016  && splitCells_[index].addedCellsPtr_.empty()
1017  )
1018  {
1019  // recombined cell. No need to keep since no parent and no subsplits
1020  // Note that gets marked if reachable from other index!
1021  }
1022  else
1023  {
1024  // Is used element.
1025  markSplit(index, oldToNew, newSplitCells);
1026  }
1027  }
1028 
1029 
1030  // Now oldToNew is fully complete and compacted elements are in
1031  // newSplitCells.
1032  // Renumber contents of newSplitCells and visibleCells.
1033  forAll(newSplitCells, index)
1034  {
1035  splitCell8& split = newSplitCells[index];
1036 
1037  if (split.parent_ >= 0)
1038  {
1039  split.parent_ = oldToNew[split.parent_];
1040  }
1041  if (split.addedCellsPtr_.valid())
1042  {
1043  FixedList<label, 8>& splits = split.addedCellsPtr_();
1044 
1045  forAll(splits, i)
1046  {
1047  if (splits[i] >= 0)
1048  {
1049  splits[i] = oldToNew[splits[i]];
1050  }
1051  }
1052  }
1053  }
1054 
1055 
1056  if (debug)
1057  {
1058  Pout<< "refinementHistory::compact : compacted splitCells from "
1059  << splitCells_.size() << " to " << newSplitCells.size() << endl;
1060  }
1061 
1062  splitCells_.transfer(newSplitCells);
1063  freeSplitCells_.clearStorage();
1064 
1065 
1066  if (debug)
1067  {
1068  Pout<< "refinementHistory::compact() NOW:"
1069  << " freeSplitCells_:" << freeSplitCells_.size()
1070  << " splitCells_:" << splitCells_.size()
1071  << " newSplitCells:" << newSplitCells.size()
1072  << " visibleCells_:" << visibleCells_.size()
1073  << endl;
1074  }
1075 
1076 
1077  // Adapt indices in visibleCells_
1078  forAll(visibleCells_, cellI)
1079  {
1080  label index = visibleCells_[cellI];
1081 
1082  if (index >= 0)
1083  {
1084  // Note that oldToNew can be -1 so it resets newVisibleCells.
1085  visibleCells_[cellI] = oldToNew[index];
1086  }
1087  else
1088  {
1089  // Keep -1 value.
1090  }
1091  }
1092 }
1093 
1094 
1096 {
1097  writeDebug(visibleCells_, splitCells_);
1098 }
1099 
1100 
1103  const label cellI,
1104  const labelList& addedCells
1105 )
1106 {
1107  label parentIndex = -1;
1108 
1109  if (visibleCells_[cellI] != -1)
1110  {
1111  // Was already live. The current live cell becomes the
1112  // parent of the cells split off from it.
1113 
1114  parentIndex = visibleCells_[cellI];
1115 
1116  // It is no longer live (note that actually cellI gets alive
1117  // again below since is addedCells[0])
1118  visibleCells_[cellI] = -1;
1119  }
1120  else
1121  {
1122  // Create 0th level. -1 parent to denote this.
1123  parentIndex = allocateSplitCell(-1, -1);
1124  }
1125 
1126  // Create live entries for added cells that point to the
1127  // cell they were created from (parentIndex)
1128  forAll(addedCells, i)
1129  {
1130  label addedCellI = addedCells[i];
1131 
1132  // Create entries for the split off cells. All of them
1133  // are visible.
1134  visibleCells_[addedCellI] = allocateSplitCell(parentIndex, i);
1135  }
1136 }
1137 
1138 
1141  const label masterCellI,
1142  const labelList& combinedCells
1143 )
1144 {
1145  // Save the parent structure
1146  label parentIndex = splitCells_[visibleCells_[masterCellI]].parent_;
1147 
1148  // Remove the information for the combined cells
1149  forAll(combinedCells, i)
1150  {
1151  label cellI = combinedCells[i];
1152 
1153  freeSplitCell(visibleCells_[cellI]);
1154  visibleCells_[cellI] = -1;
1155  }
1156 
1157  splitCell8& parentSplit = splitCells_[parentIndex];
1158  parentSplit.addedCellsPtr_.reset(NULL);
1159  visibleCells_[masterCellI] = parentIndex;
1160 }
1161 
1162 
1164 {
1165  is >> *this;
1166  return !is.bad();
1167 }
1168 
1169 
1171 {
1172  os << *this;
1173 
1174  return os.good();
1175 }
1176 
1177 
1178 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
1179 
1181 {
1182  rh.freeSplitCells_.clearStorage();
1183 
1184  is >> rh.splitCells_ >> rh.visibleCells_;
1185 
1186  // Check indices.
1187  rh.checkIndices();
1188 
1189  return is;
1190 }
1191 
1192 
1194 {
1195  const_cast<refinementHistory&>(rh).compact();
1196 
1197  return os << "// splitCells" << nl
1198  << rh.splitCells_ << nl
1199  << "// visibleCells" << nl
1200  << rh.visibleCells_;
1201 }
1202 
1203 
1204 // ************************************************************************* //
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:380
const string & prefix() const
Return the prefix of the stream.
const labelListList & subMap() const
From subsetted data back to original data.
readOption readOpt() const
Definition: IOobject.H:304
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
autoPtr< FixedList< label, 8 > > addedCellsPtr_
Cells this cell was refined into.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
bool bad() const
Return true if stream is corrupted.
Definition: IOstream.H:351
const mapDistribute & cellMap() const
Cell distribute map.
void writeDebug() const
Debug write.
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set).
Definition: autoPtrI.H:83
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
void storeSplit(const label cellI, const labelList &addedCells)
Store splitting of cell into 8.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
const labelList & visibleCells() const
Per cell in the current mesh (i.e. visible) either -1 (unrefined)
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:310
Output inter-processor communications stream.
Definition: OPstream.H:50
label nCells() const
Various functions to operate on Lists.
All refinement history. Used in unrefinement.
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
Ostream & operator<<(Ostream &, const edgeMesh &)
Definition: edgeMeshIO.C:133
Namespace for OpenFOAM.
void resize(const label nCells)
Extend/shrink storage. additional visibleCells_ elements get.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
void distribute(const mapDistributePolyMesh &)
Update local numbering for mesh redistribution.
static const char nl
Definition: Ostream.H:260
regIOobject(const IOobject &, const bool isTime=false)
Construct from IOobject. Optional flag for if IOobject is the.
Definition: regIOobject.C:121
void setSize(const label)
Reset size of List.
Definition: List.C:318
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
#define WarningIn(functionName)
Report a warning using Foam::Warning.
const polyMesh & mesh() const
#define forAll(list, i)
Definition: UList.H:421
void close()
Close Istream.
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
const DynamicList< label > & freeSplitCells() const
Cache of unused indices in splitCells.
virtual bool readData(Istream &)
ReadData function required for regIOobject read operation.
splitCell8()
Construct null (parent = -1)
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
errorManip< error > abort(error &err)
Definition: errorManip.H:131
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
void updateMesh(const mapPolyMesh &)
Update numbering for mesh changes.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
void compact()
Compact splitCells_. Removes all freeSplitCells_ elements.
void combineCells(const label masterCellI, const labelList &combinedCells)
Store combining 8 cells into master.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:60
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
error FatalError
Input inter-processor communications stream.
Definition: IPstream.H:50
refinementHistory(const IOobject &)
Construct (read) given an IOobject.
List< label > labelList
A List of labels.
Definition: labelList.H:56
Istream & operator>>(Istream &, edgeMesh &)
Definition: edgeMeshIO.C:144
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
const labelList & reverseCellMap() const
Reverse cell map.
Definition: mapPolyMesh.H:528
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:249
const DynamicList< splitCell8 > & splitCells() const
Storage for splitCell8s.
bool headerOk()
Read and check header info.
Definition: IOobject.C:424
virtual bool writeData(Ostream &) const
WriteData function required for regIOobject write operation.
bool active() const
Is there unrefinement history. Note that this will fall over if.
Istream & readStream(const word &)
Return Istream and check object type against that given.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
void subset(const labelList &pointMap, const labelList &faceMap, const labelList &cellMap)
Update numbering for subsetting.
defineTypeNameAndDebug(combustionModel, 0)
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
const labelList & cellMap() const
Old cell map.
Definition: mapPolyMesh.H:431
label parentIndex(const label cellI) const
Get parent of cell.