Peano
Loading...
Searching...
No Matches
30_domain-decomposition.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
5Create the PNG illustrations of the tutorial 30_domain-decomposition.ipynb
6
7The script builds the tutorial's Euler setup with load balancing, runs it
8with four threads, converts the output into VTU files, and lets ParaView's
9pvbatch render the subdomains into 30_domain-decomposition-subdomains.png.
10It also renders the workflow diagram 30_domain-decomposition-workflow.dot
11with Graphviz. The implementation of EulerFV is taken from the tutorial's
12%%writefile cell. Call the script from anywhere:
13
14 python3 tutorials/exahype2/illustrations/30_domain-decomposition.py
15
16All builds and outputs go into a temporary directory (or --work-directory).
17The script needs Graphviz' dot and ParaView's pvbatch (--pvbatch).
18
19"""
20import argparse
21import json
22import os
23import subprocess
24import sys
25import tempfile
26
27Here = os.path.dirname(os.path.abspath(__file__))
28PeanoRoot = os.path.abspath(os.path.join(Here, "..", "..", ".."))
29sys.path.insert(0, os.path.join(PeanoRoot, "src"))
30
31import peano4.api
32import exahype2
33
34NumberOfThreads = 4
35SubdomainsPicture = os.path.join(Here, "30_domain-decomposition-subdomains.png")
36WorkflowDiagram = os.path.join(Here, "30_domain-decomposition-workflow")
37
38# Renders the first snapshot of the pvd file argv[1] into the PNG argv[2],
39# coloured by the subdomain number, i.e. the last component of the unknowns
40ParaViewScript = """
41import sys
42from paraview.simple import *
43
44reader = PVDReader(FileName=sys.argv[1])
45reader.UpdatePipeline(reader.TimestepValues[0] if reader.TimestepValues else 0.0)
46array_name = reader.CellData.keys()[0]
47data_range = reader.CellData[array_name].GetRange(-1)
48subdomain = reader.CellData[array_name].GetNumberOfComponents() - 1
49
50view = GetActiveViewOrCreate("RenderView")
51view.OrientationAxesVisibility = 0
52view.InteractionMode = "2D"
53view.Background = [1.0, 1.0, 1.0]
54view.UseColorPaletteForBackground = 0
55display = Show(reader, view)
56display.Representation = "Surface"
57# Flat colours which match the legend
58display.Ambient = 1.0
59display.Diffuse = 0.0
60ColorBy(display, ("CELLS", array_name))
61lut = GetColorTransferFunction(array_name)
62lut.VectorMode = "Component"
63lut.VectorComponent = subdomain
64subdomain_range = reader.CellData[array_name].GetRange(subdomain)
65subdomains = range(int(subdomain_range[0]), int(subdomain_range[1]) + 1)
66lut.InterpretValuesAsCategories = 1
67lut.Annotations = [item for number in subdomains for item in (str(number), str(number))]
68lut.ApplyPreset("Brewer Qualitative Set2", True)
69bar = GetScalarBar(lut, view)
70bar.Title = "subdomain"
71bar.ComponentTitle = ""
72bar.TitleColor = [0.0, 0.0, 0.0]
73bar.LabelColor = [0.0, 0.0, 0.0]
74display.SetScalarBarVisibility(view, True)
75view.ResetCamera()
76SaveScreenshot(sys.argv[2], view, ImageResolution=[800, 650])
77"""
78
79
81 """! Body of the tutorial's cell which writes EulerFV.cpp"""
82 with open(os.path.join(Here, "..", tutorial + ".ipynb")) as notebook_file:
83 cells = json.load(notebook_file)["cells"]
84 for cell in cells:
85 source = "".join(cell["source"])
86 if source.startswith("%%writefile " + tutorial + "/EulerFV.cpp"):
87 return source.split("\n", 1)[1]
88 raise Exception("tutorial {} has no cell writing EulerFV.cpp".format(tutorial))
89
90
92 directory,
93 peano_root,
94 tutorial="30_domain-decomposition",
95 namespace="domaindecomposition",
96 load_balancer="toolbox::loadbalancing::strategies::SpreadOutOnceGridStagnates",
97 load_balancer_arguments="new ::exahype2::LoadBalancingConfiguration()",
98):
99 """!
100
101 Generate, compile and run the Euler setup within directory
102
103 The defaults are the setup of 30_domain-decomposition.ipynb. Other
104 tutorials which build upon this setup pass in their own name, namespace
105 and load balancing.
106
107 """
108 project = exahype2.api.Project(
109 namespace=["tutorials", "exahype2", namespace],
110 project_name="Euler",
111 directory=directory,
112 executable="euler",
113 )
114
115 solver = exahype2.api.Solver("EulerFV", 4, 0)
116 solver.add_pde_term(exahype2.api.Flux(stateless=False))
117 solver.add_pde_term(exahype2.api.MaxEigenvalue(stateless=False))
118 solver.add_pde_term(exahype2.api.InitPointWisely(stateless=False))
119 solver.numerical_scheme = exahype2.api.fv.RusanovWithExplicitEuler(solver, 9)
120 solver.grid_construction = exahype2.api.fv.SetupSimulationOverRegularGrid(
121 solver, volume_size=0.001
122 )
123 solver.plotter = exahype2.api.fv.PlotAsVTKFile(
124 solver, first_plot_time_stamp=0.0, time_in_between_plots=0.01
125 )
126
127 project.add_solver(solver)
128 project.set_global_simulation_parameters(
129 dimensions=2,
130 offset=[-0.1, -0.1],
131 size=[0.2, 0.2],
132 min_end_time=0.02,
133 max_end_time=0.02,
134 periodic_BC=[True, True, True],
135 )
136 project.set_load_balancing(load_balancer, load_balancer_arguments)
137 project.set_Peano4_installation(peano_root, peano4.api.output.CompileMode.RELEASE)
138 project.generate_Peano4_project().generate()
139 with open(os.path.join(directory, "EulerFV.cpp"), "w") as implementation_file:
140 implementation_file.write(euler_implementation(tutorial))
141 subprocess.run(["make", "-j"], cwd=directory, check=True, stdout=subprocess.DEVNULL)
142 with open(os.path.join(directory, "run.log"), "w") as log_file:
143 subprocess.run(
144 ["./euler"],
145 cwd=directory,
146 check=True,
147 stdout=log_file,
148 env=dict(os.environ, OMP_NUM_THREADS=str(NumberOfThreads)),
149 )
150
151
152def render_subdomains(directory, pvbatch, picture=SubdomainsPicture):
153 """! Convert the output into VTU and let ParaView render the subdomains into picture"""
154 subprocess.run(
155 [
156 sys.executable,
157 os.path.join(PeanoRoot, "src", "tarch", "plotter", "api", "render.py"),
158 "solution-EulerFV.peano-patch-file",
159 ],
160 cwd=directory,
161 env=dict(os.environ, PYTHONPATH=os.path.join(PeanoRoot, "src")),
162 check=True,
163 stdout=subprocess.DEVNULL,
164 )
165 script = os.path.join(directory, "render-subdomains.py")
166 with open(script, "w") as script_file:
167 script_file.write(ParaViewScript)
168 if os.path.exists(picture):
169 os.remove(picture)
170 # pvbatch might crash when it shuts down, so we check for the picture
171 # rather than for the return code
172 subprocess.run(
173 [
174 pvbatch,
175 "--force-offscreen-rendering",
176 script,
177 os.path.join(directory, "solution-EulerFV.EulerFVQ.pvd"),
178 picture,
179 ],
180 cwd=directory,
181 )
182 if not os.path.exists(picture):
183 raise Exception("pvbatch did not write {}".format(picture))
184
185
187 subprocess.run(
188 ["dot", "-Tpng", "-Gdpi=100", WorkflowDiagram + ".dot", "-o", WorkflowDiagram + ".png"],
189 check=True,
190 )
191
192
193if __name__ == "__main__":
194 parser = argparse.ArgumentParser(
195 description="Create the PNGs of the tutorial 30_domain-decomposition.ipynb"
196 )
197 parser.add_argument(
198 "--work-directory",
199 default=None,
200 help="Directory for builds and outputs (default: temporary directory)",
201 )
202 parser.add_argument(
203 "--peano-root",
204 default=PeanoRoot,
205 help="Peano installation with the compiled libraries (default: repository holding this script)",
206 )
207 parser.add_argument("--pvbatch", default="pvbatch", help="ParaView's pvbatch executable")
208 args = parser.parse_args()
209
211 work_directory = args.work_directory or tempfile.mkdtemp(prefix="30_domain-decomposition-")
212 print("build and run in {}".format(work_directory))
213 build_and_run(work_directory, os.path.abspath(args.peano_root))
214 render_subdomains(work_directory, args.pvbatch)
215 print("wrote PNGs into {}".format(Here))
The conservative flux F(Q) of a hyperbolic PDE.
Definition Flux.py:8
Point-wise initial condition: given the physical position of a single degree of freedom,...
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
ExaHyPE 2 project.
Definition Project.py:15
Abstract base class for all ExaHyPE 2 solvers.
Definition Solver.py:17
Plotting counterpart to RusanovWithExplicitEuler: maps the patch data of a Finite Volume scheme with ...
Finite Volumes with a Rusanov Riemann solver and explicit Euler time stepping, realised over a block-...
Setup phase counterpart to RusanovWithExplicitEuler: sets the initial condition for a Finite Volume s...
build_and_run(directory, peano_root, tutorial="30_domain-decomposition", namespace="domaindecomposition", load_balancer="toolbox::loadbalancing::strategies::SpreadOutOnceGridStagnates", load_balancer_arguments="new ::exahype2::LoadBalancingConfiguration()")
Generate, compile and run the Euler setup within directory.
euler_implementation(tutorial)
Body of the tutorial's cell which writes EulerFV.cpp.
render_subdomains(directory, pvbatch, picture=SubdomainsPicture)
Convert the output into VTU and let ParaView render the subdomains into picture.