Peano
Loading...
Searching...
No Matches
test_derive_load_store_compute_flag.py
Go to the documentation of this file.
1from peano4.api.solversteps import Step
2from peano4.api.taskgraph import Task
4 _DEFAULT_LOAD_STORE_COMPUTE_FLAG,
5 derive_load_store_compute_flag,
6)
7
8
9READ_AND_DISCARD = Task.DataAccess.READ_AND_DISCARD
10WRITE = Task.DataAccess.WRITE
11READ_AND_WRITE = Task.DataAccess.READ_AND_WRITE
12TEMPORARY = Task.DataAccess.TEMPORARY
13
14
16 """Minimal stand-in for peano4.api.datamodel.PatchToDoubleArrayWithSmartPointer:
17 derive_load_store_compute_flag() only ever needs somewhere to write
18 load_store_compute_flag to."""
19
20 def __init__(self):
22 self.includes = ""
23
24
26 """Minimal stand-in for a peano4.api.datamodel.Patch, with a generator
27 attribute like the real thing has."""
28
29 def __init__(self, name):
30 self.name = name
32
33 def __repr__(self):
34 return self.name
35
36
37def _make_step(name):
38 return Step(name=name, add_user_defined_actions=False)
39
40
41def _use_cell(step, submodel, qualifier):
42 step.use_cell(submodel)
43 step.cell_data_access[submodel] = qualifier
44
45
46def _use_face(step, submodel, qualifier):
47 step.use_face(submodel)
48 step.face_data_access[submodel] = qualifier
49
50
51def _use_vertex(step, submodel, qualifier):
52 step.use_vertex(submodel)
53 step.vertex_data_access[submodel] = qualifier
54
55
56def _active(step) -> str:
57 """The exact "this Step is active" expression, for asserting against -
58 built the same way the production code builds it, so these tests break
59 if that expression's shape ever changes."""
60 return (
61 "peano4::parallel::Node::getInstance().getCurrentProgramStep() == "
62 f"repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::{step.name})"
63 )
64
65
66def _flag(use, load, store) -> str:
67 return f"::peano4::grid::constructLoadStoreComputeFlag({use}, {load}, {store})"
68
69
71 step = _make_step("TimeStep_Reconstruction")
72 submodel = _FakeSubmodel("Q")
73 _use_cell(step, submodel, READ_AND_DISCARD)
74
75 derive_load_store_compute_flag([step])
76
77 active = _active(step)
78 assert submodel.generator.load_store_compute_flag == _flag(active, active, "false")
79
80
82 step = _make_step("Setup_InitialCondition")
83 submodel = _FakeSubmodel("Q")
84 _use_cell(step, submodel, WRITE)
85
86 derive_load_store_compute_flag([step])
87
88 active = _active(step)
89 assert submodel.generator.load_store_compute_flag == _flag(active, "false", active)
90
91
93 step = _make_step("TimeStep_UpdateCell")
94 submodel = _FakeSubmodel("Q")
95 _use_cell(step, submodel, READ_AND_WRITE)
96
97 derive_load_store_compute_flag([step])
98
99 active = _active(step)
100 assert submodel.generator.load_store_compute_flag == _flag(active, active, active)
101
102
104 step = _make_step("TimeStep_Relay")
105 submodel = _FakeSubmodel("Q")
106 _use_cell(step, submodel, TEMPORARY)
107
108 derive_load_store_compute_flag([step])
109
110 active = _active(step)
111 assert submodel.generator.load_store_compute_flag == _flag(active, "false", "false")
112
113
115 """One Step reads, a different Step (elsewhere) writes the same
116 submodel: use has both, load only the reader's term, store only the
117 writer's term."""
118 reader = _make_step("TimeStep_Reader")
119 writer = _make_step("TimeStep_Writer")
120 submodel = _FakeSubmodel("Q")
121 _use_cell(reader, submodel, READ_AND_DISCARD)
122 _use_cell(writer, submodel, WRITE)
123
124 derive_load_store_compute_flag([reader, writer])
125
126 active_reader = _active(reader)
127 active_writer = _active(writer)
128 assert submodel.generator.load_store_compute_flag == _flag(
129 f"{active_reader} or {active_writer}", active_reader, active_writer
130 )
131
132
134 writer = _make_step("SetupSimulation_InitialCondition")
135 reader = _make_step("TimeStep_Reconstruction")
136 submodel = _FakeSubmodel("Q")
137 _use_cell(writer, submodel, WRITE)
138 _use_cell(reader, submodel, READ_AND_DISCARD)
139
140 derive_load_store_compute_flag([writer, reader])
141
142 active_writer = _active(writer)
143 active_reader = _active(reader)
144 assert submodel.generator.load_store_compute_flag == _flag(
145 f"{active_writer} or {active_reader}", active_reader, active_writer
146 )
147
148
150 step = _make_step("TimeStep_Step")
151 cell_submodel = _FakeSubmodel("Cell")
152 face_submodel = _FakeSubmodel("Face")
153 vertex_submodel = _FakeSubmodel("Vertex")
154 _use_cell(step, cell_submodel, WRITE)
155 _use_face(step, face_submodel, READ_AND_DISCARD)
156 _use_vertex(step, vertex_submodel, READ_AND_WRITE)
157
158 derive_load_store_compute_flag([step])
159
160 active = _active(step)
161 assert cell_submodel.generator.load_store_compute_flag == _flag(active, "false", active)
162 assert face_submodel.generator.load_store_compute_flag == _flag(active, active, "false")
163 assert vertex_submodel.generator.load_store_compute_flag == _flag(active, active, active)
164
165
167 step = _make_step("TimeStep_Step")
168 used_submodel = _FakeSubmodel("Used")
169 unused_submodel = _FakeSubmodel("Unused")
170 _use_cell(step, used_submodel, WRITE)
171
172 derive_load_store_compute_flag([step])
173
174 assert used_submodel.generator.load_store_compute_flag is not None
175 assert unused_submodel.generator.load_store_compute_flag is None
176
177
179 """A submodel's generator starts out at the factory default (never
180 customised by anyone) - the derived flag should replace it outright,
181 not get AND-combined with it."""
182 step = _make_step("TimeStep_Step")
183 submodel = _FakeSubmodel("Q")
184 submodel.generator.load_store_compute_flag = _DEFAULT_LOAD_STORE_COMPUTE_FLAG
185 _use_cell(step, submodel, WRITE)
186
187 derive_load_store_compute_flag([step])
188
189 active = _active(step)
190 assert submodel.generator.load_store_compute_flag == _flag(active, "false", active)
191
192
194 """A task graph author (or an earlier call to this function) already
195 set a custom load_store_compute_flag - the newly derived expression
196 must be AND-combined with it, existing first, new one parenthesised."""
197 step = _make_step("TimeStep_Step")
198 submodel = _FakeSubmodel("Q")
199 submodel.generator.load_store_compute_flag = "someCustomExpression"
200 _use_cell(step, submodel, WRITE)
201
202 derive_load_store_compute_flag([step])
203
204 active = _active(step)
205 new_flag = _flag(active, "false", active)
206 assert submodel.generator.load_store_compute_flag == f"someCustomExpression and ({new_flag})"
207
208
210 step = _make_step("TimeStep_Step")
211 submodel = _FakeSubmodel("Q")
212 _use_cell(step, submodel, WRITE)
213
214 derive_load_store_compute_flag([step])
215
216 assert '#include "repositories/StepRepository.h"' in submodel.generator.includes
217 assert '#include "repositories/SolverRepository.h"' in submodel.generator.includes
218 assert '#include "peano4/parallel/Node.h"' in submodel.generator.includes
219
220
222 step = _make_step("TimeStep_Step")
223 used_submodel = _FakeSubmodel("Used")
224 unused_submodel = _FakeSubmodel("Unused")
225 _use_cell(step, used_submodel, WRITE)
226
227 derive_load_store_compute_flag([step])
228
229 assert unused_submodel.generator.includes == ""
230
231
233 step = _make_step("TimeStep_Step")
234 submodel = _FakeSubmodel("Q")
235 _use_cell(step, submodel, WRITE)
236
237 derive_load_store_compute_flag([step])
238 derive_load_store_compute_flag([step])
239
240 assert submodel.generator.includes.count('#include "repositories/StepRepository.h"') == 1
241 assert submodel.generator.includes.count('#include "repositories/SolverRepository.h"') == 1
242 assert submodel.generator.includes.count('#include "peano4/parallel/Node.h"') == 1
243
244
246 """Stand-in for a peano4.api.toolbox.GridSelector with one distinct
247 guard per kind, so tests can tell which routine was used."""
248
250 return "cellGuard"
251
253 return "faceGuard"
254
256 return "vertexGuard"
257
258
260 writer = _make_step("TimeStep_Writer")
261 reader = _make_step("TimeStep_Reader")
262 submodel = _FakeSubmodel("Q")
263 submodel.grid_selector = _FakeGridSelector()
264 _use_cell(writer, submodel, WRITE)
265 _use_cell(reader, submodel, READ_AND_DISCARD)
266
267 derive_load_store_compute_flag([writer, reader])
268
269 active_writer = _active(writer)
270 active_reader = _active(reader)
271 assert submodel.generator.load_store_compute_flag == _flag(
272 f"(cellGuard) and ({active_writer} or {active_reader})",
273 f"(cellGuard) and ({active_reader})",
274 f"(cellGuard) and ({active_writer})",
275 )
276
277
279 step = _make_step("TimeStep_Step")
280 submodel = _FakeSubmodel("Q")
281 submodel.grid_selector = _FakeGridSelector()
282 _use_cell(step, submodel, TEMPORARY)
283
284 derive_load_store_compute_flag([step])
285
286 active = _active(step)
287 assert submodel.generator.load_store_compute_flag == _flag(
288 f"(cellGuard) and ({active})", "(cellGuard) and (false)", "(cellGuard) and (false)"
289 )
290
291
293 step = _make_step("TimeStep_Step")
294 cell_submodel = _FakeSubmodel("Cell")
295 face_submodel = _FakeSubmodel("Face")
296 vertex_submodel = _FakeSubmodel("Vertex")
297 for submodel in (cell_submodel, face_submodel, vertex_submodel):
298 submodel.grid_selector = _FakeGridSelector()
299 _use_cell(step, cell_submodel, READ_AND_WRITE)
300 _use_face(step, face_submodel, READ_AND_WRITE)
301 _use_vertex(step, vertex_submodel, READ_AND_WRITE)
302
303 derive_load_store_compute_flag([step])
304
305 active = _active(step)
306 for submodel, guard in (
307 (cell_submodel, "cellGuard"),
308 (face_submodel, "faceGuard"),
309 (vertex_submodel, "vertexGuard"),
310 ):
311 predicate = f"({guard}) and ({active})"
312 assert submodel.generator.load_store_compute_flag == _flag(predicate, predicate, predicate)
313
314
316 step = _make_step("TimeStep_Step")
317 submodel = _FakeSubmodel("Q")
318 submodel.grid_selector = None
319 _use_cell(step, submodel, READ_AND_WRITE)
320
321 derive_load_store_compute_flag([step])
322
323 active = _active(step)
324 assert submodel.generator.load_store_compute_flag == _flag(active, active, active)
325
326
328 """End-to-end with the real classes: a peano4.api.datamodel.Patch
329 carrying a peano4.api.toolbox.FineGridSelector."""
331 import peano4.api.toolbox
332
333 step = _make_step("TimeStep_Step")
334 patch = peano4.api.datamodel.Patch((3, 3, 3), 1, "Q")
335 patch.grid_selector = peano4.api.toolbox.FineGridSelector()
336 _use_cell(step, patch, READ_AND_WRITE)
337
338 derive_load_store_compute_flag([step])
339
340 predicate = f"(not marker.hasBeenRefined()) and ({_active(step)})"
341 store_predicate = f"(not marker.willBeRefined()) and ({_active(step)})"
342 assert patch.generator.load_store_compute_flag == _flag(predicate, predicate, store_predicate)
343
344
346 """A selector without its own store guard stores whenever it loads."""
348 import peano4.api.toolbox
349
350 class _Selector(peano4.api.toolbox.GridSelector):
351 def createVertexGuard(self):
352 return "vertexGuard"
353
354 def createFaceGuard(self):
355 return "faceGuard"
356
357 def createCellGuard(self):
358 return "cellGuard"
359
360 step = _make_step("TimeStep_Step")
361 patch = peano4.api.datamodel.Patch((3, 3, 3), 1, "Q")
362 patch.grid_selector = _Selector()
363 _use_cell(step, patch, READ_AND_WRITE)
364
365 derive_load_store_compute_flag([step])
366
367 predicate = f"(cellGuard) and ({_active(step)})"
368 assert patch.generator.load_store_compute_flag == _flag(predicate, predicate, predicate)
Patch implementation of a degree of freedom.
Definition Patch.py:7
Select a subset of the mesh entities.
Minimal stand-in for peano4.api.datamodel.PatchToDoubleArrayWithSmartPointer: derive_load_store_compu...
Stand-in for a peano4.api.toolbox.GridSelector with one distinct guard per kind, so tests can tell wh...
Minimal stand-in for a peano4.api.datamodel.Patch, with a generator attribute like the real thing has...
The Python-side model of "what happens during one mesh sweep".
Definition __init__.py:1
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1
test_store_guard_defaults_to_guard()
A selector without its own store guard stores whenever it loads.
str _active(step)
The exact "this Step is active" expression, for asserting against - built the same way the production...
test_fine_grid_selector_restricts_patch_to_unrefined_cells()
End-to-end with the real classes: a peano4.api.datamodel.Patch carrying a peano4.api....
test_factory_default_is_overwritten_not_combined()
A submodel's generator starts out at the factory default (never customised by anyone) - the derived f...
test_pre_existing_custom_expression_is_combined_with_and()
A task graph author (or an earlier call to this function) already set a custom load_store_compute_fla...
test_terms_from_different_steps_are_ored_together()
One Step reads, a different Step (elsewhere) writes the same submodel: use has both,...