97def test_face_data_read_then_written_prevents_fusion():
98 """The reconstruction/projection pattern of a Finite Volume time step"""
99 graph, tasks = _chain(CELL, CELL, CELL)
100 face_data = _FakeSubmodel("F")
101 tasks[0].use_face(face_data, READ_AND_DISCARD)
102 tasks[2].use_face(face_data, WRITE)
103 assert _step_names(graph) == ["S_T0__T1", "S_T2"]
106def test_vertex_data_written_twice_prevents_fusion():
107 graph, tasks = _chain(CELL, CELL)
108 vertex_data = _FakeSubmodel("V")
109 tasks[0].use_vertex(vertex_data, WRITE)
110 tasks[1].use_vertex(vertex_data, WRITE)
111 assert _step_names(graph) == ["S_T0", "S_T1"]
114def test_face_data_read_twice_or_temporary_does_not_prevent_fusion():
115 graph, tasks = _chain(CELL, CELL, CELL)
116 face_data = _FakeSubmodel("F")
117 tasks[0].use_face(face_data, READ_AND_DISCARD)
118 tasks[1].use_face(face_data, READ_AND_DISCARD)
119 tasks[2].use_face(face_data, TEMPORARY)
120 assert _step_names(graph) == ["S_T0__T1__T2"]
123def test_independent_tasks_form_one_parallel_node():
125 first, second = Task("a", VERTEX), Task("b", CELL)
126 for task in (first, second):
127 task.add_action_set(_FakeActionSet(task.name))
129 steps = FuseSteps.translate(graph, "S", None)
130 assert [step.name for step in steps] == ["S_A__B"]
131 assert _groups(steps[0]) == [["a", "b"]]
132 assert all(action_set.parallel for action_set in steps[0].action_sets)
135def test_independent_tasks_with_conflicting_data_are_not_parallel():
137 first, second = Task("a", CELL), Task("b", CELL)
138 face_data = _FakeSubmodel("F")
139 first.use_face(face_data, WRITE)
140 second.use_face(face_data, READ_AND_DISCARD)
141 for task in (first, second):
142 task.add_action_set(_FakeActionSet(task.name))
144 steps = FuseSteps.translate(graph, "S", None)
145 assert [step.name for step in steps] == ["S_A", "S_B"]
147 action_set.parallel for step in steps for action_set in step.action_sets
151def test_independent_tasks_with_conflicting_cell_data_are_fused_but_not_parallel():
153 first, second, third = Task("a", CELL), Task("b", CELL), Task("c", CELL)
154 cell_data = _FakeSubmodel("Q")
155 first.use_cell(cell_data, READ_AND_WRITE)
156 second.use_cell(cell_data, READ_AND_WRITE)
157 third.use_cell(cell_data, READ_AND_DISCARD)
158 for task in (first, second, third):
159 task.add_action_set(_FakeActionSet(task.name))
161 steps = FuseSteps.translate(graph, "S", None)
162 assert [step.name for step in steps] == ["S_A__B__C"]
163 assert _groups(steps[0]) == [["a"], ["b"], ["c"]]
164 assert not any(action_set.parallel for action_set in steps[0].action_sets)
167def test_independent_tasks_reading_the_same_cell_data_are_parallel():
169 first, second = Task("a", CELL), Task("b", CELL)
170 cell_data = _FakeSubmodel("Q")
171 first.use_cell(cell_data, READ_AND_DISCARD)
172 second.use_cell(cell_data, READ_AND_DISCARD)
173 for task in (first, second):
174 task.add_action_set(_FakeActionSet(task.name))
176 steps = FuseSteps.translate(graph, "S", None)
177 assert _groups(steps[0]) == [["a", "b"]]
180def test_adjacent_parallel_nodes_are_separated_by_a_synchronisation_marker():
188 c1.add_dependency(v1)
189 c2.add_dependency(v2)
190 for task in (v1, v2, c1, c2):
191 task.add_action_set(_FakeActionSet(task.name))
193 steps = FuseSteps.translate(graph, "S", None)
194 assert [step.name for step in steps] == ["S_V1__V2__C1__C2"]
195 assert [type(action_set) for action_set in steps[0].action_sets].count(
196 SynchroniseActionSets
198 assert isinstance(steps[0].action_sets[2], SynchroniseActionSets)
199 assert _groups(steps[0]) == [["v1", "v2"], ["c1", "c2"]]
202def test_task_with_several_action_sets_is_never_part_of_a_parallel_node():
204 first, second = Task("a", CELL), Task("b", CELL)
205 first.add_action_set(_FakeActionSet("a1"))
206 first.add_action_set(_FakeActionSet("a2"))
207 second.add_action_set(_FakeActionSet("b"))
208 graph.add_task(first)
209 graph.add_task(second)
210 steps = FuseSteps.translate(graph, "S", None)
211 assert [step.name for step in steps] == ["S_A__B"]
212 assert not any(action_set.parallel for action_set in steps[0].action_sets)
213 assert _groups(steps[0]) == [["a1"], ["a2"], ["b"]]
216def test_face_task_writing_face_data_fuses_with_subsequent_cell_task():
217 """Faces are touched for the first time before their adjacent cells, e.g. boundary conditions before a reconstruction"""
218 graph, tasks = _chain(FACE, CELL)
219 face_data = _FakeSubmodel("F")
220 tasks[0].use_face(face_data, READ_AND_WRITE)
221 tasks[1].use_face(face_data, READ_AND_DISCARD)
222 assert _step_names(graph) == ["S_T0__T1"]
225def test_face_task_reading_face_data_fuses_with_subsequent_cell_task_writing_it():
226 graph, tasks = _chain(FACE, CELL)
227 face_data = _FakeSubmodel("F")
228 tasks[0].use_face(face_data, READ_AND_DISCARD)
229 tasks[1].use_face(face_data, WRITE)
230 assert _step_names(graph) == ["S_T0__T1"]
233def test_face_tasks_with_conflicting_face_data_are_fused_but_not_parallel():
235 first, second = Task("a", FACE), Task("b", FACE)
236 face_data = _FakeSubmodel("F")
237 first.use_face(face_data, WRITE)
238 second.use_face(face_data, READ_AND_WRITE)
239 for task in (first, second):
240 task.add_action_set(_FakeActionSet(task.name))
242 steps = FuseSteps.translate(graph, "S", None)
243 assert [step.name for step in steps] == ["S_A__B"]
244 assert _groups(steps[0]) == [["a"], ["b"]]
245 assert not any(action_set.parallel for action_set in steps[0].action_sets)
248def test_cell_task_writing_face_data_is_not_fused_with_subsequent_face_task():
249 graph, tasks = _chain(CELL, FACE)
250 face_data = _FakeSubmodel("F")
251 tasks[0].use_face(face_data, WRITE)
252 tasks[1].use_face(face_data, READ_AND_DISCARD)
253 assert _step_names(graph) == ["S_T0", "S_T1"]
256def test_vertex_task_writing_vertex_data_fuses_with_subsequent_cell_task():
257 graph, tasks = _chain(VERTEX, CELL)
258 vertex_data = _FakeSubmodel("V")
259 tasks[0].use_vertex(vertex_data, WRITE)
260 tasks[1].use_vertex(vertex_data, READ_AND_DISCARD)
261 assert _step_names(graph) == ["S_T0__T1"]
264def test_face_task_writing_vertex_data_prevents_fusion():
265 """A vertex is adjacent to faces which are touched only after the cell"""
266 graph, tasks = _chain(FACE, CELL)
267 vertex_data = _FakeSubmodel("V")
268 tasks[0].use_vertex(vertex_data, WRITE)
269 tasks[1].use_vertex(vertex_data, READ_AND_DISCARD)
270 assert _step_names(graph) == ["S_T0", "S_T1"]