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. 
   18import peano4.datamodel
 
   19import peano4.solversteps
 
   21import peano4.visualisation
 
   28output_files = [ f 
for f 
in os.listdir(
".") 
if f.endswith(
".peano-patch-file") ]
 
   37project = peano4.Project( [
"examples", 
"finitevolumes"], 
"finitevolumes", 
"." )
 
   45patch = peano4.datamodel.Patch( (patch_size,patch_size,patch_size), unknowns, 
"Q" )
 
   46project.datamodel.add_cell(patch)
 
   53patch_overlap = peano4.datamodel.Patch( (2,patch_size,patch_size), unknowns, 
"Q" )
 
   54project.datamodel.add_face(patch_overlap)
 
   62create_grid = peano4.solversteps.Step( 
"CreateGrid" )
 
   63create_grid.use_face(patch_overlap)
 
   64create_grid.use_cell(patch)
 
   66create_grid.add_action_set( peano4.toolbox.blockstructured.ProjectPatchOntoFaces(patch,patch_overlap) )
 
   67project.solversteps.add_step(create_grid)
 
   77print_solution = peano4.solversteps.Step( 
"PlotSolution" )
 
   78print_solution.use_cell(patch)
 
   79print_solution.use_face(patch_overlap)
 
   80print_solution.remove_all_actions()
 
   81plotter = peano4.toolbox.blockstructured.PlotPatchesInPeanoBlockFormat(
"solution",patch,
"Q")
 
   82print_solution.add_action_set( plotter )
 
   83project.solversteps.add_step(print_solution)
 
   91perform_time_step      = peano4.solversteps.Step( 
"TimeStep" )
 
   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( peano4.toolbox.blockstructured.ReconstructPatchAndApplyFunctor(patch,patch_overlap,functor,
"",
"") )
 
  268perform_time_step.add_action_set( peano4.toolbox.blockstructured.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.output.Overwrite.Default)
 
  295success = 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()