示例#1
0
def write_physical(output_dir, solver_name, n_dust):
    source_file = output_dir + 'Abstract' + solver_name + '_ADERDG.h'

    f = open(source_file, "r")
    lines = f.readlines()
    f.close()

    remove_function_body(lines, 'isPhysicallyAdmissible')

    body = ['  // Check if all quantities are finite\n']

    for i in range(0, 4 + 4 * n_dust):
        body.append(
            '  if (!std::isfinite(localDMPObservablesMin[{}])) return false;\n'
            .format(i))
        body.append(
            '  if (!std::isfinite(localDMPObservablesMax[{}])) return false;\n'
            .format(i))

    body.append('\n  // Check for positive densities\n')
    for i in range(0, n_dust + 1):
        body.append(
            '  if (localDMPObservablesMin[{}] <= 0.0) return false;\n'.format(
                4 * i))

    body.append('  return true;\n')

    add_function_body(lines, 'isPhysicallyAdmissible', body)

    # Write to file
    f = open(source_file, "w")
    f.writelines(lines)
    f.close()
示例#2
0
def write_plotter_gas_velocity(lines):
    remove_function_body(lines, 'mapQuantities')

    body = [
        '  const int writtenUnknowns = 3;\n',
        '  for (int i=0; i<writtenUnknowns; i++){\n',
        '    outputQuantities[i] = Q[i+1];\n', '  }\n'
    ]

    add_function_body(lines, 'mapQuantities', body)
示例#3
0
def write_plotter_dust_velocity(lines, n):
    remove_function_body(lines, 'mapQuantities')

    body = [
        '  const int writtenUnknowns = 3;\n',
        '  for (int i=0; i<writtenUnknowns; i++){\n',
        '    outputQuantities[i] = Q[i+1 + 4*{}];\n'.format(n + 1), '  }\n'
    ]

    add_function_body(lines, 'mapQuantities', body)
示例#4
0
def write_outflow_boundary(lines, n_vars, solver):
    # Remove current function body
    remove_function_body(lines, 'boundaryValues')

    periodic = ['  // Outflow boundaries, unimportant if periodic\n']

    if (solver == 'ADER-DG'):
        for n in range(0, n_vars):
            periodic.extend(['  stateOut[{}] = stateIn[{}];\n'.format(n, n)])
        for n in range(0, n_vars):
            periodic.extend(['  fluxOut[{}] = fluxIn[{}];\n'.format(n, n)])
    if (solver == 'Finite-Volumes'):
        for n in range(0, n_vars):
            periodic.extend(
                ['  stateOutside[{}] = stateInside[{}];\n'.format(n, n)])

    add_function_body(lines, 'boundaryValues', periodic)
示例#5
0
def write_periodic_functions(n_vars, order, offset, size, output_dir,
                             solver_name, n_ghost):
    fname = output_dir + solver_name + '.cpp'

    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    # Return if function already modified
    matches = [match for match in lines if "int n_cell_x = (int)" in match]
    if len(matches) > 0:
        return

    remove_function_body(lines, '::PlotPeriodic')

    body = \
      ['  //std::cout << "PLOT PERIODIC " << pos[0] << " " << pos[1] << std::endl;\n',
       '  // Fill a boundary array for setting periodic boundaries in 2D, non-AMR runs.\n',
       '  // If mesh = nx times ny, the first nx entries correspond to the bottom boundary.\n',
       '  // The second nx entries correspond to the top boundary.\n',
       '  // The next ny entries correspond to the left boundary.\n',
       '  // The next ny entries correspont to the right boundary.\n',
       '\n',
       '  // Hack: number of cells in x and y\n',
       '  int n_cell_x = (int) round({}/sizeOfPatch[0]);\n'.format(size[0]),
       '  int n_cell_y = (int) round({}/sizeOfPatch[1]);\n'.format(size[1]),
       '\n',
       '  // Make sure vector is of the correct size, and set elements to zero.\n',
       '  // Note that this should happen only the first time this function is called.\n',
       '  int n_bound_cells = 2*{}*(n_cell_x + n_cell_y);\n'.format(n_ghost),
       '  int n_send_per_cell = {};\n'.format(n_vars*(order+1)*(order+1)),
       '  if (boundaryVector_local.size() != n_send_per_cell*n_bound_cells) {\n',
       '    boundaryVector_local.resize(n_send_per_cell*n_bound_cells);\n',
       '    std::fill(boundaryVector_local.begin(), boundaryVector_local.end(), 0.0);\n',
       '  }\n',
       '\n',
       '  // Number of cells to left and bottom\n',
       '  int cell_x = (int) ((offsetOfPatch[0] + 0.5*sizeOfPatch[0])/sizeOfPatch[0]);\n',
       '  int cell_y = (int) ((offsetOfPatch[1] + 0.5*sizeOfPatch[1])/sizeOfPatch[1]);\n',
       '\n',
       '  int indx = -1;\n',
       '\n',
       '  for (int ng = 1; ng < {}; ng++) {{\n'.format(n_ghost + 1),
       '    if (cell_y == ng + {}) {{\n'.format(n_ghost - 1),
       '      indx = cell_x;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        boundaryVector_local[arr_index + n] = Q[n];\n',
       '    }\n',
       '    if (cell_y == n_cell_y - {} - ng) {{\n'.format(n_ghost),
       '      indx = n_cell_x + cell_x;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        boundaryVector_local[arr_index + n] = Q[n];\n',
       '    }\n',
       '    if (cell_x == ng + {}) {{\n'.format(n_ghost - 1),
       '      indx = 2*n_cell_x + cell_y;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        boundaryVector_local[arr_index + n] = Q[n];\n',
       '    }\n',
       '    if (cell_x == n_cell_x - {} - ng) {{\n'.format(n_ghost),
       '      indx = 2*n_cell_x + n_cell_y + cell_y;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        boundaryVector_local[arr_index + n] = Q[n];\n',
       '    }\n',
       '  }\n']

    add_function_body(lines, '::PlotPeriodic', body)

    remove_function_body(lines, '::SendPeriodic')

    body = \
      ['  //std::cout << "SENDING PERIODIC" << std::endl;\n',
       '#ifdef Parallel\n',
       '  // Should only happen the first time of call\n',
       '  if (boundaryVector.size() == 0) {\n',
       '    if (tarch::parallel::Node::getInstance().getNumberOfNodes() > 1) {\n',
       '      // Main rank does not know the boundary size\n',
       '      int s_loc = boundaryVector_local.size();\n',
       '      int s_max = 0;\n',
       '      MPI_Reduce(&s_loc, &s_max, 1, MPI_INT, MPI_MAX, 0,\n',
       '                 tarch::parallel::Node::getInstance().getCommunicator());\n',
       '      // Set correct size so we can use Allreduce\n',
       '      if (tarch::parallel::Node::getInstance().isGlobalMaster()) {\n',
       '        boundaryVector_local.resize(s_max);\n',
       '        std::fill(boundaryVector_local.begin(), boundaryVector_local.end(), 0.0);\n',
       '        boundaryVector.resize(s_max);\n',
       '      } else {\n',
       '        boundaryVector.resize(boundaryVector_local.size());\n',
       '      }\n',
       '    } else {\n',
       '      boundaryVector.resize(boundaryVector_local.size());\n',
       '    }\n',
       '  }\n',
       '  //std::cout << "Allreduce with rank " << tarch::parallel::Node::getInstance().getRank() << " and communicator " << tarch::parallel::Node::getInstance().getCommunicator() << std::endl;\n',
       '  MPI_Allreduce(&(boundaryVector_local[0]),\n',
       '                &(boundaryVector[0]),\n',
       '                boundaryVector_local.size(),\n',
       '                MPI_DOUBLE,\n',
       '                MPI_SUM,\n',
       '                tarch::parallel::Node::getInstance().getCommunicator());\n',
       '#else\n',
       '  boundaryVector = boundaryVector_local;\n',
       '#endif\n']

    add_function_body(lines, '::SendPeriodic', body)

    remove_function_body(lines, '::AdjustPeriodic')

    body = \
      ['  //std::cout << "ADJUSTPERIODIC " << pos[0] << " " << pos[1] << std::endl;\n',
       '  // Hack: number of cells in x and y\n',
       '  int n_cell_x = (int) round({}/sizeOfPatch[0]);\n'.format(size[0]),
       '  int n_cell_y = (int) round({}/sizeOfPatch[1]);\n'.format(size[1]),
       '\n',
       '  // Number of cells to left and bottom\n',
       '  int cell_x = (int) ((offsetOfPatch[0] + 0.5*sizeOfPatch[0])/sizeOfPatch[0]);\n',
       '  int cell_y = (int) ((offsetOfPatch[1] + 0.5*sizeOfPatch[1])/sizeOfPatch[1]);\n',
       '\n',
       '  int n_send_per_cell = {};\n'.format(n_vars*(order+1)*(order+1)),
       '  int indx = -1;\n',
       '\n',
       '  for (int ng = 1; ng < {}; ng++) {{\n'.format(n_ghost + 1),
       '    if (cell_y == n_cell_y - {} + ng - 1) {{\n'.format(n_ghost),
       '      indx = cell_x;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        Q[n] = boundaryVector[arr_index + n];\n',
       '    }\n',
       '    if (cell_y == {} - ng) {{\n'.format(n_ghost),
       '      indx = n_cell_x + cell_x;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        Q[n] = boundaryVector[arr_index + n];\n',
       '    }\n',
       '    if (cell_x == n_cell_x - {} + ng - 1) {{\n'.format(n_ghost),
       '      indx = 2*n_cell_x + cell_y;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        Q[n] = boundaryVector[arr_index + n];\n',
       '    }\n',
       '    if (cell_x == {} - ng) {{\n'.format(n_ghost),
       '      indx = 2*n_cell_x + n_cell_y + cell_y;\n',
       '      int arr_index = 2*(n_cell_x + n_cell_y)*n_send_per_cell*(ng - 1) + n_send_per_cell*indx + ({}*pos[1] + pos[0])*{};\n'.format(order + 1, n_vars),
       '      for (int n = 0; n < {}; n++)\n'.format(n_vars),
       '        Q[n] = boundaryVector[arr_index + n];\n',
       '    }\n',
       '  }\n\n'
       '  // Return 1 if state adjusted, zero otherwise\n',
       '  if (indx == -1) return 0;\n',
       '  return 1;\n'
      ]

    add_function_body(lines, '::AdjustPeriodic', body)

    f = open(fname, "w")
    f.writelines(lines)
    f.close()
示例#6
0
def write_source(lines, n_dust, q, Stokes, weights, eta):
    remove_function_body(lines, 'algebraicSource')

    source = [\
      '  // Gas source terms\n',
      '  S[0] = 0.0;\n',
      '  S[1] = 2*Q[0]*{} + 2*Q[3];\n'.format(eta),
      '  S[2] = 0.0;\n',
      '  S[3] = {}*Q[1];\n'.format(q - 2)]

    for n in range(0, n_dust):
        source.extend([\
          '  // Source terms for St = {}\n'.format(Stokes[n]),
          '  S[{}] = 0.0;\n'.format(4*n + 4),
          '  S[{}] = 2*Q[{}] - (Q[{}] - Q[{}]*Q[1]/Q[0])/{};\n'.format(4*n + 5, 4*n + 7, 4*n + 5, 4*n + 4, Stokes[n]),
          '  S[{}] = - (Q[{}] - Q[{}]*Q[2]/Q[0])/{};\n'.format(4*n + 6, 4*n + 6, 4*n + 4, Stokes[n]),
          '  S[{}] = {}*Q[{}] - (Q[{}] - Q[{}]*Q[3]/Q[0])/{};\n'.format(4*n + 7, q - 2, 4*n + 5, 4*n + 7, 4*n + 4, Stokes[n])])

    for n in range(0, n_dust):
        source.extend([\
          '  // Gas backreaction for St = {}\n'.format(Stokes[n]),
          '  S[1] += {}*(Q[{}] -Q[{}]*Q[1]/Q[0])/{};\n'.format(weights[n], 4*n + 5, 4*n + 4, Stokes[n]),
          '  S[2] += {}*(Q[{}] -Q[{}]*Q[2]/Q[0])/{};\n'.format(weights[n], 4*n + 6, 4*n + 4, Stokes[n]),
          '  S[3] += {}*(Q[{}] -Q[{}]*Q[3]/Q[0])/{};\n'.format(weights[n], 4*n + 7, 4*n + 4, Stokes[n])])

    add_function_body(lines, 'algebraicSource', source)

    return

    for i in range(0, len(lines)):
        # Source x: eta + Coriolis
        lines[i] = replace_with_indent(
            lines[i], 'S[1] = ', 'S[1] = 2*Q[0]*{} + 2*Q[3];\n'.format(eta))
        # Source y: Coriolis
        lines[i] = replace_with_indent(lines[i], 'S[3] = ',
                                       'S[3] = {}*Q[1];\n'.format(q - 2))

        for n in range(0, n_dust):
            # Source x: Coriolis + drag
            lines[i] = replace_with_indent(
                lines[i], 'S[{}] = '.format(4 * n + 5),
                'S[{}] = 2*Q[{}] - (Q[{}] - Q[{}]*Q[1]/Q[0])/{};\n'.format(
                    4 * n + 5, 4 * n + 7, 4 * n + 5, 4 * n + 4, Stokes[n]))

            # Source z: drag
            lines[i] = replace_with_indent(
                lines[i], 'S[{}] = '.format(4 * n + 6),
                'S[{}] = - (Q[{}] - Q[{}]*Q[2]/Q[0])/{};\n'.format(
                    4 * n + 6, 4 * n + 6, 4 * n + 4, Stokes[n]))

            # Source y: Coriolis + drag
            lines[i] = replace_with_indent(
                lines[i], 'S[{}] = '.format(4 * n + 7),
                'S[{}] = {}*Q[{}] - (Q[{}] - Q[{}]*Q[3]/Q[0])/{};\n'.format(
                    4 * n + 7, q - 2, 4 * n + 5, 4 * n + 7, 4 * n + 4,
                    Stokes[n]))

    gas_x_drag = []
    gas_y_drag = []
    gas_z_drag = []
    for n in range(0, n_dust):
        gas_x_drag.append('  S[1] += {}*(Q[{}] -Q[{}]*Q[1]/Q[0])/{};\n'.format(
            weights[n], 4 * n + 5, 4 * n + 4, Stokes[n]))
        gas_z_drag.append('  S[2] += {}*(Q[{}] -Q[{}]*Q[2]/Q[0])/{};\n'.format(
            weights[n], 4 * n + 6, 4 * n + 4, Stokes[n]))
        gas_y_drag.append('  S[3] += {}*(Q[{}] -Q[{}]*Q[3]/Q[0])/{};\n'.format(
            weights[n], 4 * n + 7, 4 * n + 4, Stokes[n]))

    for i in range(0, len(lines)):
        if (lines[i].find('S[1] = ') != -1):
            lines[i + 1:i + 1] = gas_x_drag
    for i in range(0, len(lines)):
        if (lines[i].find('S[2] = ') != -1):
            lines[i + 1:i + 1] = gas_z_drag
    for i in range(0, len(lines)):
        if (lines[i].find('S[3] = ') != -1):
            lines[i + 1:i + 1] = gas_y_drag
示例#7
0
def allow_periodic(repo_dir):
    ''' Modify ExaHyPE core to allow periodic boundaries on a regular mesh
    '''

    ##########################################################################
    # STEP 1: We need two extra adapters: PlotPeriodic (from mesh to boundary
    # array) and AdjustPeriodic (from boundary array to mesh). The relevant
    # cpp and h files are copied from the cpp directory of the main repo. Here
    # we modify the code to be able to use these adapters.
    ##########################################################################

    # Add adapter names to RepositoryState.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/records/RepositoryState.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        lines[i] = replace_with_indent(lines[i], 'NumberOfAdapters = 21', 'WriteCheckpoint = 0, ReadCheckpoint = 1, Terminate = 2, RunOnAllNodes = 3, UseAdapterUniformRefinement = 4, UseAdapterMeshRefinement = 5, UseAdapterMeshRefinementAndPlotTree = 6, UseAdapterFinaliseMeshRefinement = 7, UseAdapterFinaliseMeshRefinementOrLocalRollback = 8, UseAdapterInitialPrediction = 9, UseAdapterFusedTimeStep = 10, UseAdapterPredictionRerun = 11, UseAdapterBroadcast = 12, UseAdapterBroadcastAndDropNeighbourMessages = 13, UseAdapterRefinementStatusSpreading = 14, UseAdapterPredictionOrLocalRecomputation = 15, UseAdapterMergeNeighbours = 16, UseAdapterUpdateAndReduce = 17, UseAdapterPrediction = 18, UseAdapterCorrection = 19, UseAdapterAdjustPeriodic = 20, UseAdapterPlotPeriodic = 21, UseAdapterEmpty = 22, NumberOfAdapters = 23\n')

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add adapter names to RepositoryState.cpp
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/records/RepositoryState.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('case UseAdapterCorrection: return "UseAdapterCorrection";') != -1):
                lines[i+1:i+1] = ['      case UseAdapterAdjustPeriodic: return "UseAdapterAdjustPeriodic";\n', '      case UseAdapterPlotPeriodic: return "UseAdapterPlotPeriodic";\n']
        lines[i] = replace_with_indent(lines[i], 'NumberOfAdapters=21', 'return "Action(WriteCheckpoint=0,ReadCheckpoint=1,Terminate=2,RunOnAllNodes=3,UseAdapterUniformRefinement=4,UseAdapterMeshRefinement=5,UseAdapterMeshRefinementAndPlotTree=6,UseAdapterFinaliseMeshRefinement=7,UseAdapterFinaliseMeshRefinementOrLocalRollback=8,UseAdapterInitialPrediction=9,UseAdapterFusedTimeStep=10,UseAdapterPredictionRerun=11,UseAdapterBroadcast=12,UseAdapterBroadcastAndDropNeighbourMessages=13,UseAdapterRefinementStatusSpreading=14,UseAdapterPredictionOrLocalRecomputation=15,UseAdapterMergeNeighbours=16,UseAdapterUpdateAndReduce=17,UseAdapterPrediction=18,UseAdapterCorrection=19,UseAdapterAdjustPeriodic=20,UseAdapterPlotPeriodic=21,UseAdapterEmpty=22,NumberOfAdapters=23)";\n')

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add switch functions to Repository.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/repositories/Repository.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('virtual void switchToCorrection() = 0;') != -1):
            lines[i+1:i+1] = ['    virtual void switchToAdjustPeriodic() = 0;\n',
                              '    virtual void switchToPlotPeriodic() = 0;\n']
        if (lines[i].find('virtual bool isActiveAdapterCorrection() const = 0;') != -1):
            lines[i+1:i+1] = ['    virtual bool isActiveAdapterAdjustPeriodic() const = 0;\n', '    virtual bool isActiveAdapterPlotPeriodic() const = 0;\n']

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add functions to RepositorySTDStack.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/repositories/RepositorySTDStack.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        # Include the new adapter headers
        if (lines[i].find('#include "exahype/adapters/Correction.h"') != -1):
            lines[i+1:i+1] = [' #include "exahype/adapters/AdjustPeriodic.h"\n',
                              ' #include "exahype/adapters/PlotPeriodic.h"\n']
        # Declare new grids
        if (lines[i].find('peano::grid::Grid<exahype::Vertex,exahype::Cell,exahype::State,VertexStack,CellStack,exahype::adapters::Correction> _gridWithCorrection;') != -1):
            lines[i+1:i+1] = ['    peano::grid::Grid<exahype::Vertex,exahype::Cell,exahype::State,VertexStack,CellStack,exahype::adapters::AdjustPeriodic> _gridWithAdjustPeriodic;\n', '    peano::grid::Grid<exahype::Vertex,exahype::Cell,exahype::State,VertexStack,CellStack,exahype::adapters::PlotPeriodic> _gridWithPlotPeriodic;\n']
        # Declare new switch functions
        if (lines[i].find('virtual void switchToCorrection();') != -1):
            lines[i+1:i+1] = ['    virtual void switchToAdjustPeriodic();\n',
                              '    virtual void switchToPlotPeriodic();\n']
        # Declare new IsActive functions
        if (lines[i].find('virtual bool isActiveAdapterCorrection() const;') != -1):
            lines[i+1:i+1] = ['    virtual bool isActiveAdapterAdjustPeriodic() const;\n', '    virtual bool isActiveAdapterPlotPeriodic() const;\n']
        # Declare new time measurement functions
        if (lines[i].find('tarch::timing::Measurement _measureCorrectionCPUTime;') != -1):
            lines[i+1:i+1] = ['    tarch::timing::Measurement _measureAdjustPeriodicCPUTime;\n', '    tarch::timing::Measurement _measurePlotPeriodicCPUTime;\n']
        if (lines[i].find('tarch::timing::Measurement _measureCorrectionCalendarTime;') != -1):
            lines[i+1:i+1] = ['    tarch::timing::Measurement _measureAdjustPeriodicCalendarTime;\n', '    tarch::timing::Measurement _measurePlotPeriodicCalendarTime;\n']


    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add functions to RepositorySTDStack.cpp
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/repositories/RepositorySTDStack.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('_gridWithCorrection(_vertexStack,_cellStack,_geometry,_solverState,domainSize,computationalDomainOffset,_regularGridContainer,_traversalOrderOnTopLevel),') != -1):
            lines[i+1:i+1] = ['  _gridWithAdjustPeriodic(_vertexStack,_cellStack,_geometry,_solverState,domainSize,computationalDomainOffset,_regularGridContainer,_traversalOrderOnTopLevel),\n', '  _gridWithPlotPeriodic(_vertexStack,_cellStack,_geometry,_solverState,domainSize,computationalDomainOffset,_regularGridContainer,_traversalOrderOnTopLevel),\n']
        if (lines[i].find('_gridWithCorrection(_vertexStack,_cellStack,_geometry,_solverState,_regularGridContainer,_traversalOrderOnTopLevel),') != -1):
            lines[i+1:i+1] = ['  _gridWithAdjustPeriodic(_vertexStack,_cellStack,_geometry,_solverState,_regularGridContainer,_traversalOrderOnTopLevel),\n','  _gridWithPlotPeriodic(_vertexStack,_cellStack,_geometry,_solverState,_regularGridContainer,_traversalOrderOnTopLevel),\n']
        if (lines[i].find('_gridWithCorrection.restart') != -1):
            lines[i+1:i+1] = ['  _gridWithAdjustPeriodic.restart(domainSize,domainOffset,domainLevel, positionOfCentralElementWithRespectToCoarserRemoteLevel);\n', '  _gridWithPlotPeriodic.restart(domainSize,domainOffset,domainLevel, positionOfCentralElementWithRespectToCoarserRemoteLevel);\n']
        if (lines[i].find('_gridWithCorrection.terminate') != -1):
            lines[i+1:i+1] = ['  _gridWithAdjustPeriodic.terminate();\n',
                              '  _gridWithPlotPeriodic.terminate();\n']
        if (lines[i].find('case exahype::records::RepositoryState::UseAdapterCorrection:') != -1):
            lines[i+1:i+1] = ['      case exahype::records::RepositoryState::UseAdapterAdjustPeriodic: watch.startTimer(); _gridWithAdjustPeriodic.iterate(); watch.stopTimer(); _measureAdjustPeriodicCPUTime.setValue( watch.getCPUTime() ); _measureAdjustPeriodicCalendarTime.setValue( watch.getCalendarTime() ); break;\n', '      case exahype::records::RepositoryState::UseAdapterPlotPeriodic: watch.startTimer(); _gridWithPlotPeriodic.iterate(); watch.stopTimer(); _measurePlotPeriodicCPUTime.setValue( watch.getCPUTime() ); _measurePlotPeriodicCalendarTime.setValue( watch.getCalendarTime() ); break;\n']
        if (lines[i].find('void exahype::repositories::RepositorySTDStack::switchToCorrection() { _repositoryState.setAction(exahype::records::RepositoryState::UseAdapterCorrection); }') != -1):
            lines[i+1:i+1] = [' void exahype::repositories::RepositorySTDStack::switchToAdjustPeriodic() { _repositoryState.setAction(exahype::records::RepositoryState::UseAdapterAdjustPeriodic); }\n', ' void exahype::repositories::RepositorySTDStack::switchToPlotPeriodic() { _repositoryState.setAction(exahype::records::RepositoryState::UseAdapterPlotPeriodic); }\n']
        if (lines[i].find('bool exahype::repositories::RepositorySTDStack::isActiveAdapterCorrection() const { return _repositoryState.getAction() == exahype::records::RepositoryState::UseAdapterCorrection; }') != -1):
            lines[i+1:i+1] = [' bool exahype::repositories::RepositorySTDStack::isActiveAdapterAdjustPeriodic() const { return _repositoryState.getAction() == exahype::records::RepositoryState::UseAdapterAdjustPeriodic; }\n', ' bool exahype::repositories::RepositorySTDStack::isActiveAdapterPlotPeriodic() const { return _repositoryState.getAction() == exahype::records::RepositoryState::UseAdapterPlotPeriodic; }\n']

    # Add logging functions
    for i in range(0, len(lines)):
        if (lines[i].find('if (logAllAdapters || _measureCorrectionCPUTime.getNumberOfMeasurements()>0) logInfo( "logIterationStatistics()", "| Correction \t |  " << _measureCorrectionCPUTime.getNumberOfMeasurements() << " \t |  " << _measureCorrectionCPUTime.getAccumulatedValue() << " \t |  " << _measureCorrectionCPUTime.getValue()  << " \t |  " << _measureCorrectionCalendarTime.getAccumulatedValue() << " \t |  " << _measureCorrectionCalendarTime.getValue() << " \t |  " << _measureCorrectionCPUTime.toString() << " \t |  " << _measureCorrectionCalendarTime.toString() );') != -1):
            lines[i+1:i+1] = ['    if (logAllAdapters || _measureAdjustPeriodicCPUTime.getNumberOfMeasurements()>0) logInfo( "logIterationStatistics()", "| AdjustPeriodic \t |  " << _measureAdjustPeriodicCPUTime.getNumberOfMeasurements() << " \t |  " << _measureAdjustPeriodicCPUTime.getAccumulatedValue() << " \t |  " << _measureAdjustPeriodicCPUTime.getValue()  << " \t |  " << _measureAdjustPeriodicCalendarTime.getAccumulatedValue() << " \t |  " << _measureAdjustPeriodicCalendarTime.getValue() << " \t |  " << _measureAdjustPeriodicCPUTime.toString() << " \t |  " << _measureAdjustPeriodicCalendarTime.toString() );\n', '    if (logAllAdapters || _measurePlotPeriodicCPUTime.getNumberOfMeasurements()>0) logInfo( "logIterationStatistics()", "| PlotPeriodic \t |  " << _measurePlotPeriodicCPUTime.getNumberOfMeasurements() << " \t |  " << _measurePlotPeriodicCPUTime.getAccumulatedValue() << " \t |  " << _measurePlotPeriodicCPUTime.getValue()  << " \t |  " << _measurePlotPeriodicCalendarTime.getAccumulatedValue() << " \t |  " << _measurePlotPeriodicCalendarTime.getValue() << " \t |  " << _measurePlotPeriodicCPUTime.toString() << " \t |  " << _measurePlotPeriodicCalendarTime.toString() );\n']

    for i in range(0, len(lines)):
        if (lines[i].find('_measureCorrectionCPUTime.erase();') != -1):
            lines[i+1:i+1] = ['   _measureAdjustPeriodicCPUTime.erase();\n',
                              '   _measurePlotPeriodicCPUTime.erase();\n']

    for i in range(0, len(lines)):
        if (lines[i].find('_measureCorrectionCalendarTime.erase();') != -1):
            lines[i+1:i+1] = ['   _measureAdjustPeriodicCalendarTime.erase();\n', '   _measurePlotPeriodicCalendarTime.erase();\n']


    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    ##########################################################################
    # STEP 2: Integrate new adapters into time stepping loop. At the start of
    # a time step, that is, after the correction update: First use the
    # 'plotting' adapter to get the boundary values into and array, followed
    # by the 'adjusting' adapter to get the values on the periodic boundaries
    # on the mesh.
    ##########################################################################

    # Modify time stepping
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/runners/Runner.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    body = remove_function_body(lines, '::runOneTimeStepWithThreeSeparateAlgorithmicSteps')

    for i in range(0, len(body)):
        if (body[i].find('repository.switchToPrediction(); // Cell onto faces') != -1):
            body[i:i] = ['  repository.switchToPlotPeriodic();\n',
                          '  repository.iterate(1, communicatePeanoVertices);\n',
                          '  repository.switchToAdjustPeriodic();\n',
                          '  repository.iterate(1, communicatePeanoVertices);\n',
                          '\n']

    add_function_body(lines, '::runOneTimeStepWithThreeSeparateAlgorithmicSteps',
                      body)

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    ##########################################################################
    # STEP 3: Declare and define the functions performing the 'plotting' and
    # 'adjusting'. For 'adjusting' we rely on the existing adjustSolution
    # functions. For 'plotting', the final PlotPeriodic function will have to
    # be defined in the user abstract class.
    ##########################################################################

    #################################
    # First deal with ADER-DG solver
    #################################
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/ADERDGSolver.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    lines[len(lines):len(lines)] = \
      ['\n',
       'int exahype::solvers::ADERDGSolver::AdjustPeriodic(\n',
       '  const int                                          solverNumber,\n',
       '  CellInfo&                                          cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  int ret = 0;\n',
       '  const int element = cellInfo.indexOfADERDGCellDescription(solverNumber);\n',
       '  if ( element != NotFound ) {\n',
       '    CellDescription& cellDescription = cellInfo._ADERDGCellDescriptions[element];\n',
       '    if ( cellDescription.getType()==CellDescription::Type::Leaf ) {\n',
       '      double* solverSolution =\n',
       '        static_cast<double*>(cellDescription.getSolution());\n',
       '\n',
       '      const int order = getNodesPerCoordinateAxis() - 1;\n',
       '      const int basisX = order + 1;\n',
       '      const int basisY = order + 1;\n',
       '      const int basisZ = (DIMENSIONS == 3 ? order  : 0 ) + 1;\n',
       '      kernels::index idx_u(basisZ, basisY, basisX, getNumberOfVariables());\n',
       '\n',
       '      // Call the solver-defined AdjustPeriodic function\n',
       '      dfor(i, order + 1) {\n',
       '        ret = AdjustPeriodic(\n',
       '          cellDescription.getOffset(),\n',
       '          cellDescription.getSize(),\n',
       '          i,\n',
       '          solverSolution + idx_u(DIMENSIONS == 3 ? i(2) : 0, i(1), i(0), 0));\n',
       '      }\n',
       '    }\n',
       '  }\n',
       '  return ret;\n',
       '}\n',
       '\n',
       'void exahype::solvers::ADERDGSolver::PlotPeriodic(\n',
       '  const int                                          solverNumber,\n',
       '  CellInfo&                                          cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  const int element = cellInfo.indexOfADERDGCellDescription(solverNumber);\n',
       '  if ( element != NotFound ) {\n',
       '    CellDescription& cellDescription = cellInfo._ADERDGCellDescriptions[element];\n',
       '    if ( cellDescription.getType()==CellDescription::Type::Leaf ) {\n',
       '      double* solverSolution =\n',
       '        static_cast<double*>(cellDescription.getSolution());\n',
       '\n',
       '      const int order = getNodesPerCoordinateAxis() - 1;\n',
       '      const int basisX = order + 1;\n',
       '      const int basisY = order + 1;\n',
       '      const int basisZ = (DIMENSIONS == 3 ? order  : 0 ) + 1;\n',
       '      kernels::index idx_u(basisZ, basisY, basisX, getNumberOfVariables());\n',
       '\n',
       '      // Call the solver-defined PlotPeriodic function\n',
       '      dfor(i, order + 1) {\n',
       '        PlotPeriodic(\n',
       '        cellDescription.getOffset(),\n',
       '        cellDescription.getSize(),\n',
       '        i,\n',
       '        solverSolution + idx_u(DIMENSIONS == 3 ? i(2) : 0, i(1), i(0), 0));\n',
       '      }\n',
       '    }\n',
       '  }\n',
       '}\n',
       '\n',
       'void exahype::solvers::ADERDGSolver::FinishPeriodic() {\n',
       '  SendPeriodic();\n',
       '}\n',
       '\n',
       ]

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add functions to ADERDGsolver.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/ADERDGSolver.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('void updateOrRestrict(') != -1):
            lines[i:i] = ['  void PlotPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  int AdjustPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  virtual void PlotPeriodic(\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& offsetOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& sizeOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, int>& pos,\n',
                          '    double* const Q) = 0;\n',
                          '  virtual int AdjustPeriodic(\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& offsetOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& sizeOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, int>& pos,\n',
                          '    double* Q) = 0;\n',
                          '  void FinishPeriodic() final override;\n',
                          '  virtual void SendPeriodic() = 0;\n',
                          '\n']
            break;

    f = open(fname, "w")
    f.writelines(lines)
    f.close()





    #################################
    # Next: FV solver
    #################################
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/FiniteVolumesSolver.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    lines[len(lines):len(lines)] = \
      ['\n',
       'int exahype::solvers::FiniteVolumesSolver::AdjustPeriodic(\n',
       '  const int                                          solverNumber,\n',
       '  CellInfo&                                          cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  int ret = 0;\n',
       '  const int element = cellInfo.indexOfFiniteVolumesCellDescription(solverNumber);\n',
       '  if ( element != NotFound ) {\n',
       '    CellDescription& cellDescription = cellInfo._FiniteVolumesCellDescriptions[element];\n',
       '    if ( cellDescription.getType()==CellDescription::Type::Leaf ) {\n',
       '      double* solverSolution =\n',
       '        static_cast<double*>(cellDescription.getSolution());\n',
       '\n',
       '      kernels::idx3 idx(_nodesPerCoordinateAxis+2*_ghostLayerWidth,\n',
       '                        _nodesPerCoordinateAxis+2*_ghostLayerWidth,\n',
       '                        _numberOfVariables+_numberOfParameters);\n',

       '      for (int i = _ghostLayerWidth; i < _nodesPerCoordinateAxis + _ghostLayerWidth; i++) {\n',
       '        for (int j = _ghostLayerWidth; j < _nodesPerCoordinateAxis + _ghostLayerWidth; j++) {\n',
       '          tarch::la::Vector<DIMENSIONS, int> pos(i - _ghostLayerWidth, j - _ghostLayerWidth);\n',
       '          ret = AdjustPeriodic(\n',
       '            cellDescription.getOffset(),\n',
       '            cellDescription.getSize(),\n',
       '            pos,\n',
       '            solverSolution + idx(j, i, 0));\n',
       '        }\n',
       '      }\n',
       '    }\n',
       '  }\n',
       '  return ret;\n',
       '}\n',
       '\n',
       'void exahype::solvers::FiniteVolumesSolver::PlotPeriodic(\n',
       '  const int                                          solverNumber,\n',
       '  CellInfo&                                          cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  const int element = cellInfo.indexOfFiniteVolumesCellDescription(solverNumber);\n',
       '  if ( element != NotFound ) {\n',
       '    CellDescription& cellDescription = cellInfo._FiniteVolumesCellDescriptions[element];\n',
       '    if ( cellDescription.getType()==CellDescription::Type::Leaf ) {\n',
       '      double* solverSolution =\n',
       '        static_cast<double*>(cellDescription.getSolution());\n',
       '\n',
       '      kernels::idx3 idx(_nodesPerCoordinateAxis+2*_ghostLayerWidth,\n',
       '                        _nodesPerCoordinateAxis+2*_ghostLayerWidth,\n',
       '                        _numberOfVariables+_numberOfParameters);\n',

       '      for (int i = _ghostLayerWidth; i < _nodesPerCoordinateAxis + _ghostLayerWidth; i++) {\n',
       '        for (int j = _ghostLayerWidth; j < _nodesPerCoordinateAxis + _ghostLayerWidth; j++) {\n',
       '          tarch::la::Vector<DIMENSIONS, int> pos(i - _ghostLayerWidth, j - _ghostLayerWidth);\n',
       '          // Call the solver-defined PlotPeriodic function\n',
       '          PlotPeriodic(\n',
       '            cellDescription.getOffset(),\n',
       '            cellDescription.getSize(),\n',
       '            pos,\n',
       '            solverSolution + idx(j, i, 0));\n',
       '        }\n',
       '      }\n',
       '    }\n',
       '  }\n',
       '}\n',
       '\n',
       'void exahype::solvers::FiniteVolumesSolver::FinishPeriodic() {\n',
       '  SendPeriodic();\n',
       '}\n',
       '\n',
       ]

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add functions to FiniteVolumesSolver.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/FiniteVolumesSolver.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('void updateOrRestrict(') != -1):
            lines[i:i] = ['  void PlotPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  int AdjustPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  virtual void PlotPeriodic(\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& offsetOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& sizeOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, int>& pos,\n',
                          '    double* const Q) = 0;\n',
                          '  virtual int AdjustPeriodic(\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& offsetOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, double>& sizeOfPatch,\n',
                          '    const tarch::la::Vector<DIMENSIONS, int>& pos,\n',
                          '    double* Q) = 0;\n',
                          '  void FinishPeriodic() final override;\n',
                          '  virtual void SendPeriodic() = 0;\n',
                          '\n']
            break;

    f = open(fname, "w")
    f.writelines(lines)
    f.close()




    #################################
    # Finally: limiting scheme
    #################################
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/LimitingADERDGSolver.cpp'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    lines[len(lines):len(lines)] = \
      ['\n',
       'int exahype::solvers::LimitingADERDGSolver::AdjustPeriodic(\n',
       '  const int solverNumber,\n',
       '  CellInfo& cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  int madeAdjustment = _solver->AdjustPeriodic(solverNumber, cellInfo, usePreviousSolution);\n',
       '  int madeAdjustmentLimiter = _limiter->AdjustPeriodic(solverNumber, cellInfo, usePreviousSolution);\n',
       '  if (madeAdjustment) {\n',
       '    const int solverElement = cellInfo.indexOfADERDGCellDescription(solverNumber);\n',
       '    if ( solverElement != Solver::NotFound ) {\n',
       '       determineMinAndMax(solverNumber, cellInfo);\n',
       #'      SolverPatch& solverPatch = cellInfo._ADERDGCellDescriptions[solverElement];\n',
       #'      std::cout << "Adjust Refinement status: " << solverPatch.getRefinementStatus() << " " << _solver->_minRefinementStatusForTroubledCell << std::endl;\n',
       #'      solverPatch.setRefinementStatus(_solver->_minRefinementStatusForTroubledCell);\n',
       #'      const int limiterElement = cellInfo.indexOfFiniteVolumesCellDescription(solverNumber);\n',
       #'      if (limiterElement != Solver::NotFound) {\n',
       #'        LimiterPatch& limiterPatch = getLimiterPatch(solverPatch,cellInfo);\n',
       #'        projectDGSolutionOnFVSpace(solverPatch,limiterPatch);\n',
       #'      }\n',
       '    }\n',
       '  }\n',
       '  return 0;\n',
       '}\n',
       '\n',
       'void exahype::solvers::LimitingADERDGSolver::PlotPeriodic(\n',
       '  const int solverNumber,\n',
       '  CellInfo& cellInfo,\n',
       '  bool usePreviousSolution) {\n',
       '  _solver->PlotPeriodic(solverNumber, cellInfo, usePreviousSolution);\n',
       '  _limiter->PlotPeriodic(solverNumber, cellInfo, usePreviousSolution);\n',
       '}\n',
       '\n',
       'void exahype::solvers::LimitingADERDGSolver::FinishPeriodic() {\n',
       '  _solver->FinishPeriodic();\n',
       '  _limiter->FinishPeriodic();\n',
       '}\n',
       '\n',
       ]

    f = open(fname, "w")
    f.writelines(lines)
    f.close()

    # Add functions to LimitingADERDGsolver.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/LimitingADERDGSolver.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('void updateOrRestrict(') != -1):
            lines[i:i] = ['  void PlotPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  int AdjustPeriodic(\n',
                          '    const int solverNumber,\n',
                          '    CellInfo& cellInfo,\n',
                          '    bool usePreviousSolution) final override;\n',
                          '  void FinishPeriodic() final override;\n',
                          '\n']
            break;

    f = open(fname, "w")
    f.writelines(lines)
    f.close()


    # Add functions to Solver.h
    fname = repo_dir + 'ExaHyPE-Engine/ExaHyPE/exahype/solvers/Solver.h'
    f = open(fname, "r")
    lines = f.readlines()
    f.close()

    for i in range(0, len(lines)):
        if (lines[i].find('* The nonfused update routine.') != -1):
            lines[i-1:i-1] = \
              ['  virtual void PlotPeriodic(\n',
               '    const int solverNumber,\n',
               '    CellInfo& cellInfo,\n',
               '    bool usePreviousSolution) = 0;\n',
               '  virtual int AdjustPeriodic(\n',
               '    const int solverNumber,\n',
               '    CellInfo& cellInfo,\n',
               '    bool usePreviousSolution) = 0;\n',
               '  virtual void FinishPeriodic() = 0;\n',
               '\n']
            break;

    f = open(fname, "w")
    f.writelines(lines)
    f.close()