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.
28output_files = [ f
for f
in os.listdir(
".")
if f.endswith(
".peano-patch-file") ]
46project.datamodel.add_cell(patch)
54project.datamodel.add_face(patch_overlap)
63create_grid.use_face(patch_overlap)
64create_grid.use_cell(patch)
66create_grid.add_action_set( toolbox.blockstructured.api.ProjectPatchOntoFaces(patch,patch_overlap) )
67project.solversteps.add_step(create_grid)
78print_solution.use_cell(patch)
79print_solution.use_face(patch_overlap)
80print_solution.remove_all_actions()
81plotter = toolbox.blockstructured.api.PlotPatchesInPeanoBlockFormat(
"solution",patch,
"Q")
82print_solution.add_action_set( plotter )
83project.solversteps.add_step(print_solution)
92perform_time_step.use_cell(patch)
93perform_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];
267perform_time_step.add_action_set( toolbox.blockstructured.api.ReconstructPatchAndApplyFunctor(patch,patch_overlap,functor,
"",
"") )
268perform_time_step.add_action_set( toolbox.blockstructured.api.ProjectPatchOntoFaces(patch,patch_overlap) )
270perform_time_step.add_action_set( plotter )
271project.solversteps.add_step(perform_time_step)
282project.output.makefile.parse_configure_script_outcome(
"../../.." )
283project.constants.export(
"PatchSize", patch_size )
284project.constants.export(
"NumberOfUnknownsPerCell", unknowns )
293project.generate(peano4.api.output.Overwrite.Default)
295success = project.run( [
"myarguments"] )
308 convert = tarch.plotter.api.Convert(
"solution" )
309 convert.set_visualisation_tools_path(
"/home/tobias/git/Peano/src/visualisation" )
310 convert.extract_fine_grid()
311 convert.convert_to_vtk()
Represents a Peano 4 project.
Patch implementation of a degree of freedom.
The Python-side model of "what happens during one mesh sweep".