Exemplo n.º 1
0
/**
 * Main program for the simulation on a single SWE_WavePropagationBlock.
 */
int main( int argc, char** argv ) {
  /**
   * Initialization.
   */
  // Parse command line parameters
  tools::Args args;
  #ifndef READXML
  args.addOption("grid-size-x", 'x', "Number of cells in x direction");
  args.addOption("grid-size-y", 'y', "Number of cells in y direction");
  args.addOption("output-basepath", 'o', "Output base file name");
  #endif

  tools::Args::Result ret = args.parse(argc, argv);

  switch (ret)
  {
  case tools::Args::Error:
	  return 1;
  case tools::Args::Help:
	  return 0;
  }

  //! number of grid cells in x- and y-direction.
  int l_nX, l_nY;

  //! l_baseName of the plots.
  std::string l_baseName;

  // read command line parameters
  #ifndef READXML
  l_nX = args.getArgument<int>("grid-size-x");
  l_nY = args.getArgument<int>("grid-size-y");
  l_baseName = args.getArgument<std::string>("output-basepath");
  #endif

  // read xml file
  #ifdef READXML
  assert(false); //TODO: not implemented.
  if(argc != 2) {
    s_sweLogger.printString("Aborting. Please provide a proper input file.");
    s_sweLogger.printString("Example: ./SWE_gnu_debug_none_augrie config.xml");
    return 1;
  }
  s_sweLogger.printString("Reading xml-file.");

  std::string l_xmlFile = std::string(argv[1]);
  s_sweLogger.printString(l_xmlFile);

  CXMLConfig l_xmlConfig;
  l_xmlConfig.loadConfig(l_xmlFile.c_str());
  #endif

  #ifdef ASAGI
  /* Information about the example bathymetry grid (tohoku_gebco_ucsb3_500m_hawaii_bath.nc):
   *
   * Pixel node registration used [Cartesian grid]
   * Grid file format: nf = GMT netCDF format (float)  (COARDS-compliant)
   * x_min: -500000 x_max: 6500000 x_inc: 500 name: x nx: 14000
   * y_min: -2500000 y_max: 1500000 y_inc: 500 name: y ny: 8000
   * z_min: -6.48760175705 z_max: 16.1780223846 name: z
   * scale_factor: 1 add_offset: 0
   * mean: 0.00217145586762 stdev: 0.245563641735 rms: 0.245573241263
   */

  //simulation area
  float simulationArea[4];
  simulationArea[0] = -450000;
  simulationArea[1] = 6450000;
  simulationArea[2] = -2450000;
  simulationArea[3] = 1450000;

  SWE_AsagiScenario l_scenario( ASAGI_INPUT_DIR "tohoku_gebco_ucsb3_500m_hawaii_bath.nc",
                                ASAGI_INPUT_DIR "tohoku_gebco_ucsb3_500m_hawaii_displ.nc",
                                (float) 28800., simulationArea);
  #else
  // create a simple artificial scenario
  SWE_RadialDamBreakScenario l_scenario;
  #endif

  //! number of checkpoints for visualization (at each checkpoint in time, an output file is written).
  int l_numberOfCheckPoints = 200;

  //! size of a single cell in x- and y-direction
  float l_dX, l_dY;

  // compute the size of a single cell
  l_dX = (l_scenario.getBoundaryPos(BND_RIGHT) - l_scenario.getBoundaryPos(BND_LEFT) )/l_nX;
  l_dY = (l_scenario.getBoundaryPos(BND_TOP) - l_scenario.getBoundaryPos(BND_BOTTOM) )/l_nY;

  // create a single wave propagation block
  #ifndef CUDA
  SWE_WavePropagationBlock l_wavePropgationBlock(l_nX,l_nY,l_dX,l_dY);
  #else
  SWE_WavePropagationBlockCuda l_wavePropgationBlock(l_nX,l_nY,l_dX,l_dY);
  #endif

  //! origin of the simulation domain in x- and y-direction
  float l_originX, l_originY;

  // get the origin from the scenario
  l_originX = l_scenario.getBoundaryPos(BND_LEFT);
  l_originY = l_scenario.getBoundaryPos(BND_BOTTOM);

  // initialize the wave propagation block
  l_wavePropgationBlock.initScenario(l_originX, l_originY, l_scenario);


  //! time when the simulation ends.
  float l_endSimulation = l_scenario.endSimulation();

  //! checkpoints when output files are written.
  float* l_checkPoints = new float[l_numberOfCheckPoints+1];

  // compute the checkpoints in time
  for(int cp = 0; cp <= l_numberOfCheckPoints; cp++) {
     l_checkPoints[cp] = cp*(l_endSimulation/l_numberOfCheckPoints);
  }

  // Init fancy progressbar
  tools::ProgressBar progressBar(l_endSimulation);

  // write the output at time zero
  tools::Logger::logger.printOutputTime((float) 0.);
  progressBar.update(0.);

  std::string l_fileName = generateBaseFileName(l_baseName,0,0);
  //boundary size of the ghost layers
  io::BoundarySize l_boundarySize = {{1, 1, 1, 1}};
#ifdef WRITENETCDF
  //construct a NetCdfWriter
  io::NetCdfWriter l_writer( l_fileName,
		  l_wavePropgationBlock.getBathymetry(),
		  l_boundarySize,
		  l_nX, l_nY,
		  l_dX, l_dY,
		  l_originX, l_originY);
#else
  // consturct a VtkWriter
  io::VtkWriter l_writer( l_fileName,
		  l_wavePropgationBlock.getBathymetry(),
		  l_boundarySize,
		  l_nX, l_nY,
		  l_dX, l_dY );
#endif
  // Write zero time step
  l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                          l_wavePropgationBlock.getDischarge_hu(),
                          l_wavePropgationBlock.getDischarge_hv(),
                          (float) 0.);


  /**
   * Simulation.
   */
  // print the start message and reset the wall clock time
  progressBar.clear();
  tools::Logger::logger.printStartMessage();
  tools::Logger::logger.initWallClockTime(time(NULL));

  //! simulation time.
  float l_t = 0.0;
  progressBar.update(l_t);

  unsigned int l_iterations = 0;

  // loop over checkpoints
  for(int c=1; c<=l_numberOfCheckPoints; c++) {

    // do time steps until next checkpoint is reached
    while( l_t < l_checkPoints[c] ) {
      // set values in ghost cells:
      l_wavePropgationBlock.setGhostLayer();
      
      // reset the cpu clock
      tools::Logger::logger.resetClockToCurrentTime("Cpu");

      // approximate the maximum time step
      // TODO: This calculation should be replaced by the usage of the wave speeds occuring during the flux computation
      // Remark: The code is executed on the CPU, therefore a "valid result" depends on the CPU-GPU-synchronization.
//      l_wavePropgationBlock.computeMaxTimestep();

      // compute numerical flux on each edge
      l_wavePropgationBlock.computeNumericalFluxes();

      //! maximum allowed time step width.
      float l_maxTimeStepWidth = l_wavePropgationBlock.getMaxTimestep();


      // update the cell values
      l_wavePropgationBlock.updateUnknowns(l_maxTimeStepWidth);

      // update the cpu time in the logger
      tools::Logger::logger.updateTime("Cpu");

      // update simulation time with time step width.
      l_t += l_maxTimeStepWidth;
      l_iterations++;

      // print the current simulation time
      progressBar.clear();
      tools::Logger::logger.printSimulationTime(l_t);
      progressBar.update(l_t);
    }

    // print current simulation time of the output
    progressBar.clear();
    tools::Logger::logger.printOutputTime(l_t);
    progressBar.update(l_t);

    // write output
    l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                            l_wavePropgationBlock.getDischarge_hu(),
                            l_wavePropgationBlock.getDischarge_hv(),
                            l_t);
  }

  /**
   * Finalize.
   */
  // write the statistics message
  progressBar.clear();
  tools::Logger::logger.printStatisticsMessage();

  // print the cpu time
  tools::Logger::logger.printTime("Cpu", "CPU time");

  // print the wall clock time (includes plotting)
  tools::Logger::logger.printWallClockTime(time(NULL));

  // printer iteration counter
  tools::Logger::logger.printIterationsDone(l_iterations);

  return 0;
}
Exemplo n.º 2
0
int main( int argc, char** argv ) {
    
    //! Number of cells in x direction
    int l_nX = 0;
    
    //! Number of cells in y direction
    int l_nY = 0;

	//! coarseness factor
	float l_coarseness = 1.0;
    
    //! l_baseName of the plots.
    std::string l_baseName;
    
    //! bathymetry input file name
    std::string l_bathymetryFileName;
    
    //! displacement input file name
    std::string l_displacementFileName;
    
    //! checkpoint input file name
    std::string l_checkpointFileName;
    
    //! the total simulation time
    int l_simulationTime = 0.0;

#ifdef USEOPENCL
    //! Maximum number of computing devices to be used (OpenCL specific, 0 = unlimited)
    unsigned int l_maxDevices = 0;
    
    //! Maximum kernel group size
    size_t l_maxGroupSize = 1024;
    
    //! Chosen kernel optimization type
    KernelType l_kernelType = MEM_GLOBAL;
#endif
    
    //! type of boundary conditions at LEFT, RIGHT, TOP, and BOTTOM boundary
    BoundaryType l_boundaryTypes[4];
    //! whether to override the scenario-defined conditions (true) or not (false)
    bool l_overwriteBoundaryTypes = false;
    
    //! List of defined scenarios
    typedef enum {
        SCENARIO_TSUNAMI, SCENARIO_CHECKPOINT_TSUNAMI,
        SCENARIO_ARTIFICIAL_TSUNAMI, SCENARIO_PARTIAL_DAMBREAK
    } ScenarioName;
    
    //! the name of the chosen scenario
    ScenarioName l_scenarioName;
#ifdef WRITENETCDF
    l_scenarioName = SCENARIO_TSUNAMI;
#else
    l_scenarioName = SCENARIO_PARTIAL_DAMBREAK;
#endif
    
    //! number of checkpoints for visualization (at each checkpoint in time, an output file is written).
    int l_numberOfCheckPoints = 20;
    
    // Option Parsing
    // REQUIRED
    // -x <num>        // Number of cells in x-dir
    // -y <num>        // Number of cells in y-dir
    // -o <file>       // Output file basename
    // OPTIONAL (may be required for certain scenarios)
    // -i <file>       // initial bathymetry data file name (REQUIRED for certain scenarios)
    // -d <file>       // input displacement data file name (REQUIRED for certain scenarios)
    // -c <file>       // checkpoints data file name
    // -f <float>      // output coarseness factor
    // -l <num>        // maximum number of computing devices
    // -m <code>       // Kernel memory optimization type
    // -g <num         // Kernel work group size
    // -n <num>        // Number of checkpoints
    // -t <float>      // Simulation time in seconds
    // -s <scenario>   // Artificial scenario name ("artificialtsunami", "partialdambreak")
    // -b <code>       // Boundary conditions, "w" or "o"
    //                 // 1 value: for all
    //                 // 2 values: first is left/right, second is top/bottom
    //                 // 4 values: left, right, bottom, top
    int c;
    int showUsage = 0;
    std::string optstr;
    while ((c = getopt(argc, argv, "x:y:o:i:d:c:n:t:b:s:f:l:m:g:")) != -1) {
        switch(c) {
            case 'x':
                l_nX = atoi(optarg);
                break;
            case 'y':
                l_nY = atoi(optarg);
                break;
            case 'o':
                l_baseName = std::string(optarg);
                break;
#ifdef WRITENETCDF
            case 'i':
                l_bathymetryFileName = std::string(optarg);
                break;
            case 'd':
                l_displacementFileName = std::string(optarg);
                break;
            case 'c':
                l_checkpointFileName = std::string(optarg);
                break;
#endif
            case 'l':
#ifdef USEOPENCL
                l_maxDevices = atoi(optarg);
#endif
                break;
            case 'g':
#ifdef USEOPENCL
                l_maxGroupSize = atoi(optarg);
#endif
            break;
            case 'm':
#ifdef USEOPENCL
                optstr = std::string(optarg);
                if(optstr == "g" || optstr == "global")
                    l_kernelType = MEM_GLOBAL;
                else
                    l_kernelType = MEM_LOCAL;
#endif
                break;
            case 'n':
                l_numberOfCheckPoints = atoi(optarg);
                break;
            case 't':
                l_simulationTime = atof(optarg);
                break;
            case 'b':
                optstr = std::string(optarg);
                l_overwriteBoundaryTypes = true;
                switch(optstr.length()) {
                    case 1:
                        // one option for all boundaries
                        for(int i = 0; i < 4; i++)
                            l_boundaryTypes[i] = (optstr[0] == 'w') ? WALL : OUTFLOW;
                        break;
                    case 2:
                        // first: left/right, second: top/bottom
                        for(int i = 0; i < 2; i++)
                            l_boundaryTypes[i] = (optstr[0] == 'w') ? WALL : OUTFLOW;
                        for(int i = 2; i < 4; i++)
                            l_boundaryTypes[i] = (optstr[1] == 'w') ? WALL : OUTFLOW;
                        break;
                    case 4:
                        // left right bottom top
                        for(int i = 0; i < 4; i++)
                            l_boundaryTypes[i] = (optstr[i] == 'w') ? WALL : OUTFLOW;
                        break;
                    default:
                        std::cerr << "Invalid option argument: Invalid boundary specification (-b)" << std::endl;
                        showUsage = 1;
                        break;
                }
                break;
            case 's':
                optstr = std::string(optarg);
                if(optstr == "artificialtsunami") {
                    l_scenarioName = SCENARIO_ARTIFICIAL_TSUNAMI;
                } else if(optstr == "partialdambreak") {
                    l_scenarioName = SCENARIO_PARTIAL_DAMBREAK;
                } else {
                    std::cerr << "Invalid option argument: Unknown scenario (-s)" << std::endl;
                    showUsage = 1;
                }
                break;
            case 'f':
                l_coarseness = atof(optarg);
                break;
            default:
                showUsage = 1;
                break;
        }
    }
    
    // Do several checks on supplied options
    if(!showUsage) {
        // Check for required arguments x and y cells unless we can get the info from a checkpoint file
        if((l_nX == 0 || l_nY == 0) && l_checkpointFileName.empty()) {
            std::cerr << "Missing required arguments: number of cells in X (-x) and Y (-y) direction" << std::endl;
            showUsage = 1;
        }
        // Check for required output base file name
        if(l_baseName.empty() && l_checkpointFileName.empty()) {
            std::cerr << "Missing required argument: base name of output file (-o)" << std::endl;
            showUsage = 1;
        }
        // Check for valid number of checkpoints
        if(l_numberOfCheckPoints <= 0) {
            std::cerr << "Invalid option argument: Number of checkpoints must be greater than zero (-n)" << std::endl;
            showUsage = 1;
        }
        
        if(l_coarseness < 1.0) {
            std::cerr << "Invalid option argument: The coarseness factor must be greater than or equal to 1.0 (-f)" << std::endl;
            showUsage = 1;
        }
        
        // Check if a checkpoint-file is given as input. If so, switch to checkpoint scenario
        if(!l_checkpointFileName.empty()) {
            l_scenarioName = SCENARIO_CHECKPOINT_TSUNAMI;
            
            // We handle the file name of checkpoint and output data files without the ".nc"
            // extension internally, so we're removing the extension here in case it is supplied
            int cpLength = l_checkpointFileName.length();
            if(l_checkpointFileName.substr(cpLength-3, 3).compare(".nc") == 0) {
                l_checkpointFileName.erase(cpLength-3, 3);
            }
            
            if(l_nX > 0 || l_nY > 0)
                std::cerr << "WARNING: Supplied number of grid cells will be ignored (reading from checkpoint)" << std::endl;
            if(l_simulationTime > 0.0)
                std::cerr << "WARNING: Supplied simulation time will be ignored (reading from checkpoint)" << std::endl;
        }
        
        if(l_scenarioName == SCENARIO_TSUNAMI) {
            // We've got no checkpoint and no artificial scenario
            // => Bathymetry and displacement data must be supplied
            if(l_bathymetryFileName.empty() || l_displacementFileName.empty()) {
                std::cerr << "Missing required argument: bathymetry (-i) and displacement (-d) files must be supplied" << std::endl;
                showUsage = 1;
            }
        } else {
            if(!l_bathymetryFileName.empty() || !l_displacementFileName.empty())
                std::cerr << "WARNING: Supplied bathymetry and displacement data will be ignored" << std::endl;
        }
#ifdef USEOPENCL
        if(l_maxGroupSize == 0 || (l_maxGroupSize & (l_maxGroupSize - 1))) {
            std::cout << "Group size must be greater than zero and a power of two!" << std::endl;
            showUsage = 1;
        }
#endif
    }
    
    if(showUsage) {
        std::cout << "Usage:" << std::endl;
        std::cout << "Simulating a tsunami with bathymetry and displacement input:" << std::endl;
        std::cout << "    ./SWE_<opt> -i <bathymetryfile> -d <displacementfile> [OPTIONS]" << std::endl;
        std::cout << "Resuming a crashed simulation from checkpoint file:" << std::endl;
        std::cout << "    ./SWE_<opt> -c <checkpointfile> [-o <outputfile>]" << std::endl;
        std::cout << "Simulating an artificial scenario:" << std::endl;
        std::cout << "    ./SWE_<opt> -s <scenarioname> [OPTIONS]" << std::endl;
        std::cout << "" << std::endl;
        std::cout << "Options:" << std::endl;
        std::cout << "    -o <filename>   The output file base name" << std::endl;
        std::cout << "        Note: If the file already exists it is assumed to be a checkpointfile" << std::endl;
        std::cout << "        from which to resume simulation. Input options are ignored then." << std::endl;
        std::cout << "    -x <num>        The number of cells in x-direction" << std::endl;
        std::cout << "    -y <num>        The number of cells in y-direction" << std::endl;
        std::cout << "    -n <num>        Number of checkpoints to be written" << std::endl;
        std::cout << "    -t <time>       Total simulation time" << std::endl;
        std::cout << "    -f <num>        Coarseness factor (> 1.0)" << std::endl;
        std::cout << "    -l <num>        Maximum number of computing devices (OpenCL only)" << std::endl;
        std::cout << "    -b <code>       Boundary Conditions" << std::endl;
        std::cout << "                    Codes: Combination of 'w' (WALL) and 'o' (OUTFLOW)" << std::endl;
        std::cout << "                      One char: Option for ALL boundaries" << std::endl;
        std::cout << "                      Two chars: Options for left/right and top/bottom boundaries" << std::endl;
        std::cout << "                      Four chars: Options for left, right, bottom, top boundaries" << std::endl;
        std::cout << "    -i <filename>   Name of bathymetry data file" << std::endl;
        std::cout << "    -d <filename>   Name of displacement data file" << std::endl;
        std::cout << "    -c <filename>   Name of checkpointfile" << std::endl;
        std::cout << "    -s <scenario>   Name of artificial scenario" << std::endl;
        std::cout << "                    Scenarios: 'artificialtsunami', 'partialdambreak'" << std::endl;
        std::cout << "" << std::endl;
        std::cout << "Notes when using a checkpointfile:" << std::endl;
        std::cout << "    -x, -y, -n, -t, -b, -i, -d, -s are ignored (values are read from checkpointfile)" << std::endl;
        std::cout << "    An output file (-o) can be specified. In that case, the checkpointfile" << std::endl;
        std::cout << "    is copied to that location and output is appended to the output file." << std::endl;
        std::cout << "    If no output file is specified, output is appended to the checkpointfile." << std::endl;
        std::cout << "" << std::endl;
        std::cout << "Example: " << std::endl; 
        std::cout << "./SWE_<compiler>_<build>_none_dimsplit -x 100 -y 200 -o out -i b.nc -d d.nc -n 50 -b owwo" << std::endl;
        std::cout << "    will simulate a tsunami scenario using bathymetry from 'b.nc' and displacements ";
        std::cout << "from 'd.nc' on a grid of size 100 x 200 using outflow conditions for left and ";
        std::cout << "top boundary and wall conditions for right and bottom boundary, writing 50 checkpoints ";
        std::cout << "to out_<num>.nc" << std::endl;
        
        return 0;
    }
    
    //! output file basename (with block coordinates)
    std::string l_outputFileName = generateBaseFileName(l_baseName,0,0);
    
#ifdef WRITENETCDF
    if(l_scenarioName != SCENARIO_CHECKPOINT_TSUNAMI) {
        // This is a tsunami scenario, check if the output file (with .nc-extension) exists
        // In that case switch to checkpoint scenario
        int ncOutputFile;
        int status = nc_open((l_outputFileName + ".nc").c_str(), NC_NOWRITE, &ncOutputFile);
        if(status == NC_NOERR) {
            // Output file exists and is a NetCDF file => switch to checkpointing
            l_scenarioName = SCENARIO_CHECKPOINT_TSUNAMI;
            l_checkpointFileName = l_outputFileName;
            nc_close(ncOutputFile);
        }
    }
#endif
    
    //! Pointer to instance of chosen scenario
    SWE_Scenario *l_scenario;
    
    // Create scenario according to chosen options
    switch(l_scenarioName) {
#ifdef WRITENETCDF
        case SCENARIO_TSUNAMI:
            l_scenario = new SWE_TsunamiScenario(l_bathymetryFileName, l_displacementFileName);
            
            // overwrite boundary conditions from scenario in case they have 
            // been explicitly set using command line arguments
            if(l_overwriteBoundaryTypes)
                ((SWE_TsunamiScenario *)l_scenario)->setBoundaryTypes(l_boundaryTypes);
            break;
        case SCENARIO_CHECKPOINT_TSUNAMI:
            l_scenario = new SWE_CheckpointTsunamiScenario(l_checkpointFileName + ".nc");
            
            // Read number if grid cells from checkpoint
            ((SWE_CheckpointTsunamiScenario *)l_scenario)->getNumberOfCells(l_nX, l_nY);
            
            if(l_overwriteBoundaryTypes)
                std::cerr << "WARNING: Loading checkpointed Simulation does not support "
                          << "explicitly setting boundary conditions" << std::endl;
            break;
#endif
        case SCENARIO_ARTIFICIAL_TSUNAMI:
            l_scenario = new SWE_ArtificialTsunamiScenario();

            // overwrite boundary conditions from scenario in case they have 
            // been explicitly set using command line arguments
            if(l_overwriteBoundaryTypes)
                ((SWE_ArtificialTsunamiScenario *)l_scenario)->setBoundaryTypes(l_boundaryTypes);
            break;
        case SCENARIO_PARTIAL_DAMBREAK:
            l_scenario = new SWE_PartialDambreak();
            if(l_overwriteBoundaryTypes)
                std::cerr << "WARNING: PartialDambreak-Scenario does not support "
                          << "explicitly setting boundary conditions" << std::endl;
            break;
        default:
            std::cerr << "Invalid Scenario" << std::endl;
            exit(1);
            break;
    }

    //! size of a single cell in x- and y-direction
    float l_dX, l_dY;
    
    // compute the size of a single cell
    l_dX = (l_scenario->getBoundaryPos(BND_RIGHT) - l_scenario->getBoundaryPos(BND_LEFT) )/l_nX;
    l_dY = (l_scenario->getBoundaryPos(BND_TOP) - l_scenario->getBoundaryPos(BND_BOTTOM) )/l_nY;
    
    //! Dimensional Splitting Block
#ifndef USEOPENCL
    SWE_DimensionalSplitting l_dimensionalSplitting(l_nX, l_nY, l_dX, l_dY);
#else
    SWE_DimensionalSplittingOpenCL l_dimensionalSplitting(l_nX, l_nY, l_dX, l_dY, 0, l_maxDevices, l_kernelType, l_maxGroupSize);
    l_dimensionalSplitting.printDeviceInformation();
#endif
    
    //! origin of the simulation domain in x- and y-direction
    float l_originX, l_originY;

    // get the origin from the scenario
    l_originX = l_scenario->getBoundaryPos(BND_LEFT);
    l_originY = l_scenario->getBoundaryPos(BND_BOTTOM);

    // initialize the wave propagation block
    l_dimensionalSplitting.initScenario(l_originX, l_originY, *l_scenario);
    
    //! time when the simulation ends.
    float l_endSimulation;
    if(l_simulationTime <= 0.0) {
        // We haven't got a valid simulation time as arguments, use the pre-defied one from scenario
        l_endSimulation = l_scenario->endSimulation();
    } else {
        // Use time given from command line
        l_endSimulation = l_simulationTime;
    }
    
    //! simulation time.
    float l_t = 0.0;
    
    //! checkpoint counter
    int l_checkpoint = 1;

#ifdef WRITENETCDF
    if(l_scenarioName == SCENARIO_CHECKPOINT_TSUNAMI) {
        // read total number of checkpoints
        l_numberOfCheckPoints = ((SWE_CheckpointTsunamiScenario *)l_scenario)->getNumberOfCheckpoints();
        
        // load last checkpoint and timestep from scenario (checkpoint-file)
        ((SWE_CheckpointTsunamiScenario *)l_scenario)->getLastCheckpoint(l_checkpoint, l_t);
        l_checkpoint++;
        
        // forace coarseness of 1 if reading from checkpoint data
        l_coarseness = 1.0;
    }
#endif
    
    // read actual boundary types (command line merged with scenario)
    l_boundaryTypes[BND_LEFT] = l_scenario->getBoundaryType(BND_LEFT);
    l_boundaryTypes[BND_RIGHT] = l_scenario->getBoundaryType(BND_RIGHT);
    l_boundaryTypes[BND_BOTTOM] = l_scenario->getBoundaryType(BND_BOTTOM);
    l_boundaryTypes[BND_TOP] = l_scenario->getBoundaryType(BND_TOP);
    
    //! checkpoints when output files are written.
    float* l_checkPoints = new float[l_numberOfCheckPoints+1];
    
    // compute the checkpoints in time
    for(int cp = 0; cp <= l_numberOfCheckPoints; cp++) {
        l_checkPoints[cp] = cp*(l_endSimulation/l_numberOfCheckPoints);
    }
    
    // Init fancy progressbar
    tools::ProgressBar progressBar(l_endSimulation);
    
    // write the output at time zero
    tools::Logger::logger.printOutputTime((float) l_t);
    progressBar.update(l_t);
    
    //boundary size of the ghost layers
    io::BoundarySize l_boundarySize = {{1, 1, 1, 1}};
    
    // Delete scenarioto free resources and close opened files
    delete l_scenario;
    
#ifdef WRITENETCDF
    if(l_scenarioName == SCENARIO_CHECKPOINT_TSUNAMI) {
        if(l_baseName.empty()) {
            // If there is no output file name given, use the checkpoint file
            l_outputFileName = l_checkpointFileName;
        } else if(l_outputFileName.compare(l_checkpointFileName) != 0) {
            // output file name given and it is not equal to the checkpoint file
            // therefore, we have to make a copy of our checkpointfile
            // in order to continue the simulation
            std::ifstream src((l_checkpointFileName + ".nc").c_str());
            std::ofstream dst((l_outputFileName + ".nc").c_str());
            dst << src.rdbuf();
        }
    }

    //construct a NetCdfWriter
    io::NetCdfWriter l_writer( l_outputFileName,
        l_dimensionalSplitting.getBathymetry(),
  		l_boundarySize,
  		l_nX, l_nY,
  		l_dX, l_dY,
  		l_originX, l_originY,
        l_coarseness);
        
        l_writer.writeSimulationInfo(l_numberOfCheckPoints, l_endSimulation, l_boundaryTypes);
#else
    // consturct a VtkWriter
    io::VtkWriter l_writer( l_outputFileName,
  		l_dimensionalSplitting.getBathymetry(),
  		l_boundarySize,
  		l_nX, l_nY,
  		l_dX, l_dY,
        0, 0,
        l_coarseness);
#endif
    if(l_scenarioName != SCENARIO_CHECKPOINT_TSUNAMI) {
        // Write zero time step
        l_writer.writeTimeStep( l_dimensionalSplitting.getWaterHeight(),
                                l_dimensionalSplitting.getDischarge_hu(),
                                l_dimensionalSplitting.getDischarge_hv(), 
                                (float) 0.);
    }
        
    /**
     * Simulation.
     */
    // print the start message and reset the wall clock time
    progressBar.clear();
    tools::Logger::logger.printStartMessage();
    tools::Logger::logger.initWallClockTime(time(NULL));
    
    progressBar.update(l_t);
    
    unsigned int l_iterations = 0;
    
    // loop over checkpoints
    while(l_checkpoint <= l_numberOfCheckPoints) {
        
        // do time steps until next checkpoint is reached
        while( l_t < l_checkPoints[l_checkpoint] ) {
            // set values in ghost cells:
            l_dimensionalSplitting.setGhostLayer();
            
            // reset the cpu clock
            tools::Logger::logger.resetCpuClockToCurrentTime();
            
            // compute numerical flux on each edge
            l_dimensionalSplitting.computeNumericalFluxes();
            
            //! maximum allowed time step width.
            float l_maxTimeStepWidth = l_dimensionalSplitting.getMaxTimestep();
            
            // update the cell values
            l_dimensionalSplitting.updateUnknowns(l_maxTimeStepWidth);
            
            // update the cpu time in the logger
            tools::Logger::logger.updateCpuTime();
            
            // update simulation time with time step width.
            l_t += l_maxTimeStepWidth;
            l_iterations++;
            
            // print the current simulation time
            progressBar.clear();
            tools::Logger::logger.printSimulationTime(l_t);
            progressBar.update(l_t);
        }
        // print current simulation time of the output
        progressBar.clear();
        tools::Logger::logger.printOutputTime(l_t);
        progressBar.update(l_t);
        
        // write output
        l_writer.writeTimeStep( l_dimensionalSplitting.getWaterHeight(),
                              l_dimensionalSplitting.getDischarge_hu(),
                              l_dimensionalSplitting.getDischarge_hv(),
                              l_t);
        
        l_checkpoint++;
    }
    
    /**
     * Finalize.
     */
    // write the statistics message
    progressBar.clear();
    tools::Logger::logger.printStatisticsMessage();
    
    // print the cpu time
    tools::Logger::logger.printCpuTime();
    
    // print the wall clock time (includes plotting)
    tools::Logger::logger.printWallClockTime(time(NULL));
    
    // printer iteration counter
    tools::Logger::logger.printIterationsDone(l_iterations);
    
    // print average time per cell per iteration
    tools::Logger::logger.printAverageCPUTimePerCellPerIteration(l_iterations, l_nX*(l_nY+2)); 
    
#ifdef USEOPENCL
    // print opencl stats
    l_dimensionalSplitting.printProfilingInformation();
#endif
    
    return 0;
}
Exemplo n.º 3
0
/**
 * Main program for the simulation on a single SWE_WavePropagationBlock.
 */
int main( int argc, char** argv ) {
  /**
   * Initialization.
   */
  //! MPI Rank of a process.
  int l_mpiRank;
  //! number of MPI processes.
  int l_numberOfProcesses;

  // initialize MPI
  if ( MPI_Init(&argc,&argv) != MPI_SUCCESS ) {
    std::cerr << "MPI_Init failed." << std::endl;
  }

  // determine local MPI rank
  MPI_Comm_rank(MPI_COMM_WORLD,&l_mpiRank);
  // determine total number of processes
  MPI_Comm_size(MPI_COMM_WORLD,&l_numberOfProcesses);

  // initialize a logger for every MPI process
  tools::Logger::logger.setProcessRank(l_mpiRank);

  // print the welcome message
  tools::Logger::logger.printWelcomeMessage();

  // set current wall clock time within the solver
  tools::Logger::logger.initWallClockTime( MPI_Wtime() );
  //print the number of processes
  tools::Logger::logger.printNumberOfProcesses(l_numberOfProcesses);

  // check if the necessary command line input parameters are given
  #ifndef READXML
  std::vector<std::string> vargs;
  vargs.push_back(argv[0]);
  vargs.push_back("grid_size_x");
  vargs.push_back("grid_size_y");
  vargs.push_back("output_basepath");
  vargs.push_back("output_steps_count");
  #ifdef ASAGI
  vargs.push_back("bathymetry_file");
  vargs.push_back("displacement_file");
  vargs.push_back("simul_area_min_x");
  vargs.push_back("simul_area_max_x");
  vargs.push_back("simul_area_min_y");
  vargs.push_back("simul_area_max_y");
  vargs.push_back("simul_duration_secs");
  #endif
  if (argc != vargs.size()) {
    std::cout << "Usage: " << vargs[0];
    for (int i = 1, e = vargs.size(); i != e; i++)
      std::cout << " <" << vargs[i] << ">";
    std::cout << std::endl << std::flush;

    MPI_Finalize();
    return 1;
  }
  #endif

  //! total number of grid cell in x- and y-direction.
  int l_nX, l_nY;

  //! l_baseName of the plots.
  std::string l_baseName;

  // read command line parameters
  #ifndef READXML
  l_nX = atoi(ARG("grid_size_x"));
  l_nY = atoi(ARG("grid_size_y"));
  l_baseName = std::string(ARG("output_basepath"));
  #endif

  // read xml file
  #ifdef READXML
  assert(false); //TODO: not implemented.
  if(argc != 2) {
    l_sweLogger.printString("Aborting. Please provide a proper input file.");
    l_sweLogger.printString("Example: ./SWE_gnu_debug_none_augrie config.xml");
    return 1;
  }
  l_sweLogger.printString("Reading xml-file.");

  std::string l_xmlFile = std::string(argv[1]);
  l_sweLogger.printString(l_xmlFile);

  CXMLConfig l_xmlConfig;
  l_xmlConfig.loadConfig(l_xmlFile.c_str());
  #endif // READXML

  //! number of SWE_Blocks in x- and y-direction.
  int l_blocksX, l_blocksY;

  // determine the layout of MPI-ranks: use l_blocksX*l_blocksY grid blocks
  l_blocksY = computeNumberOfBlockRows(l_numberOfProcesses);
  l_blocksX = l_numberOfProcesses/l_blocksY;

  // print information about the grid
  tools::Logger::logger.printNumberOfCells(l_nX, l_nY);
  tools::Logger::logger.printNumberOfBlocks(l_blocksX, l_blocksY);


  //! local position of each MPI process in x- and y-direction.
  int l_blockPositionX, l_blockPositionY;

  // determine local block coordinates of each SWE_Block
  l_blockPositionX = l_mpiRank / l_blocksY;
  l_blockPositionY = l_mpiRank % l_blocksY;

  #ifdef ASAGI
  /*
   * Pixel node registration used [Cartesian grid]
   * Grid file format: nf = GMT netCDF format (float)  (COARDS-compliant)
   * x_min: -500000 x_max: 6500000 x_inc: 500 name: x nx: 14000
   * y_min: -2500000 y_max: 1500000 y_inc: 500 name: y ny: 8000
   * z_min: -6.48760175705 z_max: 16.1780223846 name: z
   * scale_factor: 1 add_offset: 0
   * mean: 0.00217145586762 stdev: 0.245563641735 rms: 0.245573241263
   */

  //simulation area
  float simulationArea[4];
  simulationArea[0] = atof(ARG("simul_area_min_x"));
  simulationArea[1] = atof(ARG("simul_area_max_x"));
  simulationArea[2] = atof(ARG("simul_area_min_y"));
  simulationArea[3] = atof(ARG("simul_area_max_y"));

  float simulationDuration = atof(ARG("simul_duration_secs"));

  SWE_AsagiScenario l_scenario(ARG("bathymetry_file"), ARG("displacement_file"),
                               simulationDuration, simulationArea);
  #else
  // create a simple artificial scenario
  SWE_BathymetryDamBreakScenario l_scenario;
  #endif

  //! number of checkpoints for visualization (at each checkpoint in time, an output file is written).
  int l_numberOfCheckPoints = atoi(ARG("output_steps_count"));

  //! number of grid cells in x- and y-direction per process.
  int l_nXLocal, l_nYLocal;

  //! size of a single cell in x- and y-direction
  float l_dX, l_dY;

  // compute local number of cells for each SWE_Block
  l_nXLocal = (l_blockPositionX < l_blocksX-1) ? l_nX/l_blocksX : l_nX - (l_blocksX-1)*(l_nX/l_blocksX);
  l_nYLocal = (l_blockPositionY < l_blocksY-1) ? l_nY/l_blocksY : l_nY - (l_blocksY-1)*(l_nY/l_blocksY);

  // compute the size of a single cell
  l_dX = (l_scenario.getBoundaryPos(BND_RIGHT) - l_scenario.getBoundaryPos(BND_LEFT) )/l_nX;
  l_dY = (l_scenario.getBoundaryPos(BND_TOP) - l_scenario.getBoundaryPos(BND_BOTTOM) )/l_nY;

  // print information about the cell size and local number of cells
  tools::Logger::logger.printCellSize(l_dX, l_dY);
  tools::Logger::logger.printNumberOfCellsPerProcess(l_nXLocal, l_nYLocal);

  //! origin of the simulation domain in x- and y-direction
  float l_originX, l_originY;

  // get the origin from the scenario
  l_originX = l_scenario.getBoundaryPos(BND_LEFT) + l_blockPositionX*l_nXLocal*l_dX;;
  l_originY = l_scenario.getBoundaryPos(BND_BOTTOM) + l_blockPositionY*l_nYLocal*l_dY;

  // create a single wave propagation block
  #ifndef CUDA
  SWE_WavePropagationBlock l_wavePropgationBlock(l_nXLocal,l_nYLocal,l_dX,l_dY);
  #else
  //! number of CUDA devices per node TODO: hardcoded
  int l_cudaDevicesPerNode = 7;

  //! the id of the node local GPU
  int l_cudaDeviceId = l_mpiRank % l_cudaDevicesPerNode;

  SWE_BlockCUDA::init(l_cudaDeviceId);

  SWE_WavePropagationBlockCuda l_wavePropgationBlock(l_nXLocal,l_nYLocal,l_dX,l_dY);
  #endif

  // initialize the wave propgation block
  l_wavePropgationBlock.initScenario(l_originX, l_originY, l_scenario, true);

  //! time when the simulation ends.
  float l_endSimulation = l_scenario.endSimulation();

  //! checkpoints when output files are written.
  float* l_checkPoints = new float[l_numberOfCheckPoints+1];

  // compute the checkpoints in time
  for(int cp = 0; cp <= l_numberOfCheckPoints; cp++) {
     l_checkPoints[cp] = cp*(l_endSimulation/l_numberOfCheckPoints);
  }

  /*
   * Connect SWE blocks at boundaries
   */
  // left and right boundaries
  tools::Logger::logger.printString("Connecting SWE blocks at left boundaries.");
  SWE_Block1D* l_leftInflow  = l_wavePropgationBlock.grabGhostLayer(BND_LEFT);
  SWE_Block1D* l_leftOutflow = l_wavePropgationBlock.registerCopyLayer(BND_LEFT);
  if (l_blockPositionX == 0)
    l_wavePropgationBlock.setBoundaryType(BND_LEFT, OUTFLOW);

  tools::Logger::logger.printString("Connecting SWE blocks at right boundaries.");
  SWE_Block1D* l_rightInflow  = l_wavePropgationBlock.grabGhostLayer(BND_RIGHT);
  SWE_Block1D* l_rightOutflow = l_wavePropgationBlock.registerCopyLayer(BND_RIGHT);
  if (l_blockPositionX == l_blocksX-1)
    l_wavePropgationBlock.setBoundaryType(BND_RIGHT, OUTFLOW);

  // bottom and top boundaries
  tools::Logger::logger.printString("Connecting SWE blocks at bottom boundaries.");
  SWE_Block1D* l_bottomInflow  = l_wavePropgationBlock.grabGhostLayer(BND_BOTTOM);
  SWE_Block1D* l_bottomOutflow = l_wavePropgationBlock.registerCopyLayer(BND_BOTTOM);
  if (l_blockPositionY == 0)
    l_wavePropgationBlock.setBoundaryType(BND_BOTTOM, OUTFLOW);

  tools::Logger::logger.printString("Connecting SWE blocks at top boundaries.");
  SWE_Block1D* l_topInflow  = l_wavePropgationBlock.grabGhostLayer(BND_TOP);
  SWE_Block1D* l_topOutflow = l_wavePropgationBlock.registerCopyLayer(BND_TOP);
  if (l_blockPositionY == l_blocksY-1)
    l_wavePropgationBlock.setBoundaryType(BND_TOP, OUTFLOW);

  /*
   * The grid is stored column wise in memory:
   *
   *        ************************** . . . **********
   *        *       *  ny+2 *2(ny+2)*         * (ny+1)*
   *        *  ny+1 * +ny+1 * +ny+1 *         * (ny+2)*
   *        *       *       *       *         * +ny+1 *
   *        ************************** . . . **********
   *        *       *       *       *         *       *
   *        .       .       .       .         .       .
   *        .       .       .       .         .       .
   *        .       .       .       .         .       .
   *        *       *       *       *         *       *
   *        ************************** . . . **********
   *        *       *  ny+2 *2(ny+2)*         * (ny+1)*
   *        *   1   *   +1  *   +1  *         * (ny+2)*
   *        *       *       *       *         *   +1  *
   *        ************************** . . . **********
   *        *       *  ny+2 *2(ny+2)*         * (ny+1)*
   *        *   0   *   +0  *   +0  *         * (ny+2)*
   *        *       *       *       *         *   +0  *
   *        ************************** . . . ***********
   *
   *
   *  -> The stride for a row is ny+2, because we have to jump over a whole column
   *     for every row-element. This holds only in the CPU-version, in CUDA a buffer is implemented.
   *     See SWE_BlockCUDA.hh/.cu for details.
   *  -> The stride for a column is 1, because we can access the elements linear in memory.
   */
  //! MPI row-vector: l_nXLocal+2 blocks, 1 element per block, stride of l_nYLocal+2
  MPI_Datatype l_mpiRow;
  #ifndef CUDA
  MPI_Type_vector(l_nXLocal+2, 1          , l_nYLocal+2, MPI_FLOAT, &l_mpiRow);
  #else
  MPI_Type_vector(1,           l_nXLocal+2, 1          , MPI_FLOAT, &l_mpiRow);
  #endif
  MPI_Type_commit(&l_mpiRow);

  //! MPI row-vector: 1 block, l_nYLocal+2 elements per block, stride of 1
  MPI_Datatype l_mpiCol;
  MPI_Type_vector(1,           l_nYLocal+2, 1,           MPI_FLOAT, &l_mpiCol);
  MPI_Type_commit(&l_mpiCol);

  //! MPI ranks of the neighbors
  int l_leftNeighborRank, l_rightNeighborRank, l_bottomNeighborRank, l_topNeighborRank;

  // compute MPI ranks of the neighbour processes
  l_leftNeighborRank   = (l_blockPositionX > 0) ? l_mpiRank-l_blocksY : MPI_PROC_NULL;
  l_rightNeighborRank  = (l_blockPositionX < l_blocksX-1) ? l_mpiRank+l_blocksY : MPI_PROC_NULL;
  l_bottomNeighborRank = (l_blockPositionY > 0) ? l_mpiRank-1 : MPI_PROC_NULL;
  l_topNeighborRank    = (l_blockPositionY < l_blocksY-1) ? l_mpiRank+1 : MPI_PROC_NULL;

  // print the MPI grid
  tools::Logger::logger.cout() << "neighbors: "
                     << l_leftNeighborRank << " (left), "
                     << l_rightNeighborRank << " (right), "
                     << l_bottomNeighborRank << " (bottom), "
                     << l_topNeighborRank << " (top)" << std::endl;

  // intially exchange ghost and copy layers
  exchangeLeftRightGhostLayers( l_leftNeighborRank,  l_leftInflow,  l_leftOutflow,
                  l_rightNeighborRank, l_rightInflow, l_rightOutflow,
                  l_mpiCol );

  exchangeBottomTopGhostLayers( l_bottomNeighborRank, l_bottomInflow, l_bottomOutflow,
                  l_topNeighborRank,    l_topInflow,    l_topOutflow,
                  l_mpiRow );

  // Init fancy progressbar
  tools::ProgressBar progressBar(l_endSimulation, l_mpiRank);

  // write the output at time zero
  tools::Logger::logger.printOutputTime(0);
  progressBar.update(0.);

  std::string l_fileName = generateBaseFileName(l_baseName,l_blockPositionX,l_blockPositionY);
  //boundary size of the ghost layers
  io::BoundarySize l_boundarySize = {{1, 1, 1, 1}};
#ifdef WRITENETCDF
  //construct a NetCdfWriter
  io::NetCdfWriter l_writer( l_fileName,
		  l_wavePropgationBlock.getBathymetry(),
		  l_boundarySize,
		  l_nXLocal, l_nYLocal,
		  l_dX, l_dY,
          l_originX, l_originY );
#else
  // Construct a VtkWriter
  io::VtkWriter l_writer( l_fileName,
		  l_wavePropgationBlock.getBathymetry(),
		  l_boundarySize,
		  l_nXLocal, l_nYLocal,
		  l_dX, l_dY,
		  l_blockPositionX*l_nXLocal, l_blockPositionY*l_nYLocal );
#endif
  // Write zero time step
  l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                          l_wavePropgationBlock.getDischarge_hu(),
                          l_wavePropgationBlock.getDischarge_hv(),
                          (float) 0.);
  /**
   * Simulation.
   */
  // print the start message and reset the wall clock time
  progressBar.clear();
  tools::Logger::logger.printStartMessage();
  tools::Logger::logger.initWallClockTime(time(NULL));

  //! simulation time.
  float l_t = 0.0;
  progressBar.update(l_t);

  unsigned int l_iterations = 0;

  // loop over checkpoints
  for(int c=1; c<=l_numberOfCheckPoints; c++) {

    // do time steps until next checkpoint is reached
    while( l_t < l_checkPoints[c] ) {
      //reset CPU-Communication clock
      tools::Logger::logger.resetCpuCommunicationClockToCurrentTime();

      // exchange ghost and copy layers
      exchangeLeftRightGhostLayers( l_leftNeighborRank,  l_leftInflow,  l_leftOutflow,
                      l_rightNeighborRank, l_rightInflow, l_rightOutflow,
                      l_mpiCol );

      exchangeBottomTopGhostLayers( l_bottomNeighborRank, l_bottomInflow, l_bottomOutflow,
                      l_topNeighborRank,    l_topInflow,    l_topOutflow,
                      l_mpiRow );

      // reset the cpu clock
      tools::Logger::logger.resetCpuClockToCurrentTime();

      // set values in ghost cells
      l_wavePropgationBlock.setGhostLayer();

      // compute numerical flux on each edge
      l_wavePropgationBlock.computeNumericalFluxes();

      //! maximum allowed time step width within a block.
      float l_maxTimeStepWidth = l_wavePropgationBlock.getMaxTimestep();

      // update the cpu time in the logger
      tools::Logger::logger.updateCpuTime();

      //! maximum allowed time steps of all blocks
      float l_maxTimeStepWidthGlobal;

      // determine smallest time step of all blocks
      MPI_Allreduce(&l_maxTimeStepWidth, &l_maxTimeStepWidthGlobal, 1, MPI_FLOAT, MPI_MIN, MPI_COMM_WORLD);

      // reset the cpu time
      tools::Logger::logger.resetCpuClockToCurrentTime();

      // update the cell values
      l_wavePropgationBlock.updateUnknowns(l_maxTimeStepWidthGlobal);

      // update the cpu and CPU-communication time in the logger
      tools::Logger::logger.updateCpuTime();
      tools::Logger::logger.updateCpuCommunicationTime();

      // update simulation time with time step width.
      l_t += l_maxTimeStepWidthGlobal;
      l_iterations++;

      // print the current simulation time
      progressBar.clear();
      tools::Logger::logger.printSimulationTime(l_t);
      progressBar.update(l_t);
    }

    // print current simulation time
    progressBar.clear();
    tools::Logger::logger.printOutputTime(l_t);
    progressBar.update(l_t);

    // write output
    l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                            l_wavePropgationBlock.getDischarge_hu(),
                            l_wavePropgationBlock.getDischarge_hv(),
                            l_t);
  }

  /**
   * Finalize.
   */
#ifdef ASAGI
  // Free ASAGI resources
  l_scenario.deleteGrids();
#endif

  progressBar.clear();

  // write the statistics message
  tools::Logger::logger.printStatisticsMessage();

  // print the cpu time
  tools::Logger::logger.printCpuTime("CPU time");

  // print CPU + Communication time
  tools::Logger::logger.printCpuCommunicationTime();

  // print the wall clock time (includes plotting)
  tools::Logger::logger.printWallClockTime(time(NULL));

  // printer iteration counter
  tools::Logger::logger.printIterationsDone(l_iterations);

  // print the finish message
  tools::Logger::logger.printFinishMessage();

  // finalize MPI execution
  MPI_Finalize();

  return 0;
}
Exemplo n.º 4
0
/**
 * Main program for the simulation of dimensionalsplitting.
 */
int main( int argc, char** argv ) {
  /**
   * Initialization.
   */
  // Parse command line parameters
  tools::Args args;
  #ifndef READXML
  args.addOption("grid-size-x", 'x', "Number of cells in x direction");
  args.addOption("grid-size-y", 'y', "Number of cells in y direction");
  args.addOption("output-basepath", 'o', "Output base file name");

  //add Options for Simulation Time and Boundary Condition arguments
  args.addOption("simulated-time", 't', "Simulation time");
  args.addOption("boundary-condition", 'b', "Boundary Condition");
  #endif

  tools::Args::Result ret = args.parse(argc, argv);

  switch (ret)
  {
  case tools::Args::Error:
	  return 1;
  case tools::Args::Help:
	  return 0;
  }

  //! number of grid cells in x- and y-direction.
  int l_nX, l_nY;

  //! l_baseName of the plots.
  std::string l_baseName;

  int l_simTime;
  BoundaryType l_boundaryCond;

  // read command line parameters
  #ifndef READXML
  l_nX = args.getArgument<int>("grid-size-x");
  l_nY = args.getArgument<int>("grid-size-y");
  l_baseName = args.getArgument<std::string>("output-basepath");

  //read simulation-time and boundary-condition arguments
  l_simTime= args.getArgument<int>("simulation-time");
  std::string boundaryCondString= args.getArgument<std::string>("boundary-condition");
  if(boundaryCondString.compare("WALL")){
	  l_boundaryCond=WALL;
  }else if(boundaryCondString.compare("INFLOW")){
	  l_boundaryCond=INFLOW;
  }else if(boundaryCondString.compare("CONNECT")){
	  l_boundaryCond=CONNECT;
  }else if(boundaryCondString.compare("PASSIVE")){
	  l_boundaryCond=PASSIVE;
  }else{//Outflow per default
	  l_boundaryCond=OUTFLOW;
  }
  #endif

  // create a simple artificial scenario
  //SWE_RadialDamBreakScenario l_scenario;
  //SWE_ArtificialTsunamiScenario l_scenario;

  //TsunamiScenario with NetCDF
  TsunamiScenario l_scenario;
  l_scenario.simTime=l_simTime;
  l_scenario.boundaryCond=l_boundaryCond;


  //! number of checkpoints for visualization (at each checkpoint in time, an output file is written).
  int l_numberOfCheckPoints = 100;

  //! size of a single cell in x- and y-direction
  float l_dX, l_dY;

  // compute the size of a single cell
  l_dX = (l_scenario.getBoundaryPos(BND_RIGHT) - l_scenario.getBoundaryPos(BND_LEFT) )/l_nX;
  l_dY = (l_scenario.getBoundaryPos(BND_TOP) - l_scenario.getBoundaryPos(BND_BOTTOM) )/l_nY;

  // create a single wave propagation block
  SWE_DimensionalSplitting l_wavePropgationBlock(l_nX,l_nY,l_dX,l_dY);


  //! origin of the simulation domain in x- and y-direction
  float l_originX, l_originY;

  // get the origin from the scenario
  l_originX = l_scenario.getBoundaryPos(BND_LEFT);
  l_originY = l_scenario.getBoundaryPos(BND_BOTTOM);


  // initialize the wave propagation block
  l_wavePropgationBlock.initScenario(l_originX, l_originY, l_scenario);


  //! time when the simulation ends.
  float l_endSimulation = l_scenario.endSimulation();


  //! checkpoints when output files are written.
  float* l_checkPoints = new float[l_numberOfCheckPoints+1];

  // compute the checkpoints in time
  for(int cp = 0; cp <= l_numberOfCheckPoints; cp++) {
     l_checkPoints[cp] = cp*(l_endSimulation/l_numberOfCheckPoints);
  }

  // Init fancy progressbar
  //tools::ProgressBar progressBar(l_endSimulation);

  // write the output at time zero
  tools::Logger::logger.printOutputTime((float) 0.);
  //progressBar.update(0.);

  std::string l_fileName = generateBaseFileName(l_baseName,0,0);
  //boundary size of the ghost layers
  io::BoundarySize l_boundarySize = {{1, 1, 1, 1}};

  // consturct a VtkWriter
  io::VtkWriter l_writer( l_fileName,
		  l_wavePropgationBlock.getBathymetry(),
		  l_boundarySize,
		  l_nX, l_nY,
		  l_dX, l_dY );

  // Write zero time step
  l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                          l_wavePropgationBlock.getDischarge_hu(),
                          l_wavePropgationBlock.getDischarge_hv(),
                          (float) 0.);


  /**
   * Simulation.
   */
  // print the start message and reset the wall clock time
  //progressBar.clear();
  tools::Logger::logger.printStartMessage();
  tools::Logger::logger.initWallClockTime(time(NULL));

  //! simulation time.
  float l_t = 0.0;

  //progressBar.update(l_t);

  unsigned int l_iterations = 0;

  // loop over checkpoints
  for(int c=1; c<=l_numberOfCheckPoints; c++) {

    // do time steps until next checkpoint is reached
    while( l_t < l_checkPoints[c] ) {
      // set values in ghost cells:
      l_wavePropgationBlock.setGhostLayer();

      // reset the cpu clock
      tools::Logger::logger.resetClockToCurrentTime("Cpu");

      // compute numerical flux on each edge
      l_wavePropgationBlock.computeNumericalFluxes();


      //! maximum allowed time step width.
      float l_maxTimeStepWidth = l_wavePropgationBlock.getMaxTimestep();

      // update the cell values
      l_wavePropgationBlock.updateUnknowns(l_maxTimeStepWidth);

      // update the cpu time in the logger
      tools::Logger::logger.updateTime("Cpu");


      // update simulation time with time step width.
      l_t += l_maxTimeStepWidth;
      l_iterations++;

      // print the current simulation time
      //progressBar.clear();
      tools::Logger::logger.printSimulationTime(l_t);
      //progressBar.update(l_t);
    }

    // print current simulation time of the output
    //progressBar.clear();
    tools::Logger::logger.printOutputTime(l_t);
    //progressBar.update(l_t);


    // write output
    l_writer.writeTimeStep( l_wavePropgationBlock.getWaterHeight(),
                            l_wavePropgationBlock.getDischarge_hu(),
                            l_wavePropgationBlock.getDischarge_hv(),
                            l_t);

  }


 /**
   * Finalize.
   */
  // write the statistics message
  //progressBar.clear();
  tools::Logger::logger.printStatisticsMessage();

  // print the cpu time
  tools::Logger::logger.printTime("Cpu", "CPU time");

  // print the wall clock time (includes plotting)
  tools::Logger::logger.printWallClockTime(time(NULL));

  // printer iteration counter
  tools::Logger::logger.printIterationsDone(l_iterations);

  return 0;
}