Peano
Loading...
Searching...
No Matches
SpacetreeSet-main.cpp
Go to the documentation of this file.
1// This file is part of the Peano project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3#include "SpacetreeSet-main.h"
4
5#include "Constants.h"
8#include "peano4/parallel/SpacetreeSet.h"
9#include "peano4/peano4.h"
10#include "tarch/logging/Log.h"
11#include "tarch/logging/LogFilter.h"
12#include "tarch/mpi/Rank.h"
13#include "tarch/timing/Watch.h"
14#include "toolbox/loadbalancing/LoadBalancer.h"
15
16#include <iomanip>
17#include <limits>
18
19using namespace tests::peano4::parallel;
20
21namespace {
22 tarch::logging::Log _log("");
23
24 constexpr int CreateGridWithRefinement = 0;
25 constexpr int CreateGridWithoutRefinement = 1;
26 constexpr int EmptyTraversal = 2;
27
28 static toolbox::loadbalancing::LoadBalancer loadBalancer;
29
30 static tarch::timing::Watch watch("::", "", false);
31
32 void setupEnvironment(int argc, char** argv) {
33#if DIMENSIONS == 2
34 const auto DomainOffset = {0.0, 0.0};
35 const auto DomainSize = {1.0, 1.0};
36#else
37 const auto DomainOffset = {0.0, 0.0, 0.0};
38 const auto DomainSize = {1.0, 1.0, 1.0};
39#endif
40
41 tarch::logging::LogFilter::getInstance().addFilterListEntry(
42 tarch::logging::LogFilter::FilterListEntry(
43 tarch::logging::LogFilter::FilterListEntry::TargetDebug,
44 tarch::logging::LogFilter::FilterListEntry::AnyRank,
45 "tarch",
46 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
47 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
48 )
49 );
50 tarch::logging::LogFilter::getInstance().addFilterListEntry(
51 tarch::logging::LogFilter::FilterListEntry(
52 tarch::logging::LogFilter::FilterListEntry::TargetTrace,
53 tarch::logging::LogFilter::FilterListEntry::AnyRank,
54 "tarch",
55 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
56 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
57 )
58 );
59 tarch::logging::LogFilter::getInstance().addFilterListEntry(
60 tarch::logging::LogFilter::FilterListEntry(
61 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
62 tarch::logging::LogFilter::FilterListEntry::AnyRank,
63 "tarch",
64 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
65 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
66 )
67 );
68 tarch::logging::LogFilter::getInstance().addFilterListEntry(
69 tarch::logging::LogFilter::FilterListEntry(
70 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
71 0,
72 "tarch",
73 tarch::logging::LogFilter::FilterListEntry::WhiteListEntry,
74 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
75 )
76 );
77
78 tarch::logging::LogFilter::getInstance().addFilterListEntry(
79 tarch::logging::LogFilter::FilterListEntry(
80 tarch::logging::LogFilter::FilterListEntry::TargetDebug,
81 tarch::logging::LogFilter::FilterListEntry::AnyRank,
82 "peano4",
83 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
84 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
85 )
86 );
87 tarch::logging::LogFilter::getInstance().addFilterListEntry(
88 tarch::logging::LogFilter::FilterListEntry(
89 tarch::logging::LogFilter::FilterListEntry::TargetTrace,
90 tarch::logging::LogFilter::FilterListEntry::AnyRank,
91 "peano4",
92 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
93 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
94 )
95 );
96 tarch::logging::LogFilter::getInstance().addFilterListEntry(
97 tarch::logging::LogFilter::FilterListEntry(
98 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
99 tarch::logging::LogFilter::FilterListEntry::AnyRank,
100 "peano4",
101 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
102 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
103 )
104 );
105 tarch::logging::LogFilter::getInstance().addFilterListEntry(
106 tarch::logging::LogFilter::FilterListEntry(
107 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
108 0,
109 "peano4",
110 tarch::logging::LogFilter::FilterListEntry::WhiteListEntry,
111 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
112 )
113 );
114
115 tarch::logging::LogFilter::getInstance().addFilterListEntry(
116 tarch::logging::LogFilter::FilterListEntry(
117 tarch::logging::LogFilter::FilterListEntry::TargetDebug,
118 tarch::logging::LogFilter::FilterListEntry::AnyRank,
119 "toolbox",
120 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
121 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
122 )
123 );
124 tarch::logging::LogFilter::getInstance().addFilterListEntry(
125 tarch::logging::LogFilter::FilterListEntry(
126 tarch::logging::LogFilter::FilterListEntry::TargetTrace,
127 tarch::logging::LogFilter::FilterListEntry::AnyRank,
128 "toolbox",
129 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
130 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
131 )
132 );
133 tarch::logging::LogFilter::getInstance().addFilterListEntry(
134 tarch::logging::LogFilter::FilterListEntry(
135 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
136 tarch::logging::LogFilter::FilterListEntry::AnyRank,
137 "toolbox",
138 tarch::logging::LogFilter::FilterListEntry::BlackListEntry,
139 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
140 )
141 );
142 tarch::logging::LogFilter::getInstance().addFilterListEntry(
143 tarch::logging::LogFilter::FilterListEntry(
144 tarch::logging::LogFilter::FilterListEntry::TargetInfo,
145 0,
146 "toolbox",
147 tarch::logging::LogFilter::FilterListEntry::WhiteListEntry,
148 tarch::logging::LogFilter::FilterListEntry::AlwaysOn
149 )
150 );
151
152 peano4::init(&argc, &argv, DomainOffset, DomainSize, 0);
153 peano4::writeCopyrightMessage();
154 }
155
156 void shutdownEnvironment() { peano4::shutdown(); }
157
158 void logGridTraversalStatistics(const char* step, double dt) {
159 if (tarch::mpi::Rank::getInstance().isGlobalMaster()) {
160 logInfo(
161 "logGridTraversalStatistics()",
162 step
163 << " traversal took " << std::fixed << std::setprecision(4) << dt << "s"
164 << ": Leaves=" << loadBalancer.getStatistics().getGlobalNumberOfInnerUnrefinedCells()
165 << ", Trees=" << loadBalancer.getStatistics().getGlobalNumberOfTrees()
166 );
167 }
168 }
169
170 void runNextAlgorithmicStep() {
171 const int currentStep = peano4::parallel::Node::getInstance().getCurrentProgramStep();
172
173 switch (currentStep) {
174 case CreateGridWithRefinement: {
175 tarch::logging::LogFilter::getInstance().switchProgramPhase("CreateGridWithRefinement");
176 CreateGridObserver createGridObserverWithRefinement(true);
177 watch.start();
178 peano4::parallel::SpacetreeSet::getInstance().traverse(createGridObserverWithRefinement);
179 watch.stop();
180 loadBalancer.update();
181 logGridTraversalStatistics("CreateGrid", watch.getCalendarTime());
182 break;
183 }
184 case CreateGridWithoutRefinement: {
185 tarch::logging::LogFilter::getInstance().switchProgramPhase("CreateGridWithoutRefinement");
186 CreateGridObserver createGridObserverWithoutRefinement(false);
187 watch.start();
188 peano4::parallel::SpacetreeSet::getInstance().traverse(createGridObserverWithoutRefinement);
189 watch.stop();
190 loadBalancer.update();
191 logGridTraversalStatistics("CreateGrid", watch.getCalendarTime());
192 break;
193 }
194 case EmptyTraversal: {
195 tarch::logging::LogFilter::getInstance().switchProgramPhase("EmptyTraversal");
196 EmptyTraversalObserver emptyTraversalObserver;
197 watch.start();
198 peano4::parallel::SpacetreeSet::getInstance().traverse(emptyTraversalObserver);
199 watch.stop();
200 loadBalancer.update();
201 logGridTraversalStatistics("Empty", watch.getCalendarTime());
202 break;
203 }
204 default:
205 assertion(false);
206 break;
207 }
208 }
209
211 static bool initialised = false;
212 static bool gridConstructed = false;
213 static double currentMinH = std::numeric_limits<double>::max();
214 static int currentGlobalNumberOfTrees = 0;
215 static int numberOfStationarySweeps = 0;
216
217 if (not initialised) {
218 peano4::parallel::Node::getInstance().setNextProgramStep(CreateGridWithRefinement);
219 initialised = true;
220 return true;
221 }
222
223 // If we have already executed the empty traversal, we are done.
224 if (gridConstructed and peano4::parallel::Node::getInstance().getCurrentProgramStep() == EmptyTraversal) {
225 return false;
226 }
227
228 // Once the grid is constructed, run exactly one final empty traversal and then terminate.
229 if (gridConstructed) {
230 peano4::parallel::Node::getInstance().setNextProgramStep(EmptyTraversal);
231 return true;
232 }
233
234 // Grid construction phase.
235 assertion(loadBalancer.getStatistics().getGlobalNumberOfTrees() > 0);
236
237 const int currentProgramStep = peano4::parallel::Node::getInstance().getCurrentProgramStep();
238
239 if (tarch::la::smaller(loadBalancer.getStatistics().getGlobalMinH(), currentMinH)) {
240 currentMinH = loadBalancer.getStatistics().getGlobalMinH();
241 peano4::parallel::Node::getInstance().setNextProgramStep(CreateGridWithoutRefinement);
242 return true;
243 }
244
245 if (loadBalancer.getStatistics().getGlobalNumberOfTrees() > currentGlobalNumberOfTrees) {
246 currentGlobalNumberOfTrees = loadBalancer.getStatistics().getGlobalNumberOfTrees();
247 peano4::parallel::Node::getInstance().setNextProgramStep(CreateGridWithoutRefinement);
248 return true;
249 }
250
251 if (tarch::la::smallerEquals(currentMinH, MinH) and loadBalancer.isStagnating()
252 and currentProgramStep == CreateGridWithRefinement) {
253 // Guard against rare infinite loops when not all ranks become stationary.
254 if (loadBalancer.getStatistics().getGlobalNumberOfStationarySweeps() == 0
255 and numberOfStationarySweeps < loadBalancer.getNumberOfSettlingIterations()) {
256 logInfo(
257 "selectNextAlgorithmicStep()",
258 "Admissible mesh size reached, but at least one rank still has pending refinement events."
259 );
260 peano4::parallel::Node::getInstance().setNextProgramStep(CreateGridWithRefinement);
261 ++numberOfStationarySweeps;
262 return true;
263 }
264
265 logInfo(
266 "selectNextAlgorithmicStep()",
267 "Grid construction complete. Admissible mesh size reached (h_{min}="
268 << currentMinH << ", admissible h_{min}=" << MinH << ") and load balancing has converged."
269 );
270
271 gridConstructed = true;
272 peano4::parallel::Node::getInstance().setNextProgramStep(EmptyTraversal);
273 return true;
274 }
275
276 peano4::parallel::Node::getInstance().setNextProgramStep(CreateGridWithRefinement);
277 return true;
278 }
279
280 int runGlobalMaster() {
281 while (selectNextAlgorithmicStep()) {
282 peano4::parallel::Node::getInstance().continueToRun();
283 runNextAlgorithmicStep();
284 }
285
286 // Broadcast termination to all other ranks.
287 peano4::parallel::Node::getInstance().setNextProgramStep(peano4::parallel::Node::Terminate);
288 peano4::parallel::Node::getInstance().continueToRun();
289
290 return EXIT_SUCCESS;
291 }
292
293 void runWorker() {
294 while (peano4::parallel::Node::getInstance().continueToRun()) {
295 runNextAlgorithmicStep();
296 }
297 }
298} // namespace
299
300int main(int argc, char** argv) {
301 setupEnvironment(argc, argv);
302
303 int result = EXIT_SUCCESS;
304 if (tarch::mpi::Rank::getInstance().isGlobalMaster()) {
305 result = runGlobalMaster();
306 } else {
307 runWorker();
308 }
309
310 shutdownEnvironment();
311 return result;
312}
int main(int argc, char **argv)
bool selectNextAlgorithmicStep()
Decide which step to run next.
Definition ccz4-main.cpp:70
void step()
tarch::logging::Log _log("::")