Peano 4
Loading...
Searching...
No Matches
Spacetree.cpp
Go to the documentation of this file.
1#include "Spacetree.h"
2
3#include "grid.h"
5#include "PeanoCurve.h"
6#include "TraversalObserver.h"
12#include "peano4/utils/Loop.h"
14#include "tarch/mpi/Rank.h"
16
17tarch::logging::Log peano4::grid::Spacetree::_log("peano4::grid::Spacetree");
18
20
24 const std::bitset<Dimensions>& periodicBC
25):
26 _id(0),
27 _spacetreeState(SpacetreeState::NewRoot),
28 _root(),
29 _masterId(-1),
30 _periodicBC(periodicBC),
31 _gridTraversalEventGenerator(0) {
32 _root.setLevel(0);
33 _root.setX(offset);
34 _root.setH(width);
35 _root.setInverted(false);
37
38 for (int i = 0; i < DimensionsTimesTwo; i++) {
40 }
41
43 clear(_statistics, _id == 0);
44
45 logDebug("Spacetree(...)", "create spacetree with " << offset << "x" << width << " and periodic BCs=" << _periodicBC);
46}
47
49 int newId,
50 int masterId,
53 bool traversalInverted
54):
55 _id(newId),
56 _spacetreeState(SpacetreeState::EmptyRun),
57 _root(),
58 _statistics(),
59 _masterId(masterId),
60 _periodicBC(0),
61 _splitTriggered(),
62 _splitting(),
63 _gridTraversalEventGenerator(newId) {
64 _root.setLevel(0);
65 _root.setX(offset);
66 _root.setH(width);
67 _root.setInverted(traversalInverted);
68 _root.setEvenFlags(std::bitset<Dimensions>(0));
69
70 for (int i = 0; i < DimensionsTimesTwo; i++) {
72 }
73
75 clear(_statistics, _id == 0);
76
77 logInfo("Spacetree(...)", "created spacetree " << _id << " with master tree " << masterId);
78}
79
81
83 GridVertex vertex, bool splittingIsConsideredLocal, bool joiningIsConsideredLocal
84) const {
86 and _gridTraversalEventGenerator.isVertexAdjacentToLocalSpacetree(
87 vertex,
88 _splitTriggered,
89 _splitting,
90 _joinTriggered,
91 _joining,
92 splittingIsConsideredLocal,
93 joiningIsConsideredLocal
94 );
95}
96
98 bool result = true;
99 dfor2(k) result &= (vertices[kScalar].getState() != GridVertex::State::HangingVertex);
100 enddforx return result;
101}
102
104 bool result = true;
105 dfor2(k) result &= (vertices[kScalar].getState() == GridVertex::State::Refined);
106 enddforx return result;
107}
108
110 bool result = true;
111 dfor2(k) result &= (vertices[kScalar].getState() == GridVertex::State::Unrefined);
112 enddforx return result;
113}
114
116 GridVertex vertices[TwoPowerD], bool splittingIsConsideredLocal, bool joiningIsConsideredLocal
117) const {
118 return _gridTraversalEventGenerator.isSpacetreeNodeLocal(
119 vertices, _splitTriggered, _splitting, _joinTriggered, _joining, splittingIsConsideredLocal, joiningIsConsideredLocal
120 );
121}
122
123void peano4::grid::Spacetree::traverse(TraversalObserver& observer, bool calledFromSpacetreeSet) {
124 logTraceIn("traverse(TraversalObserver)");
125
126 for (int d = 0; d < TwoTimesD; d++) {
127 assertion2(_root.getAccessNumber(d) > -2 * Dimensions, d, _root.toString());
128 assertion2(_root.getAccessNumber(d) < 2 * Dimensions, d, _root.toString());
129 }
130
131 if (calledFromSpacetreeSet) {
132 assertion(_joinTriggered.empty() or _splitTriggered.empty());
133 assertion(_joinTriggered.empty() or _splitting.empty());
134 assertion(_joining.empty() or _splitTriggered.empty());
135 assertion(_joining.empty() or _splitting.empty());
136 logDebug(
137 "traverse(TraversalObserver)",
138 _splitTriggered.size() << " tree split triggered and " << _splitting.size() << " splitting trees on tree " << _id
139 );
140 }
141
142 clear(_statistics, _id == 0);
143
144 if (_spacetreeState == SpacetreeState::EmptyRun or _spacetreeState == SpacetreeState::NewFromSplit or _spacetreeState == SpacetreeState::Joining) {
145 _gridControlEvents.clear();
146 } else {
147 _gridControlEvents = merge(observer.getGridControlEvents());
148
149 const int MagicUpperLimitToWhichIDumpEvents = 4;
150#if PeanoDebug > 0
151 if (_gridControlEvents.empty()) {
152 logInfo("traverse(...)", "got no grid refinement events");
153 } else
154#endif
155 if (not _gridControlEvents.empty() and _gridControlEvents.size() <= MagicUpperLimitToWhichIDumpEvents) {
156 std::ostringstream msg;
157 for (auto& p : _gridControlEvents)
158 msg << p.toString();
159 logInfo("traverse(...)", "got " << _gridControlEvents.size() << " grid control events: " << msg.str());
160 } else if (not _gridControlEvents.empty()) {
161 logInfo("traverse(...)", "got " << _gridControlEvents.size() << " grid control events");
162 }
163
164 if (not _gridControlEvents.empty()) {
166 "grid-control-events", ::peano4::grid::toString(_gridControlEvents)
167 );
168 }
169 }
170
171 _splittedCells.clear();
172
173 const bool isFirstTraversal = _spacetreeState == SpacetreeState::NewRoot;
174
175 GridVertex vertices[TwoPowerD];
177 adjacentRanks(TwoPowerD - 1 - kScalar) = 0;
178 vertices[kScalar] = createVertex(
180 _root.getX() + tarch::la::convertScalar<double>(k),
181 0,
182 adjacentRanks,
183 false
184 );
185 logDebug("traverse(TraversalObserver)", "create " << vertices[kScalar].toString() << " for tree " << _id);
187
188 for (int d = 0; d < Dimensions; d++) {
189 if (_periodicBC[d]) {
190 dfor2(vertex) dfor2(entries) tarch::la::Vector<Dimensions, int> entry = entries;
191 if (vertex(d) == 0) {
192 entry(d) = 0;
193 } else {
194 entry(d) = 1;
195 }
196 vertices[vertexScalar].setAdjacentRanks(peano4::utils::dLinearised(entry, 2), RankOfPeriodicBoundaryCondition);
198 "traverse(TraversalObserver)", "set periodic boundary conditions: " << vertices[vertexScalar].toString()
199 );
201 }
202 }
203
204 observer.beginTraversal(_root.getX(), _root.getH());
205
206 descend(_root, vertices, observer);
207
208 observer.endTraversal(_root.getX(), _root.getH());
209
210 _root.setInverted(not _root.getInverted());
211
212 if (calledFromSpacetreeSet) {
213 _hasSplit.clear();
214 for (auto& rank : _splitting) {
215 _childrenIds.insert(rank);
216 _hasSplit.insert(rank);
217 }
218 _splitting.clear();
219 for (auto& p : _splitTriggered) {
220 if (p.second.numberOfFineGridCells > 0) {
221 logInfo(
222 "traverse(TraversalObserver)",
223 "have not been able to assign enough cells from "
224 << _id << " to new tree " << p.first << " (should have deployed " << p.second << " more cells)"
225 );
226 }
227 _splitting.insert(p.first);
228 }
229 _splitTriggered.clear();
230
231 _joining.clear();
232 _joining.insert(_joinTriggered.begin(), _joinTriggered.end());
233 _joinTriggered.clear();
234
235 switch (_spacetreeState) {
237 _spacetreeState = SpacetreeState::NewFromSplit;
238 break;
241 _spacetreeState = SpacetreeState::Running;
242 break;
244 _spacetreeState = SpacetreeState::Joining;
245 break;
247 _spacetreeState = SpacetreeState::Joined;
248 break;
251 break;
252 }
253 logDebug(
254 "traverse(TraversalObserver)", "switched tree " << _id << " into " << peano4::grid::toString(_spacetreeState)
255 );
256 }
257
258 logTraceOut("traverse(TraversalObserver)");
259}
260
262 const AutomatonState& coarseGrid,
263 AutomatonState fineGridStates[ThreePowerD],
264 tarch::la::Vector<Dimensions, int> fineGridStatesPosition,
265 int axis
266) {
267 if (axis == -1) {
268 int arrayIndex = peano4::utils::dLinearised(fineGridStatesPosition, 3);
269 fineGridStates[arrayIndex] = coarseGrid;
270 fineGridStates[arrayIndex].setLevel(coarseGrid.getLevel() + 1);
271 } else {
272 assertion(axis >= 0);
273 assertion(axis < Dimensions);
274
275 AutomatonState firstCell = coarseGrid;
276 AutomatonState secondCell = coarseGrid;
277 AutomatonState thirdCell = coarseGrid;
278
279 if (PeanoCurve::isTraversePositiveAlongAxis(coarseGrid, axis)) {
280 PeanoCurve::setExitFace(firstCell, axis);
281 } else {
282 PeanoCurve::setEntryFace(firstCell, axis);
283 }
284 firstCell.setH(axis, coarseGrid.getH(axis) / 3.0);
285 fineGridStatesPosition(axis) = 0;
286 firstCell.setX(axis, coarseGrid.getX(axis));
287 refineState(firstCell, fineGridStates, fineGridStatesPosition, axis - 1);
288
289 PeanoCurve::invertEvenFlag(secondCell, axis);
290 PeanoCurve::setEntryFace(secondCell, axis);
291 PeanoCurve::setExitFace(secondCell, axis);
292 secondCell.setH(axis, coarseGrid.getH(axis) / 3.0);
293 fineGridStatesPosition(axis) = 1;
294 secondCell.setX(axis, coarseGrid.getX(axis) + coarseGrid.getH(axis) / 3.0);
295 refineState(secondCell, fineGridStates, fineGridStatesPosition, axis - 1);
296
297 if (PeanoCurve::isTraversePositiveAlongAxis(coarseGrid, axis)) {
298 PeanoCurve::setEntryFace(thirdCell, axis);
299 } else {
300 PeanoCurve::setExitFace(thirdCell, axis);
301 }
302 thirdCell.setH(axis, coarseGrid.getH(axis) / 3.0);
303 fineGridStatesPosition(axis) = 2;
304 thirdCell.setX(axis, coarseGrid.getX(axis) + 2.0 * coarseGrid.getH(axis) / 3.0);
305 refineState(thirdCell, fineGridStates, fineGridStatesPosition, axis - 1);
306 }
307
308 if (axis == Dimensions - 1) {
309 for (int i = 0; i < ThreePowerD; i++) {
310 for (int d = 0; d < TwoTimesD; d++) {
312 fineGridStates[i].getAccessNumber(d) > -2 * Dimensions,
313 i,
314 d,
315 fineGridStates[i].toString(),
316 coarseGrid.toString(),
319 );
321 fineGridStates[i].getAccessNumber(d) < 2 * Dimensions,
322 i,
323 d,
324 fineGridStates[i].toString(),
325 coarseGrid.toString(),
328 );
329 }
330 }
331 }
332}
333
336 for (int d = 0; d < Dimensions; d++) {
337 result[d] = in[d] ? 1 : 0;
338 }
339 return result;
340}
341
343 logTraceInWith2Arguments("receiveAndMergeGridVertexAtVerticalBoundary(GridVertex)", vertex.toString(), _id);
344
345 for (auto p : _joining) {
346 if (tarch::la::contains(vertex.getAdjacentRanks(), p)) {
348 logDebug(
349 "receiveAndMergeGridVertexAtVerticalBoundary(GridVertex)",
350 "merge "
351 << vertex.toString() << " with its replica from worker as worker is joining. Incoming stack no=" << stackNo
352 );
353
354 assertion3(not _vertexStack.getForPop(_id, stackNo)->empty(), _id, stackNo, vertex.toString());
355 GridVertex copyFromFormerWorker = _vertexStack.getForPop(_id, stackNo)->pop();
356
358 vertex.getX(), copyFromFormerWorker.getX(), vertex.toString(), copyFromFormerWorker.toString(), _id
359 );
360
361 vertex.setAdjacentRanks(copyFromFormerWorker.getAdjacentRanks());
362 logDebug(
363 "receiveAndMergeGridVertexAtVerticalBoundary(GridVertex)", "updated adjacency lists: " << vertex.toString()
364 );
365 }
366 }
367
368 logTraceOut("receiveAndMergeGridVertexAtVerticalBoundary(GridVertex)");
369}
370
372 [[maybe_unused]] GridVertex& vertex,
373 [[maybe_unused]] GridVertex fineGridVertices[TwoPowerD],
374 [[maybe_unused]] const tarch::la::Vector<Dimensions, int>& position,
375 [[maybe_unused]] TraversalObserver& observer
376) {
377 logTraceInWith2Arguments("updateVertexAfterLoad(GridVertex&)", vertex.toString(), _id);
378
379 if (_spacetreeState != SpacetreeState::NewFromSplit and _spacetreeState != SpacetreeState::EmptyRun) {
380 receiveAndMergeGridVertexAtHorizontalBoundary(vertex);
381 receiveAndMergeGridVertexAtVerticalBoundary(vertex);
382
383 vertex.setHasBeenAntecessorOfRefinedVertexInPreviousTreeSweep(
384 vertex.getIsAntecessorOfRefinedVertexInCurrentTreeSweep()
385 );
386 vertex.setHasBeenParentOfSubtreeVertexInPreviousTreeSweep(vertex.getIsParentOfSubtreeVertexInCurrentTreeSweep());
387
388 vertex.setIsAntecessorOfRefinedVertexInCurrentTreeSweep(false);
389 vertex.setIsParentOfSubtreeVertexInCurrentTreeSweep(false);
390 vertex.setNumberOfAdjacentRefinedLocalCells(0);
391
392 if (vertex.getState() == GridVertex::State::RefinementTriggered) {
393 if (isVertexAdjacentToLocalSpacetree(vertex, true, true)) {
394 logDebug("updateVertexAfterLoad()", "switch vertex to refining on tree " << _id << ": " << vertex.toString());
395 vertex.setState(GridVertex::State::Refining);
396 _statistics.setStationarySweeps(0);
397 } else {
398 vertex.setState(GridVertex::State::Unrefined);
399 // Could be set by number of adjacent cells, e.g.
400 // Anyway, don't reset stationary counter as this might
401 // stop the tree from merging into its father
402 //_statistics.setStationarySweeps( 0 );
403 }
404 } else if (vertex.getState() == GridVertex::State::EraseTriggered) {
405 if (vertex.getHasBeenAntecessorOfRefinedVertexInPreviousTreeSweep()) {
406 logDebug(
407 "updateVertexAfterLoad(...)",
408 "vertex "
409 << vertex.toString() << " may not be erased on tree " << _id
410 << " as it is father of further refined vertices. Unroll flag"
411 );
412 vertex.setState(GridVertex::State::Refined);
413 _statistics.setCoarseningHasBeenVetoed(true);
414 _statistics.setStationarySweeps(0);
415 } else {
416 logDebug(
417 "updateVertexAfterLoad(...)", "erase vertex " << vertex.toString() << " outside of domain on tree " << _id
418 );
419 vertex.setState(GridVertex::State::Erasing);
420 _statistics.setStationarySweeps(0);
421 }
422 }
423
424 // has to be here. Don't want to interfere with state splitting
425 if (
426 not isVertexAdjacentToLocalSpacetree(vertex,true,true)
427 and
428 not vertex.getHasBeenAntecessorOfRefinedVertexInPreviousTreeSweep()
429 and
430 vertex.getState()==GridVertex::State::Refined
431 ) {
432 logDebug(
433 "updateVertexAfterLoad(GridVertex&)", "would like to erase " << vertex.toString() << " in spacetree " << _id
434 );
435 vertex.setState(GridVertex::State::EraseTriggered);
436 }
437 }
438
439 if (_spacetreeState == SpacetreeState::Joining and isVertexAdjacentToLocalSpacetree(vertex, true, true)) {
441 logDebug(
442 "updateVertexAfterLoad(GridVertex&)",
443 "stream vertex "
444 << vertex.toString() << " from tree " << _id << " to master " << _masterId << " through stack " << stackNo
445 );
446 _vertexStack.getForPush(_id, stackNo)->push(vertex);
447 }
448
449 logTraceOutWith1Argument("updateVertexAfterLoad(GridVertex&)", vertex.toString());
450}
451
453 const tarch::la::Vector<Dimensions, int>& coarseVertexPosition,
454 const tarch::la::Vector<Dimensions, int>& fineVertexPosition
455) {
456 bool result = true;
457 for (int d = 0; d < Dimensions; d++) {
458 assertion2(coarseVertexPosition(d) >= 0, coarseVertexPosition, fineVertexPosition);
459 assertion2(coarseVertexPosition(d) <= 1, coarseVertexPosition, fineVertexPosition);
460
461 assertion2(fineVertexPosition(d) >= 0, coarseVertexPosition, fineVertexPosition);
462 assertion2(fineVertexPosition(d) <= 3, coarseVertexPosition, fineVertexPosition);
463
464 result
465 &= ((coarseVertexPosition(d) == 1 and fineVertexPosition(d) > 0) or (coarseVertexPosition(d) == 0 and fineVertexPosition(d) < 3));
466 }
467
468 return result;
469}
470
472 GridVertex& vertex,
473 GridVertex coarseGridVertices[TwoPowerD],
474 const tarch::la::Vector<Dimensions, int>& fineVertexPositionWithinPatch
475) {
476 logTraceInWith2Arguments("updateVertexBeforeStore()", vertex.toString(), _id);
477
478 if (_spacetreeState != SpacetreeState::EmptyRun) {
479 if (vertex.getState() == GridVertex::State::New) {
481 }
482
483 if (
484 _spacetreeState==SpacetreeState::Running
485 and
487 and
489 ) {
491 logDebug(
492 "updateVertexBeforeStore(...)",
493 "have to post-refine vertex "
494 << vertex.toString() << " as it surrounded by 2^d refined cells on tree " << _id << " x "
495 << peano4::grid::toString(_spacetreeState)
496 );
497 }
498
499 /*
500 @todo Do we want to avoid hanging vertices along boundary? I think this would make sense
501
502 if (
503 vertex.getState()==GridVertex::State::Unrefined
504 and
505 vertex.
506 ) {
507 vertex.setState( GridVertex::State::RefinementTriggered );
508 logDebug( "updateVertexBeforeStore(...)", "have to post-refine vertex " << vertex.toString() );
509 }
510 */
511
512 bool restrictIsAntecessorOfRefinedVertex = vertex.getIsAntecessorOfRefinedVertexInCurrentTreeSweep();
513
515 restrictIsAntecessorOfRefinedVertex = true;
516 } else if (vertex.getState() == GridVertex::State::Refining) {
518 restrictIsAntecessorOfRefinedVertex = true;
519 } else if (vertex.getState() == GridVertex::State::EraseTriggered) {
520 restrictIsAntecessorOfRefinedVertex = true;
521 } else if (vertex.getState() == GridVertex::State::Erasing) {
523 }
524
525 sendGridVertex(vertex);
526
527 if (restrictIsAntecessorOfRefinedVertex) {
528 dfor2(k) if (restrictToCoarseGrid(k, fineVertexPositionWithinPatch)) {
529 logDebug(
530 "updateVertexBeforeStore(...)",
531 "set antecessor flag (veto coarsenign) on vertex " << coarseGridVertices[kScalar].toString(
532 ) << " due to vertex " << vertex.toString()
533 );
534 coarseGridVertices[kScalar].setIsAntecessorOfRefinedVertexInCurrentTreeSweep(true);
535 coarseGridVertices[kScalar].setIsParentOfSubtreeVertexInCurrentTreeSweep(
536 coarseGridVertices[kScalar].getIsParentOfSubtreeVertexInCurrentTreeSweep()
538 );
539 }
541 }
542
543 if (shouldEraseAdjacencyInformation(vertex, coarseGridVertices, fineVertexPositionWithinPatch)) {
545 }
546 }
547
548 logTraceOutWith2Arguments("updateVertexBeforeStore()", vertex.toString(), _id);
549}
550
552 const GridVertex& vertex,
553 GridVertex coarseGridVertices[TwoPowerD],
554 tarch::la::Vector<Dimensions, int> fineVertexPositionWithinPatch
555) const {
556 if (isVertexAdjacentToLocalSpacetree(vertex, true, true) or vertex.getState() != GridVertex::State::Unrefined) {
557 return false;
558 }
559
560 logTraceInWith2Arguments("shouldEraseAdjacencyInformation(...)", vertex.toString(), fineVertexPositionWithinPatch);
561 for (int d = 0; d < Dimensions; d++) {
562 if (fineVertexPositionWithinPatch(d) != 0 and fineVertexPositionWithinPatch(d) != 3) {
563 tarch::la::Vector<Dimensions, int> positionA = fineVertexPositionWithinPatch;
564 tarch::la::Vector<Dimensions, int> positionB = fineVertexPositionWithinPatch;
565
566 positionA(d) = 0;
567 positionB(d) = 3;
568
569 bool result = shouldEraseAdjacencyInformation(vertex, coarseGridVertices, positionA)
570 and shouldEraseAdjacencyInformation(vertex, coarseGridVertices, positionB);
571
572 logTraceOutWith1Argument("shouldEraseAdjacencyInformation(...)", result);
573 return result;
574 }
575 }
576
577 fineVertexPositionWithinPatch = fineVertexPositionWithinPatch / 3;
578
579 bool result = not tarch::la::contains(
580 coarseGridVertices[peano4::utils::dLinearised(fineVertexPositionWithinPatch, 2)].getAdjacentRanks(), _id
581 );
582 logTraceOutWith1Argument("shouldEraseAdjacencyInformation(...)", result);
583 return result;
584}
585
587 GridVertex coarseGridVertices[TwoPowerD], const tarch::la::Vector<Dimensions, int>& vertexPositionWithin3x3Patch
588) const {
590
591 dfor2(k) std::bitset<Dimensions> vertexToInherit;
592 std::bitset<Dimensions> indexToInherit;
593 for (int d = 0; d < Dimensions; d++) {
594 if (vertexPositionWithin3x3Patch(d) <= 1) {
595 vertexToInherit.set(d, false);
596 indexToInherit.set(d, k(d) > 0 or vertexPositionWithin3x3Patch(d) > 0);
597 } else {
598 vertexToInherit.set(d, true);
599 indexToInherit.set(d, not(k(d) < 1 or vertexPositionWithin3x3Patch(d) < 3));
600 }
601 }
602 logDebug(
603 "createNewPersistentVertex(...)",
604 "inherit "
605 << indexToInherit.to_ulong() << "th index from coarse vertex " << vertexToInherit << " into local index "
606 << kScalar
607 );
608 adjacentRanks(kScalar) = coarseGridVertices[vertexToInherit.to_ulong()].getAdjacentRanks(indexToInherit.to_ulong());
610
611 return adjacentRanks;
612}
613
615 const AutomatonState& fineGridStatesState,
616 GridVertex coarseGridVertices[TwoPowerD],
617 GridVertex fineGridVertices[TwoPowerD],
618 const tarch::la::Vector<Dimensions, int>& cellPositionWithin3x3Patch,
619 TraversalObserver& observer
620) {
621 logTraceInWith3Arguments("loadVertices(...)", fineGridStatesState.toString(), cellPositionWithin3x3Patch, _id);
622
623 const std::bitset<Dimensions> coordinates = PeanoCurve::getFirstVertexIndex(fineGridStatesState);
624 for (int i = 0; i < TwoPowerD; i++) {
625 const std::bitset<Dimensions> vertexIndex(coordinates ^ std::bitset<Dimensions>(i));
627 vertexPositionWithinPatch = cellPositionWithin3x3Patch + convertToIntegerVector(vertexIndex);
628
630 x = fineGridStatesState.getX()
632 tarch::la::convertScalar<double>(convertToIntegerVector(vertexIndex)), fineGridStatesState.getH()
633 );
634
635 VertexType type = _gridTraversalEventGenerator.getVertexType(coarseGridVertices, vertexPositionWithinPatch);
636 int stackNumber = PeanoCurve::getVertexReadStackNumber(fineGridStatesState, vertexIndex);
637
638 // reset to persistent, as new vertex already has been generated
639 if (not PeanoCurve::isInOutStack(stackNumber) and type == VertexType::New) {
641 logDebug(
642 "loadVertices(...)",
643 "reset stack flag for local vertex " << vertexPositionWithinPatch << " from new/hanging to persistent"
644 );
645 }
646
647 switch (type) {
648 case VertexType::New:
650 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = createVertex(
652 x,
653 fineGridStatesState.getLevel(),
654 getAdjacentRanksForNewVertex(coarseGridVertices, vertexPositionWithinPatch),
655 true
656 );
657 break;
659 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = createVertex(
661 x,
662 fineGridStatesState.getLevel(),
663 getAdjacentRanksForNewVertex(coarseGridVertices, vertexPositionWithinPatch),
664 true
665 );
666 break;
668 logDebug("readVertices(...)", "read vertex from stack " << stackNumber);
669
670 if (PeanoCurve::isInOutStack(stackNumber)) {
671 assertion3(not _vertexStack.getForPop(_id, stackNumber)->empty(), _id, stackNumber, vertexIndex);
672 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = _vertexStack.getForPop(_id, stackNumber)->pop();
673
674 updateVertexAfterLoad(
675 fineGridVertices[peano4::utils::dLinearised(vertexIndex)],
676 coarseGridVertices,
677 vertexPositionWithinPatch,
678 observer
679 );
680 } else {
681 assertion3(not _vertexStack.getForPop(_id, stackNumber)->empty(), _id, stackNumber, vertexIndex);
682 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = _vertexStack.getForPop(_id, stackNumber)->pop();
683 }
684 } break;
685 case VertexType::Delete: {
686 logDebug("readVertices(...)", "read vertex from stack " << stackNumber);
687
688 if (PeanoCurve::isInOutStack(stackNumber)) {
689 assertion2(not _vertexStack.getForPop(_id, stackNumber)->empty(), stackNumber, _id);
690 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = _vertexStack.getForPop(_id, stackNumber)->pop();
691
692 updateVertexAfterLoad(
693 fineGridVertices[peano4::utils::dLinearised(vertexIndex)],
694 coarseGridVertices,
695 vertexPositionWithinPatch,
696 observer
697 );
698 fineGridVertices[peano4::utils::dLinearised(vertexIndex)].setState(GridVertex::State::Delete);
699 } else {
700 assertion2(not _vertexStack.getForPop(_id, stackNumber)->empty(), stackNumber, _id);
701 fineGridVertices[peano4::utils::dLinearised(vertexIndex)] = _vertexStack.getForPop(_id, stackNumber)->pop();
702 }
703 } break;
704 }
705 logDebug(
706 "loadVertices(...)",
707 "handled "
708 << peano4::grid::toString(type) << " vertex " << vertexIndex << " at " << vertexPositionWithinPatch << ": "
709 << fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString()
710 );
711
713 fineGridVertices[peano4::utils::dLinearised(vertexIndex)].getX(),
714 x,
715 fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString(),
716 fineGridStatesState.toString(),
717 vertexIndex,
718 toString(),
719 _id
720 );
722 fineGridVertices[peano4::utils::dLinearised(vertexIndex)].getLevel(),
723 fineGridStatesState.getLevel(),
724 fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString(),
725 fineGridStatesState.toString(),
726 vertexIndex,
727 toString(),
728 _id
729 );
730 }
731
732 logTraceOutWith1Argument("loadVertices(...)", fineGridStatesState.toString());
733}
734
736 [[maybe_unused]] const AutomatonState& fineGridStatesState,
737 [[maybe_unused]] GridVertex coarseGridVertices[TwoPowerD],
738 [[maybe_unused]] GridVertex fineGridVertices[TwoPowerD],
739 [[maybe_unused]] const tarch::la::Vector<Dimensions, int>& cellPositionWithin3x3Patch,
740 [[maybe_unused]] TraversalObserver& observer
741) {
742 logTraceInWith1Argument("storeVertices(...)", fineGridStatesState.toString());
743
744 const std::bitset<Dimensions> coordinates = PeanoCurve::getFirstVertexIndex(fineGridStatesState);
745 for (int i = 0; i < TwoPowerD; i++) {
746 const std::bitset<Dimensions> vertexIndex(coordinates ^ std::bitset<Dimensions>(i));
748 vertexPositionWithinPatch = cellPositionWithin3x3Patch + convertToIntegerVector(vertexIndex);
749
750 // const tarch::la::Vector<Dimensions,double> x = fineGridStatesState.getX()
751 // + tarch::la::multiplyComponents(
752 // tarch::la::convertScalar<double>( convertToIntegerVector(vertexIndex) ),
753 // fineGridStatesState.getH()
754 // );
755
756 const int stackNumber = PeanoCurve::getVertexWriteStackNumber(fineGridStatesState, vertexIndex);
757 VertexType type = _gridTraversalEventGenerator.getVertexType(coarseGridVertices, vertexPositionWithinPatch);
758
759 if (not PeanoCurve::isInOutStack(stackNumber) and type == VertexType::Delete) {
761 logDebug(
762 "storeVertices(...)",
763 "reset stack flag for local vertex " << vertexPositionWithinPatch << " from new/hanging to persistent"
764 );
765 }
766
767 switch (type) {
768 case VertexType::New:
770 logDebug(
771 "storeVertices(...)",
772 "write vertex "
773 << fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString() << " to stack " << stackNumber
774 );
775 if (PeanoCurve::isInOutStack(stackNumber)) {
776 updateVertexBeforeStore(
777 fineGridVertices[peano4::utils::dLinearised(vertexIndex)], coarseGridVertices, vertexPositionWithinPatch
778 );
779 }
780 _vertexStack.getForPush(_id, stackNumber)->push(fineGridVertices[peano4::utils::dLinearised(vertexIndex)]);
781 } break;
783 logDebug(
784 "storeVertices(...)", "discard vertex " << fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString()
785 );
786 break;
788 logDebug(
789 "storeVertices(...)", "delete vertex " << fineGridVertices[peano4::utils::dLinearised(vertexIndex)].toString()
790 );
792 break;
793 }
794 }
795
796 logTraceOutWith1Argument("storeVertices(...)", fineGridStatesState.toString());
797}
798
800 const {
801 const bool receiverCriteria = (_joining.count(rank) == 0) and (_splitting.count(rank) == 0);
802 const bool senderCriteria = (_joining.count(rank) == 0) and (_splitTriggered.count(rank) == 0)
803 and _spacetreeState != SpacetreeState::Joining;
804
805 const bool mandatoryCriteria = rank != _id and rank != InvalidRank and rank != RankOfPeriodicBoundaryCondition;
806
807 return calledByReceivingProcess ? (mandatoryCriteria and receiverCriteria) : (mandatoryCriteria and senderCriteria);
808}
809
811 GridVertex fineGridVertices[TwoPowerD], int faceNumber, bool calledByReceivingProcess
812) const {
813 logTraceInWith2Arguments("isFaceAlongPeriodicBoundaryCondition(...)", faceNumber, calledByReceivingProcess);
814
815 tarch::la::Vector<TwoPowerD, int> adjacentRanksOfFace = _gridTraversalEventGenerator.getAdjacentRanksOfFace(
816 fineGridVertices, faceNumber, calledByReceivingProcess
817 );
818
819 bool isAdjacentToLocalRank = false;
820 bool holdsPeriodicBoundaryConditionFlag = false; // semantics is either has been local or will be local
821 for (int i = 0; i < TwoPowerD; i++) {
822 isAdjacentToLocalRank |= adjacentRanksOfFace(i) == _id;
823 holdsPeriodicBoundaryConditionFlag |= adjacentRanksOfFace(i) == RankOfPeriodicBoundaryCondition;
824 }
825
826 holdsPeriodicBoundaryConditionFlag &= isAdjacentToLocalRank;
827
829 "isFaceAlongPeriodicBoundaryCondition(...)", holdsPeriodicBoundaryConditionFlag, isAdjacentToLocalRank
830 );
831 return holdsPeriodicBoundaryConditionFlag;
832}
833
835 GridVertex fineGridVertices[TwoPowerD], int faceNumber, bool calledByReceivingProcess
836) const {
837 logTraceInWith3Arguments("getNeighbourTrees(...)", faceNumber, calledByReceivingProcess, _id);
838
839 tarch::la::Vector<TwoPowerD, int> adjacentRanksOfFace = _gridTraversalEventGenerator.getAdjacentRanksOfFace(
840 fineGridVertices, faceNumber, calledByReceivingProcess
841 );
842
843 logDebug("getNeighbourTrees(...)", "face adjacency list=" << adjacentRanksOfFace);
844
845 // Study whether face is local and who neighbours it. See routine
846 // documentation of our particular flavour of localness in this
847 // case.
848 // --------------------------------------------------------------
849 bool isAdjacentToLocalRank = false; // semantics is either has been local or will be local
850 int neighbour = TraversalObserver::NoData;
851 for (int i = 0; i < TwoPowerD; i++) {
852 const bool mandatoryCriteria = adjacentRanksOfFace(i) != _id and adjacentRanksOfFace(i) != InvalidRank
853 and adjacentRanksOfFace(i) != RankOfPeriodicBoundaryCondition
854 and _spacetreeState != SpacetreeState::EmptyRun;
855
856 if (calledByReceivingProcess) {
857 isAdjacentToLocalRank |= adjacentRanksOfFace(i) == _id or _splitTriggered.count(adjacentRanksOfFace(i)) == 1
858 or _splitting.count(adjacentRanksOfFace(i)) == 1;
859
860 const bool receiverCriteria = _splitTriggered.count(adjacentRanksOfFace(i)) == 0
861 and _splitting.count(adjacentRanksOfFace(i)) == 0
862 and _spacetreeState != SpacetreeState::NewFromSplit;
863
864 if (mandatoryCriteria and receiverCriteria) {
865 neighbour = adjacentRanksOfFace(i);
866 }
867 } else {
868 isAdjacentToLocalRank |= adjacentRanksOfFace(i) == _id or _splitTriggered.count(adjacentRanksOfFace(i)) == 1;
869
870 const bool senderCriteria = _splitTriggered.count(adjacentRanksOfFace(i)) == 0;
871
872 if (mandatoryCriteria and senderCriteria) {
873 neighbour = adjacentRanksOfFace(i);
874 }
875 }
876 }
877
878 if (not isAdjacentToLocalRank) {
879 neighbour = TraversalObserver::NoData;
880 }
881
882 logTraceOutWith1Argument("getNeighbourTrees(...)", neighbour);
883 return neighbour;
884}
885
886std::set<int> peano4::grid::Spacetree::getNeighbourTrees(const GridVertex& vertex, bool calledByReceivingProcess)
887 const {
888 std::set<int> neighbourIds;
889
890 const bool isLocalVertex = calledByReceivingProcess ? isVertexAdjacentToLocalSpacetree(vertex, true, false)
891 : isVertexAdjacentToLocalSpacetree(vertex, false, true);
892
893 if (isLocalVertex) {
894 auto adjacentRanks = calledByReceivingProcess ? vertex.getBackupOfAdjacentRanks() : vertex.getAdjacentRanks();
895
896 for (int i = 0; i < TwoPowerD; i++) {
897 if (doesRankIndexIdentifyHorizontalDataExchange(adjacentRanks(i), calledByReceivingProcess)) {
898 neighbourIds.insert(adjacentRanks(i));
899 }
900 }
901 }
902
903 return neighbourIds;
904}
905
907 GridVertex& vertex, const GridVertex& inVertex, int neighbour
908) {
909 //
910 // Merge adjacency lists. The neighbour owns some entries
911 //
912 for (int i = 0; i < TwoPowerD; i++) {
913 if (vertex.getAdjacentRanks(i) == neighbour and neighbour != InvalidRank) {
914 if (inVertex.getAdjacentRanks(i) != vertex.getAdjacentRanks(i)) {
915 logDebug(
916 "mergeGridVertexAdjacencyListsAtHorizontalDomainBoundary(...)",
917 "update "
918 << i << "th entry of adjacency data of vertex " << vertex.toString() << " with neighbouring vertex "
919 << inVertex.toString() << " on tree " << _id
920 );
921 }
922 vertex.setAdjacentRanks(i, inVertex.getAdjacentRanks(i));
923 }
924 }
925}
926
928 [[maybe_unused]] GridVertex& vertex, [[maybe_unused]] const GridVertex& inVertex, [[maybe_unused]] int neighbour
929) {
931 vertex.getState() != GridVertex::State::HangingVertex, inVertex.toString(), vertex.toString(), _id, neighbour
932 );
934 inVertex.getState() != GridVertex::State::HangingVertex, inVertex.toString(), vertex.toString(), _id, neighbour
935 );
937 tarch::la::equals(vertex.getX(), inVertex.getX())
938 or
939 (
940 tarch::la::contains(vertex.getAdjacentRanks(),RankOfPeriodicBoundaryCondition)
941 and
942 (_periodicBC.count()>1 or tarch::la::countEqualEntries(vertex.getX(), inVertex.getX())==Dimensions-static_cast<int>(_periodicBC.count()))
943 ),
944 inVertex.toString(), vertex.toString(), _id, neighbour,
945 tarch::la::countEqualEntries(vertex.getX(), inVertex.getX()), _periodicBC
946 );
947 assertionEquals4(vertex.getLevel(), inVertex.getLevel(), inVertex.toString(), vertex.toString(), _id, neighbour);
949 not(vertex.getState() == GridVertex::State::Refined and inVertex.getState() == GridVertex::State::Erasing),
950 inVertex.toString(),
951 vertex.toString(),
952 _id,
953 neighbour
954 );
956 not(vertex.getState() == GridVertex::State::Refined and inVertex.getState() == GridVertex::State::Unrefined),
957 inVertex.toString(),
958 vertex.toString(),
959 _id,
960 neighbour
961 );
962
963 //
964 // Merge helper flags
965 //
966 vertex.setIsAntecessorOfRefinedVertexInCurrentTreeSweep(
967 vertex.getIsAntecessorOfRefinedVertexInCurrentTreeSweep()
968 or inVertex.getIsAntecessorOfRefinedVertexInCurrentTreeSweep()
969 );
970
971 //
972 // Update refinement flags
973 //
974 assertion3(vertex.getState() != GridVertex::State::Erasing, vertex.toString(), inVertex.toString(), _id);
975 assertion3(vertex.getState() != GridVertex::State::Refining, vertex.toString(), inVertex.toString(), _id);
976
977 const bool OnlyNeighbourHasTriggeredRefinement
978 = inVertex.getState() == GridVertex::State::RefinementTriggered
979 && (vertex.getState() == GridVertex::State::Unrefined or vertex.getState() == GridVertex::State::New or vertex.getState() == GridVertex::State::Delete);
980 const bool OnlyLocalHasTriggeredRefinement =
981 vertex.getState()==GridVertex::State::RefinementTriggered &&
982 (inVertex.getState()==GridVertex::State::Unrefined or inVertex.getState()==GridVertex::State::New or inVertex.getState()==GridVertex::State::Delete);
983 const bool OnlyNeighbourHasTriggeredErase = inVertex.getState() == GridVertex::State::EraseTriggered
984 && vertex.getState() == GridVertex::State::Refined;
985 const bool OnlyLocalHasTriggeredErase = vertex.getState() == GridVertex::State::EraseTriggered
986 && inVertex.getState() == GridVertex::State::Refined;
987
988 if (OnlyNeighbourHasTriggeredRefinement || OnlyLocalHasTriggeredRefinement) {
990 logDebug(
991 "mergeGridVertexRefinementStateAtHorizontalDomainBoundary( GridVertex )",
992 "set state to " << vertex.toString() << " on tree " << _id << " due to merge with neighbour"
993 );
994 } else if (OnlyNeighbourHasTriggeredErase || OnlyLocalHasTriggeredErase) {
995 vertex.setState(GridVertex::State::EraseTriggered);
996 logDebug(
997 "mergeGridVertexRefinementStateAtHorizontalDomainBoundary( GridVertex )",
998 "set state to " << vertex.toString() << " on tree " << _id << " due to merge with neighbour"
999 );
1000 } else {
1001 assertion4(vertex.getState() == inVertex.getState(), inVertex.toString(), vertex.toString(), _id, neighbour);
1002 }
1003}
1004
1006 assertion(_spacetreeState != SpacetreeState::NewFromSplit and _spacetreeState != SpacetreeState::EmptyRun);
1007
1008 logTraceInWith1Argument("receiveAndMergeGridVertexAtHorizontalBoundary(...)", vertex.toString());
1009
1010 //
1011 // Backup adjacency lists
1012 //
1014
1015 std::set<int> neighbourIds = getNeighbourTrees(vertex, true);
1016 for (auto neighbour : neighbourIds) {
1017 assertion1(neighbour >= 0, neighbour);
1019
1020 assertion4(_vertexStack.holdsStack(_id, inStack), _id, inStack, neighbour, vertex.toString());
1021 assertion4(not _vertexStack.getForPop(_id, inStack)->empty(), _id, inStack, neighbour, vertex.toString());
1022 GridVertex inVertex = _vertexStack.getForPop(_id, inStack)->pop();
1023
1024 mergeGridVertexRefinementStateAtHorizontalDomainBoundary(vertex, inVertex, neighbour);
1025 mergeGridVertexAdjacencyListsAtHorizontalDomainBoundary(vertex, inVertex, neighbour);
1026 }
1027
1028 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>
1029 periodicBCOutputStacks = _id == 0 ? peano4::parallel::Node::getInstance()
1031 : std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>();
1032 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier> periodicBCInputStacks;
1033 for (auto& p : periodicBCOutputStacks) {
1036 ));
1037 }
1038
1039 for (auto stackNo : periodicBCInputStacks) {
1040 assertion4(_id == 0, _id, stackNo.first, stackNo.second, vertex.toString());
1041 assertion3(not _vertexStack.getForPop(_id, stackNo.first)->empty(), stackNo.first, stackNo.second, _id);
1042 GridVertex inVertex = _vertexStack.getForPop(_id, stackNo.first)->pop();
1043 logDebug(
1044 "receiveAndMergeGridVertexAtHorizontalBoundary(...)",
1045 "read periodic BC data from stack " << stackNo.first << ": " << inVertex.toString()
1046 );
1047 logDebug(
1048 "receiveAndMergeGridVertexAtHorizontalBoundary(...)", "normals of involved symmetry axes: " << stackNo.second
1049 );
1050 mergeGridVertexRefinementStateAtHorizontalDomainBoundary(vertex, inVertex, _id);
1051
1053 vertex.getAdjacentRanks(kScalar) == RankOfPeriodicBoundaryCondition or vertex.getAdjacentRanks(kScalar) == _id
1054 or vertex.getAdjacentRanks(kScalar) == InvalidRank,
1055 vertex.toString(),
1056 inVertex.toString(),
1057 _id
1058 );
1059 enddforx
1060 }
1061
1062 logTraceOut("receiveAndMergeGridVertexAtHorizontalBoundary(...)");
1063}
1064
1066 logTraceInWith2Arguments("sendGridVertex(GridVertex)", vertex.toString(), _id);
1067
1068 assertion2(_spacetreeState != SpacetreeState::EmptyRun, _id, peano4::grid::toString(_spacetreeState));
1069
1070 std::set<int> outRanks = getNeighbourTrees(vertex, false);
1071
1072 for (auto p : outRanks) {
1073 //
1074 // Boundary exchange
1075 //
1077
1078 GridVertex vertexCopy = vertex;
1079 for (int i = 0; i < TwoPowerD; i++) {
1080 int targetRank = vertexCopy.getAdjacentRanks(i);
1081 if (_spacetreeState == SpacetreeState::JoinTriggered and targetRank == _id and p != _masterId) {
1082 vertexCopy.setAdjacentRanks(i, _masterId);
1083 }
1084 }
1085
1086 _vertexStack.getForPush(_id, stackNo)->push(vertexCopy);
1087 }
1088
1089 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>
1090 periodicBCStacks = _id == 0 ? peano4::parallel::Node::getInstance()
1092 : std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>();
1093
1094 for (auto stackNo : periodicBCStacks) {
1095 _vertexStack.getForPush(_id, stackNo.first)->push(vertex);
1096 logDebug(
1097 "sendGridVertex(GridVertex)",
1098 "vertex "
1099 << vertex.toString() << " on tree " << _id << " goes to stack " << stackNo.first << " to realise periodic BC"
1100 );
1101 }
1102
1103 logTraceOutWith1Argument("sendGridVertex(GridVertex)", isVertexAdjacentToLocalSpacetree(vertex, true, true));
1104}
1105
1107 dfor2(k) vertices[kScalar].setNumberOfAdjacentRefinedLocalCells(
1108 vertices[kScalar].getNumberOfAdjacentRefinedLocalCells() + 1
1109 );
1110 logDebug(
1111 "incrementNumberOfAdjacentRefinedLocalCells(...)", "incremented counter of " << vertices[kScalar].toString()
1112 );
1113 enddforx
1114}
1115
1117 dfor2(k) fineGridVertices[kScalar].setAdjacentRanks(TwoPowerD - kScalar - 1, newId);
1118 enddforx
1119}
1120
1122 const AutomatonState& state, GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1123) {
1124 if (not _gridControlEvents.empty()) {
1125 logTraceInWith2Arguments("evaluateGridControlEvents(...)", state.toString(), _gridControlEvents.size());
1126
1127 assertion1(
1128 _spacetreeState != SpacetreeState::EmptyRun and _spacetreeState != SpacetreeState::NewFromSplit
1129 and _spacetreeState != SpacetreeState::Joining,
1130 toString()
1131 );
1132
1133 bool mayChangeGrid = true;
1134 for (int i = 0; i < TwoPowerD; i++) {
1135 // excluding refinement triggered and refining ensures that we have no immediate
1136 // refine anymore. This is important for the adjacency lists. We have to allow
1137 // erase triggered, as the grid control events are evaluated top-down, i.e. data
1138 // might be set.
1139 mayChangeGrid &= (
1140 coarseGridVertices[i].getState()==GridVertex::State::HangingVertex
1141 or
1142 coarseGridVertices[i].getState()==GridVertex::State::Unrefined
1143 or
1144 coarseGridVertices[i].getState()==GridVertex::State::Refined
1145 or
1146 coarseGridVertices[i].getState()==GridVertex::State::EraseTriggered
1147 );
1148 }
1149
1150 bool refine = false;
1151 bool erase = false;
1152 if (mayChangeGrid) {
1153 for (auto p : _gridControlEvents) {
1154 if (
1155 overlaps(state,p)
1156 and
1157 p.getRefinementControl()==GridControlEvent::RefinementControl::Refine
1158 and
1160 ) {
1161 refine = true;
1162 }
1163
1164 if (
1165 isContained(state,p,3.0)
1166 and
1167 p.getRefinementControl()==GridControlEvent::RefinementControl::Erase
1168 and
1169 tarch::la::allSmaller( state.getH(), p.getH() )
1170 ) {
1171 erase = true;
1172 }
1173 }
1174 }
1175
1176 logDebug(
1177 "evaluateGridControlEvents(...)",
1178 _gridControlEvents.size(
1179 ) << " event(s) in state "
1180 << state.toString() << " trigger change=" << mayChangeGrid << ", refine=" << refine << ", erase=" << erase
1181 );
1182
1183 if (refine) {
1184 bool haveTriggeredRefinementForAtLeastOneVertex = false;
1185 dfor2(i
1186 ) if (isVertexAdjacentToLocalSpacetree(fineGridVertices[iScalar], true, true) and fineGridVertices[iScalar].getState() == GridVertex::State::Unrefined) {
1187 fineGridVertices[iScalar].setState(GridVertex::State::RefinementTriggered);
1188 haveTriggeredRefinementForAtLeastOneVertex = true;
1189 }
1190 enddforx
1191
1192 if (not haveTriggeredRefinementForAtLeastOneVertex) {
1193 logDebug("evaluate...", "wanted to refine cell " << state.toString() << " but no vertex is refinable");
1194 }
1195 } else if (erase) {
1196 for (int i = 0; i < TwoPowerD; i++) {
1197 if (isVertexAdjacentToLocalSpacetree(fineGridVertices[i], true, true) and fineGridVertices[i].getState() == GridVertex::State::Refined) {
1198 fineGridVertices[i].setState(GridVertex::State::EraseTriggered);
1199 }
1200 }
1201 }
1202
1203 logTraceOutWith3Arguments("evaluateGridControlEvents(...)", state.toString(), refine, erase);
1204 }
1205}
1206
1208 const AutomatonState& state, GridVertex vertices[TwoPowerD], TraversalObserver& observer
1209) {
1211 logTraceInWith2Arguments("descend(...)", state.toString(), _id);
1212
1213#if PeanoDebug >= 2
1214 dfor2(k) logDebug("descend(...)", "-" << vertices[kScalar].toString());
1215 enddforx
1216#endif
1217
1218 peano4::utils::LoopDirection loopDirection
1220
1221 //
1222 // Construct the 3^d new children states
1223 //
1224 AutomatonState fineGridStates[ThreePowerD];
1225 refineState(state, fineGridStates);
1226
1227#if PeanoDebug >= 2
1228 dfor3(k) logDebug("descend(...)", "-" << fineGridStates[kScalar].toString());
1229 enddforx
1230#endif
1231
1232 //
1233 // Loop over children
1234 //
1235 zfor3(k, loopDirection)
1236 //
1237 // Load cell's vertices
1238 //
1239 GridVertex fineGridVertices[TwoPowerD];
1240 loadVertices(fineGridStates[peano4::utils::dLinearised(k, 3)], vertices, fineGridVertices, k, observer);
1241
1242 mergeCellFromWorkerWithMasterThroughoutJoin(vertices, fineGridVertices);
1243
1244 //
1245 // Enter cell
1246 //
1247
1248 // flag areas which fork off further
1249 if (isSpacetreeNodeLocal(fineGridVertices, false, false) and not isSpacetreeNodeLocal(vertices, false, false)) {
1250 markVerticesAroundForkedCell(vertices, fineGridVertices);
1251 } else if (not isSpacetreeNodeLocal(fineGridVertices, false, false) and isSpacetreeNodeLocal(vertices, false, false)) {
1252 markVerticesAroundForkedCell(vertices, fineGridVertices);
1253 }
1254
1255 // refinement control
1256 if (isSpacetreeNodeLocal(fineGridVertices, false, false)) {
1257 evaluateGridControlEvents(fineGridStates[peano4::utils::dLinearised(k, 3)], vertices, fineGridVertices);
1258 }
1259
1260 splitCellTopDown(vertices, fineGridVertices);
1261
1262 GridTraversalEvent enterCellTraversalEvent = _gridTraversalEventGenerator.createEnterCellTraversalEvent(
1263 vertices,
1264 fineGridVertices,
1265 fineGridStates[peano4::utils::dLinearised(k, 3)],
1266 _splitTriggered,
1267 _splitting,
1268 _joinTriggered,
1269 _joining,
1270 _hasSplit,
1271 k,
1272 _spacetreeState == SpacetreeState::Running
1273 );
1274
1275 observer.loadCell(
1276 _gridTraversalEventGenerator.createPrunedEnterCellTraversalEvent(_spacetreeState, enterCellTraversalEvent)
1277 );
1278
1279 if (_spacetreeState != SpacetreeState::EmptyRun and _spacetreeState != SpacetreeState::NewFromSplit and _spacetreeState != SpacetreeState::Joined) {
1280 receiveAndMergeUserData(
1281 fineGridStates[peano4::utils::dLinearised(k, 3)], observer, enterCellTraversalEvent, fineGridVertices
1282 );
1283 }
1284
1285 observer.enterCell(
1286 _gridTraversalEventGenerator.createPrunedEnterCellTraversalEvent(_spacetreeState, enterCellTraversalEvent)
1287 );
1288
1289 _statistics.setMinH(tarch::la::min(_statistics.getMinH(), 1.0 / 3.0 * state.getH()));
1290
1291 //
1292 // DFS
1293 //
1294 if (isSpacetreeNodeRefined(fineGridVertices)) {
1295 if (isSpacetreeNodeLocal(fineGridVertices, false, false)) {
1296 _statistics.setNumberOfLocalRefinedCells(_statistics.getNumberOfLocalRefinedCells() + 1);
1297 incrementNumberOfAdjacentRefinedLocalCells(fineGridVertices);
1298 } else {
1299 _statistics.setNumberOfRemoteRefinedCells(_statistics.getNumberOfRemoteRefinedCells() + 1);
1300 }
1301 descend(fineGridStates[peano4::utils::dLinearised(k, 3)], fineGridVertices, observer);
1302 } else {
1303 if (isSpacetreeNodeLocal(fineGridVertices, true, true)) {
1304 _statistics.setNumberOfLocalUnrefinedCells(_statistics.getNumberOfLocalUnrefinedCells() + 1);
1305 } else {
1306 _statistics.setNumberOfRemoteUnrefinedCells(_statistics.getNumberOfRemoteUnrefinedCells() + 1);
1307 }
1308 }
1309
1310 //
1311 // Leave cell
1312 //
1313 GridTraversalEvent leaveCellTraversalEvent = _gridTraversalEventGenerator.createLeaveCellTraversalEvent(
1314 vertices,
1315 fineGridVertices,
1316 fineGridStates[peano4::utils::dLinearised(k, 3)],
1317 _splitTriggered,
1318 _splitting,
1319 _joinTriggered,
1320 _joining,
1321 _hasSplit,
1322 k,
1323 _spacetreeState == SpacetreeState::Running
1324 );
1325
1326 observer.leaveCell(
1327 _gridTraversalEventGenerator.createPrunedLeaveCellTraversalEvent(_spacetreeState, leaveCellTraversalEvent)
1328 );
1329
1330 if (_spacetreeState != SpacetreeState::EmptyRun and _spacetreeState != SpacetreeState::Joined) {
1331 sendUserData(fineGridStates[peano4::utils::dLinearised(k, 3)], observer, leaveCellTraversalEvent, fineGridVertices);
1332 }
1333
1334 observer.storeCell(
1335 _gridTraversalEventGenerator.createPrunedLeaveCellTraversalEvent(_spacetreeState, leaveCellTraversalEvent)
1336 );
1337
1338 splitOrJoinCellBottomUp(vertices, fineGridVertices);
1339
1340 //
1341 // Store vertices
1342 //
1343 storeVertices(fineGridStates[peano4::utils::dLinearised(k, 3)], vertices, fineGridVertices, k, observer);
1344 endzfor
1345
1346 logTraceOut("descend(...)");
1347}
1348
1350 const AutomatonState& state,
1351 TraversalObserver& observer,
1352 const GridTraversalEvent& enterCellTraversalEvent,
1353 GridVertex fineGridVertices[TwoPowerD]
1354) {
1355 logTraceInWith3Arguments("receiveAndMergeUserData(...)", state.toString(), enterCellTraversalEvent.toString(), _id);
1356
1357 assertion3(
1358 _spacetreeState != SpacetreeState::EmptyRun and _spacetreeState != SpacetreeState::NewFromSplit
1359 and _spacetreeState != SpacetreeState::Joined,
1360 state.toString(),
1361 peano4::grid::toString(_spacetreeState),
1362 _id
1363 );
1364
1365 for (int i = 0; i < TwoPowerD; i++) {
1366 int inVertexStack = enterCellTraversalEvent.getVertexDataFrom(i);
1367 int inVertexPositionWithinCell = enterCellTraversalEvent.getVertexDataTo(i);
1368
1369 if (peano4::grid::PeanoCurve::isInOutStack(inVertexStack)) {
1372
1373 if (enterCellTraversalEvent.getIsVertexLocal(inVertexPositionWithinCell)) {
1374 std::set<int> neighbours = getNeighbourTrees(fineGridVertices[inVertexPositionWithinCell], true);
1375 for (auto p : neighbours) {
1376 logDebug(
1377 "receiveAndMergeUserData(...)",
1378 "receive neighbour data from neighbour "
1379 << p << " for vertex " << fineGridVertices[inVertexPositionWithinCell].toString()
1380 );
1382 observer.receiveAndMergeVertex(
1383 inVertexPositionWithinCell,
1384 fromStack, // Rank
1386 enterCellTraversalEvent
1387 );
1388 }
1389
1390 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>
1391 periodicBCOutputStacks = _id == 0
1393 fineGridVertices[inVertexPositionWithinCell].getAdjacentRanks()
1394 )
1395 : std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>();
1396
1397 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier> periodicBCInputStacks;
1398 for (auto& p : periodicBCOutputStacks) {
1399 periodicBCInputStacks.insert(
1401 );
1402 }
1403
1404 for (auto p : periodicBCInputStacks) {
1405 observer.receiveAndMergeVertex(
1406 inVertexPositionWithinCell,
1407 p.first, // Rank
1409 enterCellTraversalEvent
1410 );
1411 }
1412 }
1413 }
1414 }
1415
1416 for (int i = 0; i < 2 * Dimensions; i++) {
1417 int inFaceStack = enterCellTraversalEvent.getFaceDataFrom(i);
1418 int inFacePositionWithinCell = enterCellTraversalEvent.getFaceDataTo(i);
1419 if (peano4::grid::PeanoCurve::isInOutStack(inFaceStack)) {
1422
1423 if (enterCellTraversalEvent.getIsFaceLocal(inFacePositionWithinCell)) {
1424 int neighbour = getNeighbourTrees(fineGridVertices, inFacePositionWithinCell, true);
1425 if (neighbour >= 0) {
1427 observer.receiveAndMergeFace(
1428 inFacePositionWithinCell,
1429 fromStack,
1431 enterCellTraversalEvent
1432 );
1433 }
1434
1435 if (isFaceAlongPeriodicBoundaryCondition(fineGridVertices, inFacePositionWithinCell, true)) {
1438 );
1439
1440 peano4::datamanagement::FaceMarker marker(enterCellTraversalEvent, inFacePositionWithinCell /*oppositeFace*/);
1441 logDebug(
1442 "receiveAndMergeUserData(...)",
1443 "will merge face from periodic BC stack #"
1444 << fromStack << " with local face. Cell marker=" << marker.toString()
1445 << ". in-face=" << inFacePositionWithinCell
1446 );
1447
1448 observer.receiveAndMergeFace(
1449 inFacePositionWithinCell,
1450 fromStack,
1452 enterCellTraversalEvent
1453 );
1454 }
1455 }
1456 }
1457 }
1458
1459 logTraceOut("receiveAndMergeUserData(...)");
1460}
1461
1463 [[maybe_unused]] const AutomatonState& state,
1464 [[maybe_unused]] TraversalObserver& observer,
1465 [[maybe_unused]] const GridTraversalEvent& leaveCellTraversalEvent,
1466 [[maybe_unused]] GridVertex fineGridVertices[TwoPowerD]
1467) {
1468 logTraceInWith3Arguments("sendUserData(...)", state.toString(), leaveCellTraversalEvent.toString(), _id);
1469 assertion4(
1470 _spacetreeState != SpacetreeState::EmptyRun and _spacetreeState != SpacetreeState::Joined,
1471 peano4::grid::toString(_spacetreeState),
1472 state.toString(),
1473 leaveCellTraversalEvent.toString(),
1474 _id
1475 );
1476
1477 for (int i = 0; i < TwoPowerD; i++) {
1478 int outVertexStack = leaveCellTraversalEvent.getVertexDataTo(i);
1479 int outVertexPositionWithinCell = leaveCellTraversalEvent.getVertexDataFrom(i);
1480
1481 if (peano4::grid::PeanoCurve::isInOutStack(outVertexStack)) {
1484
1485 if (leaveCellTraversalEvent.getIsVertexLocal(outVertexPositionWithinCell)) {
1486 std::set<int> neighbours = getNeighbourTrees(fineGridVertices[outVertexPositionWithinCell], false);
1487
1488 for (auto p : neighbours) {
1489 logDebug(
1490 "sendUserData(...)",
1491 "send local vertex data of "
1492 << fineGridVertices[outVertexPositionWithinCell].toString() << " from stack " << outVertexStack
1493 << " on tree " << _id << " to neighbour " << p << ". Position within cell=" << outVertexPositionWithinCell
1494 );
1496 observer.sendVertex(
1497 outVertexPositionWithinCell,
1498 toStack,
1500 leaveCellTraversalEvent
1501 );
1502 }
1503
1504 std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>
1506 fineGridVertices[outVertexPositionWithinCell].getAdjacentRanks()
1507 )
1508 : std::set<peano4::parallel::Node::PeriodicBoundaryStackIdentifier>();
1509
1510 for (auto stackNo : periodicBCStacks) {
1511 logDebug(
1512 "sendUserData(...)",
1513 "vertex "
1514 << fineGridVertices[outVertexPositionWithinCell].toString() << " on tree " << _id << " goes to stack "
1515 << stackNo.first << " to realise periodic BC"
1516 );
1517
1518 observer.sendVertex(
1519 outVertexPositionWithinCell,
1520 stackNo.first,
1522 leaveCellTraversalEvent
1523 );
1524 }
1525 }
1526
1527 for (auto p : _splitting) {
1528 if (tarch::la::contains(fineGridVertices[outVertexPositionWithinCell].getBackupOfAdjacentRanks(), p)) {
1529 logDebug(
1530 "sendUserData(...)",
1531 "stream local vertex data of "
1532 << fineGridVertices[outVertexPositionWithinCell].toString() << " from stack " << outVertexStack
1533 << " on tree " << _id << " to upcoming worker " << p << ". Position within cell="
1534 << outVertexPositionWithinCell << ". event=" << leaveCellTraversalEvent.toString()
1535 );
1537 observer.sendVertex(
1538 outVertexPositionWithinCell,
1539 toStack,
1541 leaveCellTraversalEvent
1542 );
1543 } else {
1544 logDebug(
1545 "sendUserData(...)",
1546 "skip vertex data of " << fineGridVertices[outVertexPositionWithinCell].toString() << " on tree " << _id
1547 );
1548 }
1549 }
1550 }
1551 }
1552
1553 for (int i = 0; i < 2 * Dimensions; i++) {
1554 int outFaceStack = leaveCellTraversalEvent.getFaceDataTo(i);
1555 int outFacePositionWithinCell = leaveCellTraversalEvent.getFaceDataFrom(i);
1556
1557 if (peano4::grid::PeanoCurve::isInOutStack(outFaceStack)) {
1560 if (leaveCellTraversalEvent.getIsFaceLocal(outFacePositionWithinCell)) {
1561 int neighbour = getNeighbourTrees(fineGridVertices, outFacePositionWithinCell, false);
1562 if (neighbour >= 0) {
1563 logDebug(
1564 "sendUserData(...)",
1565 "send local face from stack "
1566 << outFaceStack << " of tree " << _id << " to neighbour " << neighbour
1567 << ". Position within cell=" << outFacePositionWithinCell
1568 );
1569
1571 observer.sendFace(
1572 outFacePositionWithinCell,
1573 toStack,
1575 leaveCellTraversalEvent
1576 );
1577 }
1578
1579 if (isFaceAlongPeriodicBoundaryCondition(fineGridVertices, outFacePositionWithinCell, false)) {
1581 outFacePositionWithinCell
1582 );
1583
1584 logDebug(
1585 "sendUserData(...)",
1586 "send local face from stack " << outFaceStack << " of tree " << _id << " to periodic BC stack #" << toStack
1587 );
1588
1589 observer.sendFace(
1590 outFacePositionWithinCell,
1591 toStack,
1593 leaveCellTraversalEvent
1594 );
1595 }
1596 }
1597
1598 for (auto p : _splitting) {
1600 _gridTraversalEventGenerator.getAdjacentRanksOfFace(fineGridVertices, outFacePositionWithinCell, false), p
1601 )) {
1602 logDebug(
1603 "sendUserData(...)",
1604 "stream local face from stack "
1605 << outFaceStack << " of tree " << _id << " to new worker " << p
1606 << ". Position within cell=" << outFacePositionWithinCell
1607 );
1608
1610 observer.sendFace(
1611 outFacePositionWithinCell,
1612 toStack,
1614 leaveCellTraversalEvent
1615 );
1616 }
1617 }
1618 }
1619 }
1620
1621 [[maybe_unused]] int outCellStack = leaveCellTraversalEvent.getCellData();
1622 for (auto p : _splitting) {
1623 if (_gridTraversalEventGenerator.getTreeOwningSpacetreeNode(fineGridVertices, _splitTriggered, _splitting, _joinTriggered, _joining) == p) {
1624 logDebug(
1625 "sendUserData(...)",
1626 "stream local cell of tree "
1627 << _id << " to new worker " << p << ". Left bottom vertex=" << fineGridVertices[0].toString()
1628 );
1629
1631 observer.sendCell(toStack, TraversalObserver::SendReceiveContext::ForkDomain, leaveCellTraversalEvent);
1632 }
1633 }
1634 logTraceOutWith3Arguments("sendUserData(...)", state.toString(), leaveCellTraversalEvent.toString(), _id);
1635}
1636
1638 GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1639) const {
1640 bool isOneVertexAdjacentToPeriodicBC = false;
1641 bool areAllVerticesParentOfForkedTree = true;
1642 bool isOneVertexParentOfForkedTree = false;
1643 dfor2(k) isOneVertexAdjacentToPeriodicBC |= tarch::la::contains(
1644 fineGridVertices[kScalar].getAdjacentRanks(), RankOfPeriodicBoundaryCondition
1645 );
1646 isOneVertexParentOfForkedTree |= fineGridVertices[kScalar].getHasBeenParentOfSubtreeVertexInPreviousTreeSweep();
1647 areAllVerticesParentOfForkedTree
1648 &= (fineGridVertices[kScalar].getHasBeenParentOfSubtreeVertexInPreviousTreeSweep() or fineGridVertices[kScalar].getState() == GridVertex::State::HangingVertex);
1649 enddforx
1650
1651 return isSpacetreeNodeLocal(fineGridVertices, false, false)
1652 and isSpacetreeNodeLocal(coarseGridVertices, false, false) and areAllVerticesNonHanging(fineGridVertices)
1653 and not isOneVertexAdjacentToPeriodicBC and (not isOneVertexParentOfForkedTree);
1654 // not (isOneVertexParentOfForkedTree and areAllVerticesParentOfForkedTree);
1655}
1656
1658 GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1659) {
1660 [[maybe_unused]] constexpr int NoSplit = -1;
1661
1662 if (not _splitTriggered.empty() and _splitTriggered.begin()->second.mode == peano4::SplitInstruction::Mode::BottomUp) {
1663 const bool isSplitCandidate = isCellSplitCandidate(coarseGridVertices, fineGridVertices);
1664 const bool isRefined = isSpacetreeNodeRefined(fineGridVertices);
1665
1666 logDebug(
1667 "splitOrJoinCellBottomUp(...)",
1668 "checked cell"
1669 << ". is-refined=" << isRefined << ", is-split-candidate=" << isSplitCandidate
1670 );
1671
1672 if (isSplitCandidate and isRefined) {
1673 int reducedMarker = _splittedCells.back();
1674 for (int i = 0; i < ThreePowerD; i++) {
1675 int topMarker = _splittedCells.back();
1676 _splittedCells.pop_back();
1677 if (topMarker != reducedMarker) {
1678 reducedMarker = NoSplit;
1679 }
1680 }
1681
1682 if (reducedMarker >= 0) {
1683 updateVertexRanksWithinCell(fineGridVertices, reducedMarker);
1684 }
1685
1686 _splittedCells.push_back(reducedMarker);
1687 } else if (not isSplitCandidate and isRefined) {
1688 for (int i = 0; i < ThreePowerD; i++) {
1689 _splittedCells.pop_back();
1690 }
1691 _splittedCells.push_back(NoSplit);
1692 } else if (isSplitCandidate and not isRefined) {
1693 int targetSpacetreeId = getSplittingTree();
1694 if (targetSpacetreeId >= 0) {
1695 updateVertexRanksWithinCell(fineGridVertices, targetSpacetreeId);
1696 updateSplittingCounter(targetSpacetreeId);
1697 }
1698 _splittedCells.push_back(targetSpacetreeId);
1699 } else if (not isSplitCandidate and not isRefined) {
1700 _splittedCells.push_back(NoSplit);
1701 } else {
1702 assertionMsg(false, "should not be entered as all combination are covered already");
1703 }
1704 }
1705 else if (
1706 not _splitTriggered.empty()
1707 and
1708 _splitTriggered.begin()->second.mode == peano4::SplitInstruction::Mode::AggressiveTopDown
1709 and
1710 not _splittedCells.empty()
1711 ) {
1712 int targetSpacetreeId = _splittedCells.back();
1713 _splittedCells.pop_back();
1714 logDebug(
1715 "splitOrJoinCellBottomUp(...)",
1716 "fork off cell at "
1717 << fineGridVertices[0].toString() << " to tree " << targetSpacetreeId
1718 << ". #splitted-cells=" << _splittedCells.size()
1719 );
1720 assertion(isSpacetreeNodeLocal(fineGridVertices, false, false));
1721 assertion(isSpacetreeNodeLocal(coarseGridVertices, false, false));
1722 updateVertexRanksWithinCell(fineGridVertices, targetSpacetreeId);
1723 }
1724
1725 /*
1726 static int newlyCreatedCells = 0;
1727
1728
1729 if (isSpacetreeNodeRefined(fineGridVertices)) {
1730 assertion1( _splittedCells.size()>=ThreePowerD, _splittedCells.size() );
1731
1732 int reducedMarker = _splittedCells.back();
1733 for (int i=0; i<ThreePowerD; i++) {
1734 int topMarker = _splittedCells.back();
1735 _splittedCells.pop_back();
1736 if (topMarker!=reducedMarker) {
1737 reducedMarker = -1;
1738 }
1739 }
1740
1741 if (reducedMarker>=0 and isSplitCandidate) {
1742 updateVertexRanksWithinCell( fineGridVertices, reducedMarker );
1743 }
1744 else {
1745 reducedMarker = -1;
1746 newlyCreatedCells = 0;
1747 }
1748
1749 _splittedCells.push_back(reducedMarker);
1750 }
1751 else { // not refined
1752 int targetSpacetreeId = getSplittingTree();
1753
1754 if (isSplitCandidate and targetSpacetreeId>=0) {
1755 updateVertexRanksWithinCell( fineGridVertices, targetSpacetreeId );
1756
1757 newlyCreatedCells++;
1758
1759 if (
1760 _gridTraversalEventGenerator.getCellType( coarseGridVertices, 0 )!=CellType::New
1761 or
1762 newlyCreatedCells%ThreePowerD==ThreePowerD-1
1763 ) {
1764 updateSplittingCounter( targetSpacetreeId );
1765 newlyCreatedCells = 0;
1766 }
1767
1768 _splittedCells.push_back(targetSpacetreeId);
1769 }
1770 else {
1771 _splittedCells.push_back(-1);
1772 }
1773 }
1774 */
1775
1776 /*
1777 if (
1778 _spacetreeState==SpacetreeState::JoinTriggered
1779 and
1780 isSpacetreeNodeLocal(fineGridVertices,false,false)
1781 ) {
1782 logDebug( "splitOrJoinCellBottomUp(...)", "will merge cell from tree " << _id << " into master " << _masterId );
1783
1784 for (int i=0; i<TwoPowerD; i++) {
1785 assertion2(fineGridVertices[i].getState()!=GridVertex::State::HangingVertex,fineGridVertices[i].toString(),_id);
1786 logDebug( "splitOrJoinCellBottomUp(...)", "- " << fineGridVertices[i].toString() );
1787 }
1788
1789 updateVertexRanksWithinCell( fineGridVertices, RankOfCellWitchWillBeJoined );
1790 }
1791 */
1792
1793 /*
1794 if (
1795 _spacetreeState==SpacetreeState::Joining
1796 and
1797 isSpacetreeNodeLocal(fineGridVertices,false,false)
1798 and
1799 not isSpacetreeNodeLocal(coarseGridVertices,false,false)
1800 ) {
1801 logDebug( "splitOrJoinCellBottomUp(...)", "merge cell at " << fineGridVertices[0].toString() << " from tree " <<
1802 _id << " into master " << _masterId ); for (int i=0; i<TwoPowerD; i++) {
1803 // reset the 'local' adjacency entries
1804 fineGridVertices[i].setAdjacentRanks(TwoPowerD-1-i,
1805 fineGridVertices[i].getAdjacentRanks(TwoPowerD-1-i)==RankOfCellWitchWillBeJoined ?
1806 _masterId : fineGridVertices[i].getAdjacentRanks(TwoPowerD-1-i)
1807 );
1808 logDebug( "splitOrJoinCellBottomUp(...)", "updated into " << fineGridVertices[i].toString() );
1809 }
1810 }
1811 */
1812}
1813
1815 GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1816) {
1817 [[maybe_unused]] constexpr int NoSplit = -1;
1818
1819 if (not _splitTriggered.empty() and _splitTriggered.begin()->second.mode == peano4::SplitInstruction::Mode::AggressiveTopDown) {
1820 const bool isParentSplit = not _splittedCells.empty();
1821 const int targetSpacetreeId = getSplittingTree();
1822 const bool isSplitCandidate = targetSpacetreeId >= 0 and isCellSplitCandidate(coarseGridVertices, fineGridVertices);
1823 const bool isRefined = isSpacetreeNodeRefined(fineGridVertices);
1824
1825 if (isParentSplit and isRefined) {
1826 assertion(isSpacetreeNodeLocal(fineGridVertices, false, false));
1827 assertion(isSpacetreeNodeLocal(coarseGridVertices, false, false));
1828 int parentId = _splittedCells.back();
1829 _splittedCells.push_back(parentId);
1830 } else if (isParentSplit and not isRefined) {
1831 assertion(isSpacetreeNodeLocal(fineGridVertices, false, false));
1832 assertion(isSpacetreeNodeLocal(coarseGridVertices, false, false));
1833 updateSplittingCounter(targetSpacetreeId);
1834 int parentId = _splittedCells.back();
1835 _splittedCells.push_back(parentId);
1836 } else if (not isParentSplit and isSplitCandidate and isRefined) {
1837 assertion(isSpacetreeNodeLocal(fineGridVertices, false, false));
1838 assertion(isSpacetreeNodeLocal(coarseGridVertices, false, false));
1839 logDebug(
1840 "splitCellTopDown(...)",
1841 "refined cell at "
1842 << fineGridVertices[0].toString() << " should go with all children to tree " << targetSpacetreeId
1843 );
1844 _splittedCells.push_back(targetSpacetreeId);
1845 } else if (not isParentSplit and isSplitCandidate and not isRefined) {
1846 updateSplittingCounter(targetSpacetreeId);
1847 assertion(isSpacetreeNodeLocal(fineGridVertices, false, false));
1848 assertion(isSpacetreeNodeLocal(coarseGridVertices, false, false));
1849 _splittedCells.push_back(targetSpacetreeId);
1850 }
1851 logDebug("splitOrJoinCellBottomUp(...)", "#splitted-cells=" << _splittedCells.size());
1852 }
1853}
1854
1856 GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1857) {
1858 for (auto worker : _joining) {
1859 if (isSpacetreeNodeLocal(coarseGridVertices, false, false) and _gridTraversalEventGenerator.getTreeOwningSpacetreeNode(fineGridVertices, _splitTriggered, _splitting, _joinTriggered, _joining) == worker) {
1860 logDebug(
1861 "mergeCellFromWorkerWithMasterThroughoutJoin(...)",
1862 "cell from worker " << worker << " is merged into master " << _id
1863 );
1864 /*
1865 for (int i=0; i<TwoPowerD; i++) {
1866 if ( not isVertexAdjacentToLocalSpacetree(fineGridVertices[i],true,false) ) {
1867 logDebug(
1868 "mergeCellFromWorkerWithMasterThroughoutJoin(...)",
1869 "have to overwrite adjacency information of local vertex " << fineGridVertices[i].toString() << " on
1870 tree " << _id
1871 );
1872 fineGridVertices[i].setAdjacentRanks( receivedVertex.getAdjacentRanks() );
1873 for (int j=0; j<TwoPowerD; j++) {
1874 fineGridVertices[i].setAdjacentRanks( j,
1875 fineGridVertices[i].getAdjacentRanks(j)==RankOfCellWitchWillBeJoined ? worker :
1876 fineGridVertices[i].getAdjacentRanks(j)
1877 );
1878 }
1879 logDebug(
1880 "mergeCellFromWorkerWithMasterThroughoutJoin(...)",
1881 "overwrote local adjacency information as vertex used to be a remote one: " <<
1882 fineGridVertices[i].toString() << " on tree " << _id
1883 );
1884 }
1885 }
1886 */
1887 updateVertexRanksWithinCell(fineGridVertices, _id);
1888 } else {
1889 for (int i = 0; i < TwoPowerD; i++) {
1890 logDebug("mergeCellFromWorkerWithMasterThroughoutJoin(...)", "- " << coarseGridVertices[i].toString());
1891 }
1892 for (int i = 0; i < TwoPowerD; i++) {
1893 logDebug("mergeCellFromWorkerWithMasterThroughoutJoin(...)", "- " << fineGridVertices[i].toString());
1894 }
1895 }
1896 }
1897}
1898
1900 for (auto& p : _splitTriggered) {
1901 if (p.first == treeId) {
1902 p.second.numberOfFineGridCells = std::max(p.second.numberOfFineGridCells - 1, 0);
1903 break;
1904 }
1905 }
1906}
1907
1909 for (auto& p : _splitTriggered) {
1910 if (p.second.numberOfFineGridCells > 0) {
1911 return p.first;
1912 }
1913 }
1914 return -1;
1915}
1916
1918
1920 GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]
1921) const {
1923 coarseGridVertices[kScalar].getState() != GridVertex::State::HangingVertex, coarseGridVertices[kScalar].toString()
1924 );
1925 coarseGridVertices[kScalar].setIsAntecessorOfRefinedVertexInCurrentTreeSweep(true);
1926 coarseGridVertices[kScalar].setIsParentOfSubtreeVertexInCurrentTreeSweep(true);
1927 fineGridVertices[kScalar].setIsParentOfSubtreeVertexInCurrentTreeSweep(true);
1928 enddforx
1929}
1930
1931void peano4::grid::Spacetree::split(int newSpacetreeId, const SplitInstruction& instruction) {
1932 assertion3(
1933 instruction.numberOfFineGridCells == std::numeric_limits<int>::max() or maySplit(),
1934 newSpacetreeId,
1935 instruction,
1936 toString()
1937 );
1938 assertion3(
1939 instruction.numberOfFineGridCells != std::numeric_limits<int>::max(), newSpacetreeId, instruction, toString()
1940 );
1941 assertion3(instruction.numberOfFineGridCells >= 1, newSpacetreeId, instruction, toString());
1942
1943 _splitTriggered.insert(std::pair<int, SplitInstruction>(newSpacetreeId, instruction));
1944
1945 auto firstMode = _splitTriggered.begin()->second.mode;
1946 for (auto& p : _splitTriggered) {
1947 if (p.second.mode != firstMode) {
1948 logWarning(
1949 "split(...)",
1950 "split of tree "
1951 << p.first << " is of type " << p.second.mode << " while other splits have mode " << firstMode
1952 << ". Switch all splits to " << firstMode
1953 );
1954 p.second.mode = firstMode;
1955 }
1956 }
1957}
1958
1960 std::ostringstream msg;
1961 msg << "(id=" << _id << ",master=" << _masterId << ",state=" << peano4::grid::toString(_spacetreeState)
1962 << ",statistics=" << _statistics.toString();
1963 if (_joinTriggered.empty()) {
1964 msg << ",no-join-triggered-with-any-tree";
1965 } else {
1966 msg << ",join-triggered={";
1967 for (const auto& p : _joinTriggered) {
1968 msg << "(" << p << ")";
1969 }
1970 msg << "}";
1971 }
1972 if (_joining.empty()) {
1973 msg << ",not-joining";
1974 } else {
1975 msg << ",joining={";
1976 for (const auto& p : _joining) {
1977 msg << "(" << p << ")";
1978 }
1979 msg << "}";
1980 }
1981 /*
1982 if (_hasJoined.empty()) {
1983 msg << ",noone-has-joined-recently";
1984 }
1985 else {
1986 msg << ",has-joined-recently={";
1987 for (const auto& p: _hasJoined) {
1988 msg << "(" << p << ")";
1989 }
1990 msg << "}";
1991 }
1992 */
1993 if (_splitTriggered.empty()) {
1994 msg << ",no-split-triggered";
1995 } else {
1996 msg << ",split-triggered={";
1997 for (const auto& p : _splitTriggered) {
1998 msg << "(" << p.first << "," << p.second << ")";
1999 }
2000 msg << "}";
2001 }
2002 if (_splitting.empty()) {
2003 msg << ",not-splitting";
2004 } else {
2005 msg << ",splitting={";
2006 for (const auto& p : _splitting) {
2007 msg << "(" << p << ")";
2008 }
2009 msg << "}";
2010 }
2011 msg << ",stacks:" << _vertexStack.toString() << ")";
2012 return msg.str();
2013}
2014
2016 return _spacetreeState == SpacetreeState::Running and _joinTriggered.empty() and _joining.empty()
2017 and _splitting.empty() and _statistics.getNumberOfLocalUnrefinedCells() > 0
2018 and (_splitTriggered.empty() or _splitTriggered.begin()->second.numberOfFineGridCells < std::numeric_limits<int>::max());
2019}
2020
2022 return _spacetreeState == SpacetreeState::Running and _splitTriggered.empty() and _joining.empty()
2023 and _splitting.empty() and _joinTriggered.empty();
2024}
2025
2027 return _spacetreeState == SpacetreeState::Running and _masterId >= 0
2028 and _statistics.getStationarySweeps() > NumberOfStationarySweepsToWaitAtLeastTillJoin
2029 and _splitTriggered.empty() and _splitting.empty() and _joinTriggered.empty() and _joining.empty()
2030 and _statistics.getNumberOfLocalRefinedCells() == 0;
2031}
2032
2034 assertion1(mayJoinWithMaster(), _id);
2035 _spacetreeState = SpacetreeState::JoinTriggered;
2036 assertion(_splitTriggered.empty());
2037 assertion(_splitting.empty());
2038 assertion(_splittedCells.empty());
2039 assertion(_joining.empty());
2040}
2041
2043 logInfo("joinWithWorker(int)", "merge tree " << id << " into tree " << _id);
2044 assertion2(_joinTriggered.count(id) == 0, id, _id);
2045 _joinTriggered.insert(id);
2046 assertion2(_splitTriggered.empty(), id, toString());
2047 assertion2(_splitting.empty(), id, toString());
2048}
2049
2051 return not _joinTriggered.empty() or not _joining.empty() or not _splitTriggered.empty() or not _splitting.empty();
2052}
#define assertion2(expr, param0, param1)
#define assertion4(expr, param0, param1, param2, param3)
#define assertionVectorNumericalEquals3(lhs, rhs, param0, param1, param2)
#define assertionNumericalEquals5(lhs, rhs, a, b, c, d, e)
#define assertion3(expr, param0, param1, param2)
#define assertion1(expr, param)
#define assertionMsg(expr, message)
#define assertion(expr)
#define assertionEquals5(lhs, rhs, larg, rarg, three, four, five)
#define assertionEquals4(lhs, rhs, larg, rarg, three, four)
#define assertion6(expr, param0, param1, param2, param3, param4, param5)
we integrate over each cell and then take the sum across each of the cells We also consider the terms that enter the f$ k
#define TwoTimesD
Definition Globals.h:29
#define ThreePowerD
Definition Globals.h:24
#define TwoPowerD
Definition Globals.h:19
#define DimensionsTimesTwo
Definition Globals.h:17
AutomatonState state
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logTraceOutWith1Argument(methodName, argument0)
Definition Log.h:380
#define logTraceOut(methodName)
Definition Log.h:379
#define logWarning(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:440
#define logTraceOutWith3Arguments(methodName, argument0, argument1, argument2)
Definition Log.h:382
#define logTraceInWith3Arguments(methodName, argument0, argument1, argument2)
Definition Log.h:372
#define logTraceOutWith2Arguments(methodName, argument0, argument1)
Definition Log.h:381
#define logTraceIn(methodName)
Definition Log.h:369
#define logTraceInWith1Argument(methodName, argument0)
Definition Log.h:370
#define logTraceInWith2Arguments(methodName, argument0, argument1)
Definition Log.h:371
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
#define endzfor
Definition Loop.h:1044
#define dfor2(counter)
Shortcut For dfor(counter,2)
Definition Loop.h:906
#define dfor3(counter)
Shortcut For dfor(counter,3)
Definition Loop.h:642
#define zfor3(counter, direction)
Definition Loop.h:1039
#define enddforx
I prefer to use this macro for dforx instead of a closing bracket as many syntax parser fail otherwis...
Definition Loop.h:928
std::bitset< Dimensions > periodicBC
Definition main.cpp:19
static int getVertexWriteStackNumber(const AutomatonState &state, const std::bitset< Dimensions > &vertex)
static void invertEvenFlag(AutomatonState &cell, int axis)
static bool isInOutStack(int number)
static int getVertexReadStackNumber(const AutomatonState &state, const std::bitset< Dimensions > &vertex)
static peano4::utils::LoopDirection getLoopDirection(const AutomatonState &state)
Holds a set bit for each dimension along which the traversal is positive.
static void setEntryFace(AutomatonState &cell, int axis)
static bool isTraversePositiveAlongAxis(const AutomatonState &state, int axis)
Definition PeanoCurve.cpp:9
static std::bitset< Dimensions > getFirstVertexIndex(const AutomatonState &cell)
Looks into a cell of the spacetree and gives the index of the first local vertex.
static void setExitFace(AutomatonState &cell, int axis)
static void refineState(const AutomatonState &coarseGrid, AutomatonState fineGrid[ThreePowerD], tarch::la::Vector< Dimensions, int > fineGridPosition=tarch::la::Vector< Dimensions, int >(0), int axis=Dimensions-1)
Takes a state (describing a node in the tree) and returns the states on the next finer level along t...
void mergeGridVertexRefinementStateAtHorizontalDomainBoundary(GridVertex &vertex, const GridVertex &inVertex, int neighbour)
Called by receiveAndMergeGridVertexAtHorizontalBoundary().
static void updateVertexRanksWithinCell(GridVertex fineGridVertices[TwoPowerD], int newId)
If a cell gets a new id, we have to update its vertices.
void receiveAndMergeGridVertexAtHorizontalBoundary(GridVertex &vertex)
Manage the data exchange after a vertex is loaded for the first time.
bool maySplit() const
Is the tree in principle allowed to split.
void traverse(TraversalObserver &observer, bool calledFromSpacetreeSet=false)
GridStatistics getGridStatistics() const
void split(int treeId, const SplitInstruction &instruction)
Add a split instruction.
std::string toString() const
bool isVertexAdjacentToLocalSpacetree(GridVertex vertex, bool splittingIsConsideredLocal, bool joiningIsConsideredLocal) const
Returns if a vertex is local to adjacent tree.
Definition Spacetree.cpp:82
void descend(const AutomatonState &state, GridVertex vertices[TwoPowerD], TraversalObserver &observer)
void updateSplittingCounter(int treeId)
Reduce splitting counter.
bool isCellSplitCandidate(GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]) const
Can a cell be split (deployed to another rank)
void splitOrJoinCellBottomUp(GridVertex vertex[TwoPowerD], GridVertex fineGridVertices[TwoPowerD])
Realise the splits and joins.
bool doesRankIndexIdentifyHorizontalDataExchange(int rank, bool calledByReceivingProcess) const
You may exchange data horizontally with rank if and only if.
void splitCellTopDown(GridVertex vertex[TwoPowerD], GridVertex fineGridVertices[TwoPowerD])
Split cell in a top down fashion.
bool isFaceAlongPeriodicBoundaryCondition(GridVertex vertex[TwoPowerD], int faceNumber, bool calledByReceivingProcess) const
void receiveAndMergeGridVertexAtVerticalBoundary(GridVertex &vertex)
This is a merge routine for vertical data exchange.
GridStatistics _statistics
Definition Spacetree.h:99
void updateVertexBeforeStore(GridVertex &vertex, GridVertex fineGridVertices[TwoPowerD], const tarch::la::Vector< Dimensions, int > &fineVertexPositionWithinPatch)
void mergeCellFromWorkerWithMasterThroughoutJoin(GridVertex vertex[TwoPowerD], GridVertex fineGridVertices[TwoPowerD])
Merge data from worker with master data throughout join.
std::set< int > getNeighbourTrees(const GridVertex &vertex, bool calledByReceivingProcess) const
Get the ids of the surrounding cells of a vertex.
void sendGridVertex(const GridVertex &vertex)
This one is to be invoked if and only if a vertex goes to the in/out stacks.
void storeVertices(const AutomatonState &fineGridState, GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD], const tarch::la::Vector< Dimensions, int > &cellPositionWithin3x3Patch, TraversalObserver &observer)
bool mayJoinWithWorker() const
We allow at most one join at a time and not while we split.
const std::bitset< Dimensions > _periodicBC
Indicate per axis whether we have periodic boundary conditions.
Definition Spacetree.h:115
static void incrementNumberOfAdjacentRefinedLocalCells(GridVertex vertices[TwoPowerD])
Every local refined cell should call this routine.
void markVerticesAroundForkedCell(GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD]) const
setIsAntecessorOfRefinedVertexInCurrentTreeSweep()
void loadVertices(const AutomatonState &fineGridState, GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD], const tarch::la::Vector< Dimensions, int > &cellPositionWithin3x3Patch, TraversalObserver &observer)
Load the vertices of one cell.
bool areAllVerticesNonHanging(GridVertex vertices[TwoPowerD]) const
Could also be called areAllVerticesPersistent() in the Peano terminology.
Definition Spacetree.cpp:97
static constexpr int NumberOfStationarySweepsToWaitAtLeastTillJoin
Definition Spacetree.h:55
bool areAllVerticesUnrefined(GridVertex vertices[TwoPowerD]) const
AutomatonState _root
The root of a spacetree corresponds to the initial state of the tree traversal automaton.
Definition Spacetree.h:97
static GridVertexStackMap _vertexStack
Definition Spacetree.h:152
void receiveAndMergeUserData(const AutomatonState &state, TraversalObserver &observer, const GridTraversalEvent &enterCellTraversalEvent, GridVertex fineGridVertices[TwoPowerD])
Spacetree(int newId, int masterId, const tarch::la::Vector< Dimensions, double > &offset, const tarch::la::Vector< Dimensions, double > &width, bool traversalInverted)
Only used by SpacetreeSet to create children of the original tree.
Definition Spacetree.cpp:48
bool areAllVerticesRefined(GridVertex vertices[TwoPowerD]) const
static tarch::la::Vector< Dimensions, int > convertToIntegerVector(const std::bitset< Dimensions > &in)
Little helper.
bool shouldEraseAdjacencyInformation(const GridVertex &vertex, GridVertex coarseGridVertices[TwoPowerD], tarch::la::Vector< Dimensions, int > fineVertexPositionWithinPatch) const
void mergeGridVertexAdjacencyListsAtHorizontalDomainBoundary(GridVertex &vertex, const GridVertex &inVertex, int neighbour)
void joinWithWorker(int id)
bool isSpacetreeNodeLocal(GridVertex vertices[TwoPowerD], bool splittingIsConsideredLocal, bool joiningIsConsideredLocal) const
Wrapper around GridTraversalEventGenerator::isSpacetreeNodeLocal()
bool mayJoinWithMaster() const
Only ranks that have no kids are allowed to join.
void evaluateGridControlEvents(const AutomatonState &fineGridState, GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD])
Should only be called for inner cells.
bool isInvolvedInJoinOrFork() const
void updateVertexAfterLoad(GridVertex &vertex, GridVertex fineGridVertices[TwoPowerD], const tarch::la::Vector< Dimensions, int > &fineVertexPositionWithinPatch, TraversalObserver &observer)
This operation has multiple purposes.
static tarch::logging::Log _log
Definition Spacetree.h:58
void joinWithMaster()
Join with master.
void sendUserData(const AutomatonState &state, TraversalObserver &observer, const GridTraversalEvent &enterCellTraversalEvent, GridVertex fineGridVertices[TwoPowerD])
Send user data.
tarch::la::Vector< TwoPowerD, int > getAdjacentRanksForNewVertex(GridVertex coarseGridVertices[TwoPowerD], const tarch::la::Vector< Dimensions, int > &vertexPositionWithin3x3Patch) const
static bool restrictToCoarseGrid(const tarch::la::Vector< Dimensions, int > &coarseVertexPosition, const tarch::la::Vector< Dimensions, int > &fineVertexPosition)
Determines whether to restrict a vertex to the coarser level or not.
virtual void receiveAndMergeVertex(int position, int fromStack, SendReceiveContext context, const GridTraversalEvent &event)
static constexpr int CreateOrDestroyHangingGridEntity
Implies that the data will then be local or had been local.
static constexpr int CreateOrDestroyPersistentGridEntity
Implies that the data will then be local or had been local.
virtual void loadCell(const GridTraversalEvent &event)=0
virtual void receiveAndMergeFace(int position, int fromStack, SendReceiveContext context, const GridTraversalEvent &event)
virtual void storeCell(const GridTraversalEvent &event)=0
virtual void beginTraversal(const tarch::la::Vector< Dimensions, double > &x, const tarch::la::Vector< Dimensions, double > &h)=0
Begin the traversal.
virtual void endTraversal(const tarch::la::Vector< Dimensions, double > &x, const tarch::la::Vector< Dimensions, double > &h)=0
static constexpr int NoData
Can this grid entity hold data.
virtual std::vector< GridControlEvent > getGridControlEvents() const =0
virtual void leaveCell(const GridTraversalEvent &event)=0
virtual void enterCell(const GridTraversalEvent &event)=0
Event is invoked per cell.
static int getOutputStackForPeriodicBoundaryExchange(int faceNumber)
Identify output stack for periodic boundary data written by face.
Definition Node.cpp:250
static int getOutputStackNumberForHorizontalDataExchange(int id)
Hand in a spacetree id and get back the number that we should use to send something to this tree.
Definition Node.cpp:211
static int getInputStackNumberForHorizontalDataExchange(int id)
Counterpart of getOutputStackNumberOfBoundaryExchange(int)
Definition Node.cpp:216
std::pair< int, int > PeriodicBoundaryStackIdentifier
A periodic boundary stack is basically a stack (an integer), but I do augment it by a bitset which id...
Definition Node.h:216
static int getOutputStackNumberForVerticalDataExchange(int id)
Definition Node.cpp:221
static std::set< PeriodicBoundaryStackIdentifier > getOutputStacksForPeriodicBoundaryExchange(const tarch::la::Vector< TwoPowerD, int > &flags)
You hand in a the flags of a vertex and you get the boundary stack identifiers including their direct...
Definition Node.cpp:282
static int getPeriodicBoundaryExchangeInputStackNumberForOutputStack(int outputStackNumber)
Hand in an output stack number of a face and you get back the input stack number.
Definition Node.cpp:355
static int getInputStackNumberForVerticalDataExchange(int id)
Get the input stack where a tree writes all of its vertical data to/from when it exchanges informatio...
Definition Node.cpp:226
static Node & getInstance()
This operation returns the singleton instance.
Definition Node.cpp:108
Log Device.
Definition Log.h:516
void log(const std::string &identifier, double value, bool disableSampling=false)
Log one particular value.
Definition Statistics.h:90
static Statistics & getInstance()
This is not the canonical realisation of singletons as I use it usually for stats in Peano.
bool isSpacetreeNodeRefined(GridVertex vertices[TwoPowerD])
A spacetree node is refined if any of its adjacent vertices holds one of the following flags:
Definition grid.cpp:242
std::string toString(VertexType type)
Definition grid.cpp:277
bool isSpacetreeNodeLocal(GridVertex vertices[TwoPowerD], bool splittingIsConsideredLocal, bool joiningIsConsideredLocal, int id)
A spacetree node as 2^d adjacent vertices.
void clear(GridStatistics &statistics, bool isGlobalMasterTree)
The term clear() is not 100% correct, as the number of stationary traversals is not reset to a dummy ...
Definition grid.cpp:231
GridVertex createVertex(GridVertex::State state, const tarch::la::Vector< Dimensions, double > &x, int level, const tarch::la::Vector< TwoPowerD, int > &adjacentRanks, bool isNewFineGridVertex)
Factory mechanism.
Definition grid.cpp:65
@ NewFromSplit
Set if this tree results from a split and if this is the first grid sweep when the former owner actua...
@ JoinTriggered
Join has been triggered for this tree.
@ EmptyRun
Not yet a new root.
bool overlaps(const tarch::la::Vector< Dimensions, double > &x, const GridControlEvent &event)
Definition grid.cpp:60
constexpr int InvalidRank(-1)
std::vector< GridControlEvent > merge(std::vector< GridControlEvent > events, const double Tolerance=0.1)
Merge set of refinement/coarsening commands.
Definition grid.cpp:113
bool isContained(const AutomatonState &x, const GridControlEvent &event, double upscaleAutomatonState=1.0)
isContained() is defined over the closed interval, i.e.
Definition grid.cpp:44
std::bitset< Dimensions > LoopDirection
Is used by the z-loop.
Definition Loop.h:65
CPUGPUMethod int dLinearised(const tarch::la::Vector< Dimensions, int > &counter, int max)
Map d-dimensional vector onto integer index.
Definition Loop.cpp:106
bool allGreaterEquals(const Vector< Size, Scalar > &lhs, const Scalar &cmp, const Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
int countEqualEntries(const Vector< Size, int > &lhs, const Vector< Size, int > &rhs)
Run through both vectors and count how many entries are the same.
bool allSmaller(const Vector< Size, Scalar > &lhs, const Scalar &cmp, const Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
bool equals(const Matrix< Rows, Cols, Scalar > &lhs, const Matrix< Rows, Cols, Scalar > &rhs, const Scalar &tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares to matrices on equality by means of a numerical accuracy.
Matrix< Rows, Cols, Scalar > multiplyComponents(const Matrix< Rows, X, Scalar > &lhs, const Matrix< X, Cols, Scalar > &rhs)
bool contains(const Vector< Size, Scalar > &vector, const Scalar &value)
Scalar min(const Vector< Size, Scalar > &vector)
Returns the element with minimal value (NOT absolute value).
Instruction to split.
Definition grid.h:34
Provide information about selected face.
Definition FaceMarker.h:35
tarch::la::Vector< Dimensions, double > getX() const
void setAccessNumber(const tarch::la::Vector< DimensionsTimesTwo, int > &value)
tarch::la::Vector< Dimensions, double > getH() const
void setH(const tarch::la::Vector< Dimensions, double > &value)
void setEvenFlags(const std::bitset< Dimensions > &value)
void setX(const tarch::la::Vector< Dimensions, double > &value)
std::bitset< TwoTimesD > getIsFaceLocal() const
tarch::la::Vector< TwoTimesD, int > getFaceDataFrom() const
tarch::la::Vector< TwoPowerD, int > getVertexDataFrom() const
tarch::la::Vector< TwoTimesD, int > getFaceDataTo() const
tarch::la::Vector< TwoPowerD, int > getVertexDataTo() const
std::bitset< TwoPowerD > getIsVertexLocal() const
bool getIsParentOfSubtreeVertexInCurrentTreeSweep() const
tarch::la::Vector< TwoPowerD, int > getAdjacentRanks() const
int getNumberOfAdjacentRefinedLocalCells() const
void setBackupOfAdjacentRanks(const tarch::la::Vector< TwoPowerD, int > &value)
tarch::la::Vector< TwoPowerD, int > getBackupOfAdjacentRanks() const
std::string toString() const
bool getIsAntecessorOfRefinedVertexInCurrentTreeSweep() const
void setState(State value)
void setAdjacentRanks(const tarch::la::Vector< TwoPowerD, int > &value)
peano4::grid::GridVertex::State getState() const
Simple vector class.
Definition Vector.h:134