Peano
Loading...
Searching...
No Matches
fuse-steps-illustrations.py
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"""!
4
5Generate the illustrations of peano4.api.taskgraph.compiler.FuseSteps
6
7Run from the repository root via
8
9~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10PYTHONPATH=src python3 src/peano4/api/taskgraph/compiler/fuse-steps-illustrations.py
11~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
13The script builds a few small task graphs, compiles them with
14peano4.api.taskgraph.compiler.FuseSteps.translate(), and writes one PNG per
15example next to this script: the input task graph (as drawn by
16peano4.api.taskgraph.Graph.visualise()) on the left, the compiled sequence
17of mesh traversals (as drawn by
18peano4.api.taskgraph.compiler.ReportCompiledStepSequence) on the right. The
19PNGs are referenced from the documentation of FuseSteps.translate().
20
21"""
22import io
23import os
24
25import matplotlib
26
27matplotlib.use("Agg")
28import matplotlib.pyplot as plt
29from PIL import Image
30
31from peano4.api.taskgraph import Graph, Task
32from peano4.api.taskgraph.compiler import FuseSteps
34 _visualise_compiled_step_sequence,
35)
36
37
39 """Minimal stand-in for an action set: the illustrations only need a name"""
40
41 def __init__(self, name):
42 self.name = name
44 self.parallel = False
45
47 return self.name
48
49
51 """Minimal stand-in for a submodel: the illustrations only need a name"""
52
53 def __init__(self, name):
54 self.name = name
55
56
57def _task(name, entity, *action_set_names):
58 task = Task(name=name, entity=entity)
59 for action_set_name in action_set_names:
60 task.add_action_set(_IllustrationActionSet(action_set_name))
61 return task
62
63
64def _render_current_figure() -> Image.Image:
65 buffer = io.BytesIO()
66 plt.gcf().savefig(buffer, format="png", dpi=110)
67 plt.close(plt.gcf())
68 buffer.seek(0)
69 return Image.open(buffer).convert("RGB")
70
71
72def _write_illustration(graph: Graph, title: str, file_name: str):
73 graph.visualise(title=f"{title}: task graph")
74 graph_image = _render_current_figure()
75
76 steps = FuseSteps.translate(graph, "Example", None)
77 _visualise_compiled_step_sequence(steps, f"{title}: fused mesh traversals")
78 steps_image = _render_current_figure()
79
80 height = max(graph_image.height, steps_image.height)
81 result = Image.new("RGB", (graph_image.width + steps_image.width, height), "white")
82 result.paste(graph_image, (0, 0))
83 result.paste(steps_image, (graph_image.width, 0))
84 result.save(os.path.join(os.path.dirname(os.path.abspath(__file__)), file_name))
85
86
87def entity_order_example() -> Graph:
88 graph = Graph()
89 tasks = [
90 _task("a", Task.GridEntity.VERTEX, "A"),
91 _task("b", Task.GridEntity.FACE, "B"),
92 _task("c", Task.GridEntity.CELL, "C"),
93 _task("d", Task.GridEntity.VERTEX, "D"),
94 _task("e", Task.GridEntity.CELL, "E"),
95 ]
96 for previous_task, task in zip(tasks, tasks[1:]):
97 task.add_dependency(previous_task)
98 for task in tasks:
99 graph.add_task(task)
100 return graph
101
102
103def parallel_example() -> Graph:
104 graph = Graph()
105 vertex_task_1 = _task("v1", Task.GridEntity.VERTEX, "V1")
106 vertex_task_2 = _task("v2", Task.GridEntity.VERTEX, "V2")
107 cell_task_1 = _task("c1", Task.GridEntity.CELL, "C1")
108 cell_task_2 = _task("c2", Task.GridEntity.CELL, "C2")
109 final_task = _task("c3", Task.GridEntity.CELL, "C3a", "C3b")
110 cell_task_1.add_dependency(vertex_task_1)
111 cell_task_2.add_dependency(vertex_task_2)
112 final_task.add_dependency(cell_task_1)
113 final_task.add_dependency(cell_task_2)
114 for task in (vertex_task_1, vertex_task_2, cell_task_1, cell_task_2, final_task):
115 graph.add_task(task)
116 return graph
117
118
120 patch = _IllustrationSubmodel("Q")
121 patch_with_halo = _IllustrationSubmodel("QWithHalo")
122 face_data = _IllustrationSubmodel("QFace")
123
124 graph = Graph()
125 reconstruct = _task("Reconstruct", Task.GridEntity.CELL, "ReconstructPatchWithHalo")
126 update = _task("Update cell", Task.GridEntity.CELL, "UpdateCell")
127 project = _task("Project on faces", Task.GridEntity.CELL, "ProjectPatchOntoFaces")
128 update.add_dependency(reconstruct)
129 project.add_dependency(update)
130
131 reconstruct.use_cell(patch, Task.DataAccess.READ_AND_WRITE)
132 reconstruct.use_cell(patch_with_halo, Task.DataAccess.WRITE)
133 reconstruct.use_face(face_data, Task.DataAccess.READ_AND_DISCARD)
134 update.use_cell(patch_with_halo, Task.DataAccess.READ_AND_DISCARD)
135 update.use_cell(patch, Task.DataAccess.WRITE)
136 project.use_cell(patch, Task.DataAccess.READ_AND_WRITE)
137 project.use_face(face_data, Task.DataAccess.WRITE)
138
139 for task in (reconstruct, update, project):
140 graph.add_task(task)
141 return graph
142
143
145 patch = _IllustrationSubmodel("Q")
146 patch_with_halo = _IllustrationSubmodel("QWithHalo")
147 face_data = _IllustrationSubmodel("QFace")
148
149 graph = Graph()
150 boundary = _task("Apply BCs", Task.GridEntity.FACE, "ApplyBoundaryConditions")
151 reconstruct = _task("Reconstruct", Task.GridEntity.CELL, "ReconstructPatchWithHalo")
152 update = _task("Update cell", Task.GridEntity.CELL, "UpdateCell")
153 reconstruct.add_dependency(boundary)
154 update.add_dependency(reconstruct)
155
156 boundary.use_face(face_data, Task.DataAccess.READ_AND_WRITE)
157 reconstruct.use_cell(patch, Task.DataAccess.READ_AND_WRITE)
158 reconstruct.use_cell(patch_with_halo, Task.DataAccess.WRITE)
159 reconstruct.use_face(face_data, Task.DataAccess.READ_AND_DISCARD)
160 update.use_cell(patch_with_halo, Task.DataAccess.READ_AND_DISCARD)
161 update.use_cell(patch, Task.DataAccess.WRITE)
162
163 for task in (boundary, reconstruct, update):
164 graph.add_task(task)
165 return graph
166
167
168if __name__ == "__main__":
170 entity_order_example(), "Entity order", "fuse-steps-entity-order.png"
171 )
172 _write_illustration(parallel_example(), "Parallel tasks", "fuse-steps-parallel.png")
174 data_conflict_example(), "Conflicting face data", "fuse-steps-data-conflict.png"
175 )
178 "Face task before cell task",
179 "fuse-steps-face-before-cell.png",
180 )
Holds a sequence of Task instances.
Definition Graph.py:9
One task within a peano4.api.taskgraph.Graph.
Definition Task.py:8
Minimal stand-in for an action set: the illustrations only need a name.
Minimal stand-in for a submodel: the illustrations only need a name.
Compilers are simple functions.
Definition __init__.py:1
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1