3 A very simple example which demonstrates how to configure a patch-based
4 Finite Volume solver in Peano4. The code relies on snippets from ExaHyPE2.
5 However, it relies only on ExaHyPE's C/FORTRAN compute kernels, i.e. the
6 sophisticated build environment of this H2020 project is not used. The
7 solver simulates the simple Euler equations.
18 import peano4.datamodel
19 import peano4.solversteps
21 import peano4.visualisation
28 output_files = [ f
for f
in os.listdir(
".")
if f.endswith(
".peano-patch-file") ]
29 for f
in output_files:
37 project = peano4.Project( [
"examples",
"finitevolumes"],
"finitevolumes",
"." )
45 patch = peano4.datamodel.Patch( (patch_size,patch_size,patch_size), unknowns,
"Q" )
46 project.datamodel.add_cell(patch)
53 patch_overlap = peano4.datamodel.Patch( (2,patch_size,patch_size), unknowns,
"Q" )
54 project.datamodel.add_face(patch_overlap)
62 create_grid = peano4.solversteps.Step(
"CreateGrid" )
63 create_grid.use_face(patch_overlap)
64 create_grid.use_cell(patch)
66 create_grid.add_action_set( peano4.toolbox.blockstructured.ProjectPatchOntoFaces(patch,patch_overlap) )
67 project.solversteps.add_step(create_grid)
77 print_solution = peano4.solversteps.Step(
"PlotSolution" )
78 print_solution.use_cell(patch)
79 print_solution.use_face(patch_overlap)
80 print_solution.remove_all_actions()
81 plotter = peano4.toolbox.blockstructured.PlotPatchesInPeanoBlockFormat(
"solution",patch,
"Q")
82 print_solution.add_action_set( plotter )
83 project.solversteps.add_step(print_solution)
91 perform_time_step = peano4.solversteps.Step(
"TimeStep" )
92 perform_time_step.use_cell(patch)
93 perform_time_step.use_face(patch_overlap)
96 auto eigenvalues = [](double Q[5], const tarch::la::Vector<DIMENSIONS,double>& x, int normal, double lambda[5]) -> void {
97 constexpr double gamma = 1.4;
98 const double irho = 1./Q[0];
100 const double p = (gamma-1) * (Q[4] - 0.5*irho*Q[1]*Q[1]+Q[2]*Q[2]+Q[3]*Q[3]);
102 const double p = (gamma-1) * (Q[4] - 0.5*irho*Q[1]*Q[1]+Q[2]*Q[2]);
105 const double u_n = Q[normal + 1] * irho;
106 assertion10( gamma * p * irho>=0.0, gamma, p, irho, x, normal, Q[0], Q[1], Q[2], Q[3], Q[4] );
107 const double c = std::sqrt(gamma * p * irho);
115 assertion4( lambda[0]==lambda[0], u_n, c, x, normal );
116 assertion4( lambda[1]==lambda[1], u_n, c, x, normal );
117 assertion4( lambda[2]==lambda[2], u_n, c, x, normal );
118 assertion4( lambda[3]==lambda[3], u_n, c, x, normal );
119 assertion4( lambda[4]==lambda[4], u_n, c, x, normal );
122 auto flux = [](double Q[5], const tarch::la::Vector<DIMENSIONS,double>& x, int normal, double F[5]) -> void {
123 assertion5( Q[0]==Q[0], Q[0], Q[1], Q[2], Q[3], Q[4] );
124 assertion5( Q[1]==Q[1], Q[0], Q[1], Q[2], Q[3], Q[4] );
125 assertion5( Q[2]==Q[2], Q[0], Q[1], Q[2], Q[3], Q[4] );
126 assertion5( Q[3]==Q[3], Q[0], Q[1], Q[2], Q[3], Q[4] );
127 assertion5( Q[4]==Q[4], Q[0], Q[1], Q[2], Q[3], Q[4] );
129 assertion5( Q[0]>1e-12, Q[0], Q[1], Q[2], Q[3], Q[4] );
130 constexpr double gamma = 1.4;
131 const double irho = 1./Q[0];
133 const double p = (gamma-1) * (Q[4] - 0.5*irho*Q[1]*Q[1]+Q[2]*Q[2]+Q[3]*Q[3]);
135 const double p = (gamma-1) * (Q[4] - 0.5*irho*Q[1]*Q[1]+Q[2]*Q[2]);
142 F[1] = irho*Q[1]*Q[1] + p;
143 F[2] = irho*Q[2]*Q[1];
144 F[3] = (DIMENSIONS==3) ? irho*Q[3]*Q[1] : 0.0;
145 F[4] = irho*(Q[4]+p)*Q[1];
151 F[1] = irho*Q[1]*Q[2];
152 F[2] = irho*Q[2]*Q[2] + p;
153 F[3] = (DIMENSIONS==3) ? irho*Q[3]*Q[2] : 0.0;
154 F[4] = irho*(Q[4]+p)*Q[2];
160 F[1] = irho*Q[1]*Q[3];
161 F[2] = irho*Q[2]*Q[3];
162 F[3] = (DIMENSIONS==3) ? irho*Q[3]*Q[3] + p : 0.0;
163 F[4] = irho*(Q[4]+p)*Q[3];
168 assertion( F[0]==F[0] );
169 assertion( F[1]==F[1] );
170 assertion( F[2]==F[2] );
171 assertion( F[3]==F[3] );
172 assertion( F[4]==F[4] );
175 auto splitRiemann1d = [&flux, &eigenvalues](double QL[5], double QR[5], const tarch::la::Vector<DIMENSIONS,double>& x, double dx, double dt, int normal, double F[5]) -> void {{
177 for (int unknown=0; unknown<5; unknown++) {{
178 averageQ[unknown] = 0.5 * (QL[unknown] + QR[unknown]);
179 assertion4(averageQ[unknown]==averageQ[unknown], x, dx, dt, normal);
184 flux(averageQ,x,normal,averageF);
186 double lambdaMax = 0.0;
187 eigenvalues(averageQ,x,normal,lambdas);
188 for (int unknown=0; unknown<5; unknown++) {{
189 assertion(lambdas[unknown]==lambdas[unknown]);
190 lambdaMax = std::max(lambdaMax,lambdas[unknown]);
193 for (int unknown=0; unknown<5; unknown++) {{
194 assertion( QR[unknown]==QR[unknown] );
195 assertion( QL[unknown]==QL[unknown] );
196 F[unknown] = averageF[unknown] - 0.5 * lambdaMax * (QR[unknown] - QL[unknown]);
197 assertion9( F[unknown]==F[unknown], averageF[unknown], lambdas[unknown], QR[unknown], QL[unknown], unknown, x, dx, dt, normal );
201 constexpr int PatchSize = 13;
202 constexpr int HaloSize = 1;
204 double dx = marker.h()(0) / PatchSize;
205 assertion( dx>=tarch::la::NUMERICAL_ZERO_DIFFERENCE );
206 dfor(cell,PatchSize) {{ // DOFS_PER_AXIS
207 tarch::la::Vector<DIMENSIONS,double> voxelCentre = marker.x()
208 - static_cast<double>((PatchSize/2+HaloSize)) * tarch::la::Vector<DIMENSIONS,double>(dx)
209 + tarch::la::multiplyComponents(cell.convertScalar<double>(), tarch::la::Vector<DIMENSIONS,double>(dx));
211 tarch::la::Vector<DIMENSIONS,int> currentVoxel = cell + tarch::la::Vector<DIMENSIONS,int>(HaloSize); // OVERLAP / Halo layer size
212 int currentVoxelSerialised = peano4::utils::dLinearised(currentVoxel,PatchSize + 2*HaloSize);
214 double accumulatedNumericalFlux[] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
215 double numericalFlux[5];
216 for (int d=0; d<DIMENSIONS; d++) {
217 tarch::la::Vector<DIMENSIONS,int> neighbourVoxel = currentVoxel;
218 tarch::la::Vector<DIMENSIONS,double> x = voxelCentre;
220 neighbourVoxel(d) -= 1;
221 int neighbourVoxelSerialised = peano4::utils::dLinearised(neighbourVoxel,PatchSize + 2*HaloSize);
223 assertion(neighbourVoxel(d)>=0);
226 oldQWithHalo + neighbourVoxelSerialised*5,
227 oldQWithHalo + currentVoxelSerialised*5,
231 for (int unknown=0; unknown<5; unknown++) {
232 //accumulatedNumericalFlux[unknown] -= numericalFlux[unknown];
233 accumulatedNumericalFlux[unknown] += numericalFlux[unknown];
234 assertion( numericalFlux[unknown]==numericalFlux[unknown] );
235 assertion( accumulatedNumericalFlux[unknown]==accumulatedNumericalFlux[unknown] );
238 neighbourVoxel(d) += 2;
239 neighbourVoxelSerialised = peano4::utils::dLinearised(neighbourVoxel,PatchSize + 2*HaloSize);
243 oldQWithHalo + currentVoxelSerialised*5,
244 oldQWithHalo + neighbourVoxelSerialised*5,
248 for (int unknown=0; unknown<5; unknown++) {
249 //accumulatedNumericalFlux[unknown] += numericalFlux[unknown];
250 accumulatedNumericalFlux[unknown] -= numericalFlux[unknown];
251 assertion( numericalFlux[unknown]==numericalFlux[unknown] );
252 assertion( accumulatedNumericalFlux[unknown]==accumulatedNumericalFlux[unknown] );
256 int destinationVoxelSerialised = peano4::utils::dLinearised(cell,PatchSize);
258 for (int unknown=0; unknown<5; unknown++) {{
259 assertion( originalPatch[ destinationVoxelSerialised*5+unknown ]==originalPatch[ destinationVoxelSerialised*5+unknown ] );
260 assertion( accumulatedNumericalFlux[unknown]==accumulatedNumericalFlux[unknown] );
261 originalPatch[ destinationVoxelSerialised*5+unknown ] += dt / dx * accumulatedNumericalFlux[unknown];
267 perform_time_step.add_action_set( peano4.toolbox.blockstructured.ReconstructPatchAndApplyFunctor(patch,patch_overlap,functor,
"",
"") )
268 perform_time_step.add_action_set( peano4.toolbox.blockstructured.ProjectPatchOntoFaces(patch,patch_overlap) )
270 perform_time_step.add_action_set( plotter )
271 project.solversteps.add_step(perform_time_step)
282 project.output.makefile.parse_configure_script_outcome(
"../../.." )
283 project.constants.export(
"PatchSize", patch_size )
284 project.constants.export(
"NumberOfUnknownsPerCell", unknowns )
293 project.generate(peano4.output.Overwrite.Default)
295 success = project.run( [
"myarguments"] )
308 convert = peano4.visualisation.Convert(
"solution" )
309 convert.set_visualisation_tools_path(
"/home/tobias/git/Peano/src/visualisation" )
310 convert.extract_fine_grid()
311 convert.convert_to_vtk()