Exemple #1
0
void setup_coeffs4(BoxArray& bs, MultiFab& alpha, MultiFab& beta, const Geometry& geom)
{
  ParmParse pp;

  Real sigma, w;
  pp.get("sigma", sigma);
  pp.get("w", w);

  for ( MFIter mfi(alpha); mfi.isValid(); ++mfi ) {
    const Box& bx = mfi.validbox();

    const int* alo = alpha[mfi].loVect();
    const int* ahi = alpha[mfi].hiVect();
    const Box& abx = alpha[mfi].box();
    FORT_SET_ALPHA(alpha[mfi].dataPtr(),ARLIM(alo),ARLIM(ahi),
    		   abx.loVect(),abx.hiVect(),dx);

    const int* clo = beta[mfi].loVect();
    const int* chi = beta[mfi].hiVect();

    FORT_SET_CC_COEF(beta[mfi].dataPtr(),ARLIM(clo),ARLIM(chi),
		     bx.loVect(),bx.hiVect(),dx, sigma, w);
  }

  if (plot_beta == 1) {
    writePlotFile("BETA4", beta, geom);
  }
}
Exemple #2
0
void setup_coeffs(BoxArray& bs, MultiFab& alpha, PArray<MultiFab>& beta, 
		  const Geometry& geom, MultiFab& cc_coef)
{
  BL_PROFILE("setup_coeffs()");
  ParmParse pp;

  Real sigma, w;
  pp.get("sigma", sigma);
  pp.get("w", w);

  for ( MFIter mfi(alpha); mfi.isValid(); ++mfi ) {
    const Box& bx = mfi.validbox();

    const int* alo = alpha[mfi].loVect();
    const int* ahi = alpha[mfi].hiVect();
    FORT_SET_ALPHA(alpha[mfi].dataPtr(),ARLIM(alo),ARLIM(ahi),
    		   bx.loVect(),bx.hiVect(),dx);

    const int* clo = cc_coef[mfi].loVect();
    const int* chi = cc_coef[mfi].hiVect();
    FORT_SET_CC_COEF(cc_coef[mfi].dataPtr(),ARLIM(clo),ARLIM(chi),
		     bx.loVect(),bx.hiVect(),dx, sigma, w);
  }

  BoxLib::average_cellcenter_to_face(beta, cc_coef, geom);

  if (plot_beta == 1) {
    writePlotFile("BETA", cc_coef, geom);
  }
}
Exemple #3
0
void setup_rhs(MultiFab& rhs, const Geometry& geom)
{
  BL_PROFILE("setup_rhs()");
  ParmParse pp;

  Real a, b, sigma, w;
  pp.get("a",  a);
  pp.get("b",  b);
  pp.get("sigma", sigma);
  pp.get("w", w);

  int ibnd = static_cast<int>(bc_type); 

  // We test the sum of the RHS to check solvability
  Real sum_rhs = 0.;

  for ( MFIter mfi(rhs); mfi.isValid(); ++mfi ) {
    const int* rlo = rhs[mfi].loVect();
    const int* rhi = rhs[mfi].hiVect();
    const Box& bx = rhs[mfi].box();

    FORT_SET_RHS(rhs[mfi].dataPtr(),ARLIM(rlo),ARLIM(rhi),
                 bx.loVect(),bx.hiVect(),dx, a, b, sigma, w, ibnd);
    sum_rhs += rhs[mfi].sum(0,1);
  }

  for (int n=0; n < BL_SPACEDIM; n++) {
    sum_rhs *= dx[n]; 
  }
  
  ParallelDescriptor::ReduceRealSum(sum_rhs, ParallelDescriptor::IOProcessorNumber());

  if (ParallelDescriptor::IOProcessor()) {
     std::cout << "Sum of RHS      : " << sum_rhs << std::endl;
  }

  if (plot_rhs == 1) {
    writePlotFile("RHS", rhs, geom);
  }
}
Exemple #4
0
/******************************************************************************
   mergingAndClustering() : Clustering of GMMs and Realignment; Merging of states 
   inputs : 
   features - pointer to all feature vectors, allMixtureMeans, allMixtureVars
   numstates, numMixEachState, totalNumFeatures, 
   posterior - posterior probability matrix, mixtureElemCount - Element count in each mixture

   outputs : Perform viterbi realignment, clustering and merging of states or GMMs
******************************************************************************/
void ClusteringAndMerging(VECTOR_OF_F_VECTORS *features,                     VECTOR_OF_F_VECTORS *allMixtureMeans,         
			  VECTOR_OF_F_VECTORS *allMixtureVars,               int *numStates,                  int *numMixEachState,
			  int totalNumFeatures,                              float **posterior,          float **mixtureElemCount,
			  int *numElemEachState,                 float *Pi,  float *mixtureWeight)
{
  // local Variable declaration
  int                           VQIter = 7, GMMIter = 23, mergeIter=0, maxMergeIter = 16;
  int                           viterbiIter = 5;
  int                           i = 0, j = 0, k = 0,s= 0,  flag = 1;
  float                         *T1[MAX_NUM_STATES];
  int                           *T2[MAX_NUM_STATES];
  int                           *newStateSeq;
  float                         *deltaBIC[MAX_NUM_STATES];
  for(i = 0; i < (*numStates); i++){
    deltaBIC[i] = (float *)calloc((*numStates), sizeof(float));
  }
  for(i = 0; i < (*numStates); i++){
    T1[i] = (float *)calloc(totalNumFeatures, sizeof(float));
    T2[i] = (int *)calloc(totalNumFeatures, sizeof(int));
  }
  // Merge two GMM States or two mixture models
  //perform the steps repeatedly till there are no more states to be merged 
  while(flag && mergeIter < maxMergeIter){
    printf("\nClustering and Merging Iteration: %d...........\n", mergeIter);
    printf("starting with, States: %d \n", *numStates);
    mergeIter++;
    for(s = 0; s < *numStates; s++)
      printf("state[%d] : %d \n", s, numElemEachState[s]);
    for(i = 0; i < viterbiIter; i++){
      //perform Viterbi Realignment       
      printf("performing viterbi realignment....\n");
      
      newStateSeq     = viterbi(  features , numStates,       allMixtureMeans,      allMixtureVars,      numMixEachState,
				  totalNumFeatures,     posterior,                numElemEachState,        T1,           T2,
				  Pi, mixtureWeight);
      
      printf("Viterbi realignment has successfully completed...\n");
      //find number of elements in each state
      //FindNumberOfElemInEachState(newStateSeq,   numStates, totalNumFeatures,  numElemEachState, Pi);
      
      //perform GMM clustering for all states
      for(s = 0; s < (*numStates); s++){
	// find all elements present in state s using viterbi_realignment
	int count = 0, d = 0; // to count number of features in a state
	for(j = 0; j < totalNumFeatures; j++){
	  if(newStateSeq[j] == s){
	    for(d = 0; d < DIM; d++){
	      featuresForClustering[count]->array[d] = features[j]->array[d];
	      featuresForClustering[count]->numElements = DIM;
	    }
	    count++;//increment count
	  }
	}
	extern VECTOR_OF_F_VECTORS *mixtureMeans, *mixtureVars;
	extern float probScaleFactor; 
	extern int varianceNormalize, ditherMean;
	int numFeatures = count;
	//printf("count: %d  num: %d\n", count, numElemEachState[s]);
	int numMix = numMixEachState[s];
	// Cluster using GMM
	ComputeGMM(featuresForClustering,            numFeatures,              mixtureMeans,             mixtureVars,
		   mixtureElemCount[s],     numMix   ,          VQIter,           GMMIter,               probScaleFactor,
		   ditherMean,         varianceNormalize,        time(NULL));
	
	int mixCount = 0, k=0;
	//store current mean and variance into all means and variance
	for(j = 0; j < s; j++)
	  mixCount += numMixEachState[j];
	for(j = mixCount; j < mixCount + numMixEachState[s]; j++){
	  for(k = 0; k < DIM; k++){
	    allMixtureMeans[j]->array[k] = mixtureMeans[j-mixCount]->array[k];
	    allMixtureVars[j]->array[k] = mixtureVars[j-mixCount]->array[k];
	  }
	  float mix_wt = mixtureElemCount[s][j-mixCount] / numElemEachState[s];
	  mixtureWeight[j] = mix_wt;
	}
      }//GMM Clustering for each state has completed 
      //calculate posterior probabilities      
      PrintAllDetails(numStates, numMixEachState, numElemEachState, 
		      mixtureElemCount, allMixtureMeans, mixtureWeight);
      ComputePosteriorProb(features,    posterior,      allMixtureMeans,       allMixtureVars,     numStates,  
			   numMixEachState,      totalNumFeatures,             mixtureWeight);
    }
    //    PrintAllDetails(numStates, numMixEachState, numElemEachState, 
    //		    mixtureElemCount, allMixtureMeans, mixtureWeight);
    // Calculate BIC Value between Each state   
    CalculateBIC(deltaBIC,    features ,        allMixtureMeans,    allMixtureVars,    numStates,        totalNumFeatures,    
		 newStateSeq,     		 numMixEachState , numElemEachState,   posterior);
    int min_i =0, min_j = 0;
    float min = 99999999;
    // find minimum delta BIC states
    for(j = 0; j < *numStates; j++){
      for(k = j+1; k < *numStates; k++){
	if(deltaBIC[j][k] < min){
	  min = deltaBIC[j][k];
	  min_i = j;
	  min_j = k;
	}
      }
    }
    printf("min_i: %d   min_j: %d   minDBIC: %f\n", min_i, min_j, deltaBIC[min_i][min_j]);
    // if no two states can be merged set the flag to False to terminate process
    if(deltaBIC[min_i][min_j] >= 0){
      printf("We need to stop now ..... Final no of states: %d\n", *numStates);
      flag = 0;
    }
    // Merge two states 
    if(flag)
      MergeTwoStates( min_i,   min_j,   allMixtureMeans,    allMixtureVars,      numStates,     numMixEachState,   
		      numElemEachState,                     Pi,                  totalNumFeatures,
		      features,                  newStateSeq,                    mixtureWeight);
    /*printf("Means after Merging of two states.................\n");
      PrintAllDetails(numStates, numMixEachState, numElemEachState, 
      mixtureElemCount, allMixtureMeans);*/
    for(i = 0; i < *numStates; i++)
      printf("mix[%d]: %d\n", i, numMixEachState[i]);
  }
  //WRITE PLOT_File to plot distribution of each data point
  writePlotFile(posterior, totalNumFeatures, numStates);
  //WRITE RTTM FILE
  writeRTTMFile(newStateSeq, numStates, totalNumFeatures, numElemEachState);
}
Exemple #5
0
int
main (int argc, char* argv[])
{
    BoxLib::Initialize(argc,argv);

    // What time is it now?  We'll use this to compute total run time.
    Real strt_time = ParallelDescriptor::second();

    std::cout << std::setprecision(15);

    // ParmParse is way of reading inputs from the inputs file
    ParmParse pp;
    
    int verbose = 0;
    pp.query("verbose", verbose);
    
    // We need to get n_cell from the inputs file - this is the number of cells on each side of 
    //   a square (or cubic) domain.
    int n_cell;
    pp.get("n_cell",n_cell);

    int max_grid_size;
    pp.get("max_grid_size",max_grid_size);

    // Default plot_int to 1, allow us to set it to something else in the inputs file
    //  If plot_int < 0 then no plot files will be written
    int plot_int = 1;
    pp.query("plot_int",plot_int);

    // Default nsteps to 0, allow us to set it to something else in the inputs file
    int nsteps   = 0;
    pp.query("nsteps",nsteps);

    pp.query("do_tiling", do_tiling);

    // Define a single box covering the domain
    IntVect dom_lo(0,0,0);
    IntVect dom_hi(n_cell-1,n_cell-1,n_cell-1);
    Box domain(dom_lo,dom_hi);

    // Initialize the boxarray "bs" from the single box "bx"
    BoxArray bs(domain);

    // Break up boxarray "bs" into chunks no larger than "max_grid_size" along a direction
    bs.maxSize(max_grid_size);

    // This defines the physical size of the box.  Right now the box is [-1,1] in each direction.
    RealBox real_box;
    for (int n = 0; n < BL_SPACEDIM; n++) {
	real_box.setLo(n,-1.0);
	real_box.setHi(n, 1.0);
    }

    // This says we are using Cartesian coordinates
    int coord = 0;
    
    // This sets the boundary conditions to be doubly or triply periodic
    int is_per[BL_SPACEDIM];
    for (int i = 0; i < BL_SPACEDIM; i++) is_per[i] = 1; 
    
    // This defines a Geometry object which is useful for writing the plotfiles  
    Geometry geom(domain,&real_box,coord,is_per);

    // This defines the mesh spacing
    Real dx[BL_SPACEDIM];
    for ( int n=0; n<BL_SPACEDIM; n++ )
	dx[n] = ( geom.ProbHi(n) - geom.ProbLo(n) )/domain.length(n);

    // Nghost = number of ghost cells for each array 
    int Nghost = 1;

    // Ncomp = number of components for each array
    int Ncomp  = 1;
    pp.query("ncomp", Ncomp);

    // Allocate space for the old_phi and new_phi -- we define old_phi and new_phi as
    PArray < MultiFab > phis(2, PArrayManage);
    phis.set(0, new MultiFab(bs, Ncomp, Nghost));
    phis.set(1, new MultiFab(bs, Ncomp, Nghost));
    MultiFab* old_phi = &phis[0];
    MultiFab* new_phi = &phis[1];

    // Initialize both to zero (just because)
    old_phi->setVal(0.0);
    new_phi->setVal(0.0);

    // Initialize phi by calling a Fortran routine.
    // MFIter = MultiFab Iterator
#ifdef _OPENMP
#pragma omp parallel
#endif
    for ( MFIter mfi(*new_phi,true); mfi.isValid(); ++mfi )
    {
	const Box& bx = mfi.tilebox();

	init_phi(bx.loVect(),bx.hiVect(), 
		 BL_TO_FORTRAN((*new_phi)[mfi]),Ncomp,
		 dx,geom.ProbLo(),geom.ProbHi());
    }

    // Call the compute_dt routine to return a time step which we will pass to advance
    Real dt = compute_dt(dx[0]);

    // Write a plotfile of the initial data if plot_int > 0 (plot_int was defined in the inputs file)
    if (plot_int > 0) {
	int n = 0;
	const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
	writePlotFile(pltfile, *new_phi, geom);
    }

    Real adv_start_time = ParallelDescriptor::second();

    for (int n = 1; n <= nsteps; n++)
    {
	// Swap the pointers so we don't have to allocate and de-allocate data
	std::swap(old_phi, new_phi);

	// new_phi = old_phi + dt * (something)
	advance(old_phi, new_phi, dx, dt, geom); 

	// Tell the I/O Processor to write out which step we're doing
	if (verbose && ParallelDescriptor::IOProcessor())
	    std::cout << "Advanced step " << n << std::endl;

	// Write a plotfile of the current data (plot_int was defined in the inputs file)
	if (plot_int > 0 && n%plot_int == 0) {
	    const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
	    writePlotFile(pltfile, *new_phi, geom);
	}
    }

    // Call the timer again and compute the maximum difference between the start time and stop time
    //   over all processors
    Real advance_time = ParallelDescriptor::second() - adv_start_time;
    Real stop_time = ParallelDescriptor::second() - strt_time;
    const int IOProc = ParallelDescriptor::IOProcessorNumber();
    ParallelDescriptor::ReduceRealMax(stop_time,IOProc);
    ParallelDescriptor::ReduceRealMax(advance_time,IOProc);
    ParallelDescriptor::ReduceRealMax(kernel_time,IOProc);
    ParallelDescriptor::ReduceRealMax(FB_time,IOProc);
    
    // Tell the I/O Processor to write out the "run time"
    if (ParallelDescriptor::IOProcessor()) {
	std::cout << "Kernel    time = " << kernel_time << std::endl;
	std::cout << "FB        time = " << FB_time << std::endl;
	std::cout << "Advance   time = " << advance_time << std::endl;
	std::cout << "Total run time = " << stop_time << std::endl;
    }
    
    // Say goodbye to MPI, etc...
    BoxLib::Finalize();
}
Exemple #6
0
void main_main ()
{
  // What time is it now?  We'll use this to compute total run time.
  Real strt_time = ParallelDescriptor::second();

  std::cout << std::setprecision(15);

  int n_cell, max_grid_size, nsteps, plot_int, is_periodic[BL_SPACEDIM];

  // Boundary conditions
  Array<int> lo_bc(BL_SPACEDIM), hi_bc(BL_SPACEDIM);

  // inputs parameters
  {
    // ParmParse is way of reading inputs from the inputs file
    ParmParse pp;

    // We need to get n_cell from the inputs file - this is the number of cells on each side of 
    //   a square (or cubic) domain.
    pp.get("n_cell",n_cell);

    // Default nsteps to 0, allow us to set it to something else in the inputs file
    pp.get("max_grid_size",max_grid_size);

    // Default plot_int to 1, allow us to set it to something else in the inputs file
    //  If plot_int < 0 then no plot files will be written
    plot_int = 1;
    pp.query("plot_int",plot_int);

    // Default nsteps to 0, allow us to set it to something else in the inputs file
    nsteps = 0;
    pp.query("nsteps",nsteps);

    // Boundary conditions - default is periodic (INT_DIR)
    for (int i = 0; i < BL_SPACEDIM; ++i)
    {
      lo_bc[i] = hi_bc[i] = INT_DIR;   // periodic boundaries are interior boundaries
    }
    pp.queryarr("lo_bc",lo_bc,0,BL_SPACEDIM);
    pp.queryarr("hi_bc",hi_bc,0,BL_SPACEDIM);
  }

  // make BoxArray and Geometry
  BoxArray ba;
  Geometry geom;
  {
    IntVect dom_lo(IntVect(D_DECL(0,0,0)));
    IntVect dom_hi(IntVect(D_DECL(n_cell-1, n_cell-1, n_cell-1)));
    Box domain(dom_lo, dom_hi);

    // Initialize the boxarray "ba" from the single box "bx"
    ba.define(domain);
    // Break up boxarray "ba" into chunks no larger than "max_grid_size" along a direction
    ba.maxSize(max_grid_size);

    // This defines the physical size of the box.  Right now the box is [-1,1] in each direction.
    RealBox real_box;
    for (int n = 0; n < BL_SPACEDIM; n++) {
      real_box.setLo(n,-1.0);
      real_box.setHi(n, 1.0);
    }

    // This says we are using Cartesian coordinates
    int coord = 0;
	
    // This sets the boundary conditions to be doubly or triply periodic
    int is_periodic[BL_SPACEDIM];
    for (int i = 0; i < BL_SPACEDIM; i++)
    {
      is_periodic[i] = 0;
      if (lo_bc[i] == 0 && hi_bc[i] == 0) {
	is_periodic[i] = 1;
      }
    }

    // This defines a Geometry object
    geom.define(domain,&real_box,coord,is_periodic);
  }

  // Boundary conditions
  PhysBCFunct physbcf;
  BCRec bcr(&lo_bc[0], &hi_bc[0]);
  physbcf.define(geom, bcr, BndryFunctBase(phifill)); // phifill is a fortran function

  // define dx[]
  const Real* dx = geom.CellSize();

  // Nghost = number of ghost cells for each array 
  int Nghost = 1;

  // Ncomp = number of components for each array
  int Ncomp  = 1;

  // time = starting time in the simulation
  Real time = 0.0;
  
  // we allocate two phi multifabs; one will store the old state, the other the new
  // we swap the indices each time step to avoid copies of new into old
  PArray<MultiFab> phi(2, PArrayManage);
  phi.set(0, new MultiFab(ba, Ncomp, Nghost));
  phi.set(1, new MultiFab(ba, Ncomp, Nghost));

  // Initialize both to zero (just because)
  phi[0].setVal(0.0);
  phi[1].setVal(0.0);

  // Initialize phi[init_index] by calling a Fortran routine.
  // MFIter = MultiFab Iterator
  int init_index = 0;
  for ( MFIter mfi(phi[init_index]); mfi.isValid(); ++mfi )
  {
    const Box& bx = mfi.validbox();

    init_phi(phi[init_index][mfi].dataPtr(),
	     bx.loVect(), bx.hiVect(), &Nghost,
	     geom.CellSize(), geom.ProbLo(), geom.ProbHi());
  }

  // compute the time step
  Real dt = 0.9*dx[0]*dx[0] / (2.0*BL_SPACEDIM);

  // Write a plotfile of the initial data if plot_int > 0 (plot_int was defined in the inputs file)
  if (plot_int > 0)
  {
    int n = 0;
    const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
    writePlotFile(pltfile, phi[init_index], geom, time);
  }

  // build the flux multifabs
  PArray<MultiFab> flux(BL_SPACEDIM, PArrayManage);
  for (int dir = 0; dir < BL_SPACEDIM; dir++)
  {
    // flux(dir) has one component, zero ghost cells, and is nodal in direction dir
    BoxArray edge_ba = ba;
    edge_ba.surroundingNodes(dir);
    flux.set(dir, new MultiFab(edge_ba, 1, 0));
  }

  int old_index = init_index;
  for (int n = 1; n <= nsteps; n++, old_index = 1 - old_index)
  {
    int new_index = 1 - old_index;

    // new_phi = old_phi + dt * (something)
    advance(phi[old_index], phi[new_index], flux, time, dt, geom, physbcf, bcr); 
    time = time + dt;

    // Tell the I/O Processor to write out which step we're doing
    if (ParallelDescriptor::IOProcessor())
      std::cout << "Advanced step " << n << std::endl;

    // Write a plotfile of the current data (plot_int was defined in the inputs file)
    if (plot_int > 0 && n%plot_int == 0)
    {
      const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
      writePlotFile(pltfile, phi[new_index], geom, time);
    }
  }

  // Call the timer again and compute the maximum difference between the start time and stop time
  //   over all processors
  Real stop_time = ParallelDescriptor::second() - strt_time;
  const int IOProc = ParallelDescriptor::IOProcessorNumber();
  ParallelDescriptor::ReduceRealMax(stop_time,IOProc);

  // Tell the I/O Processor to write out the "run time"
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "Run time = " << stop_time << std::endl;
  }
}
Exemple #7
0
int
main (int argc, char* argv[])
{
  BoxLib::Initialize(argc,argv);

  // What time is it now?  We'll use this to compute total run time.
  Real strt_time = ParallelDescriptor::second();

  std::cout << std::setprecision(15);

  // ParmParse is way of reading inputs from the inputs file
  ParmParse pp;

  // We need to get n_cell from the inputs file - this is the number of cells on each side of 
  //   a square (or cubic) domain.
  int n_cell;
  pp.get("n_cell",n_cell);

  // Default nsteps to 0, allow us to set it to something else in the inputs file
  int max_grid_size;
  pp.get("max_grid_size",max_grid_size);

  // Default plot_int to 1, allow us to set it to something else in the inputs file
  //  If plot_int < 0 then no plot files will be written
  int plot_int = 1;
  pp.query("plot_int",plot_int);

  // Default nsteps to 0, allow us to set it to something else in the inputs file
  int nsteps   = 0;
  pp.query("nsteps",nsteps);

  // Define a single box covering the domain
#if (BL_SPACEDIM == 2)
  IntVect dom_lo(0,0);
  IntVect dom_hi(n_cell-1,n_cell-1);
#else
  IntVect dom_lo(0,0,0);
  IntVect dom_hi(n_cell-1,n_cell-1,n_cell-1);
#endif
  Box domain(dom_lo,dom_hi);

  // Initialize the boxarray "bs" from the single box "bx"
  BoxArray bs(domain);

  // Break up boxarray "bs" into chunks no larger than "max_grid_size" along a direction
  bs.maxSize(max_grid_size);

  // This defines the physical size of the box.  Right now the box is [-1,1] in each direction.
  RealBox real_box;
  for (int n = 0; n < BL_SPACEDIM; n++)
  {
     real_box.setLo(n,-1.0);
     real_box.setHi(n, 1.0);
  }

  // This says we are using Cartesian coordinates
  int coord = 0;

  // This sets the boundary conditions to be doubly or triply periodic
  int is_per[BL_SPACEDIM];
  for (int i = 0; i < BL_SPACEDIM; i++) is_per[i] = 1; 

  // This defines a Geometry object which is useful for writing the plotfiles  
  Geometry geom(domain,&real_box,coord,is_per);

  // This defines the mesh spacing
  Real dx[BL_SPACEDIM];
  for ( int n=0; n<BL_SPACEDIM; n++ )
      dx[n] = ( geom.ProbHi(n) - geom.ProbLo(n) )/domain.length(n);

  // Nghost = number of ghost cells for each array 
  int Nghost = 1;

  // Ncomp = number of components for each array
  int Ncomp  = 1;

  // Make sure we can fill the ghost cells from the adjacent grid
  if (Nghost > max_grid_size)
    std::cout <<  "NGHOST < MAX_GRID_SIZE --  grids are too small! " << std::endl;

  // Allocate space for the old_phi and new_phi -- we define old_phi and new_phi as
  //   pointers to the MultiFabs
  MultiFab* old_phi = new MultiFab(bs, Ncomp, Nghost);
  MultiFab* new_phi = new MultiFab(bs, Ncomp, Nghost);

  // Initialize both to zero (just because)
  old_phi->setVal(0.0);
  new_phi->setVal(0.0);

  // Initialize the old_phi by calling a Fortran routine.
  // MFIter = MultiFab Iterator
  for ( MFIter mfi(*new_phi); mfi.isValid(); ++mfi )
  {
    const Box& bx = mfi.validbox();

    FORT_INIT_PHI((*new_phi)[mfi].dataPtr(),
                     bx.loVect(),bx.hiVect(), &Nghost,
                     dx,geom.ProbLo(),geom.ProbHi());
  }

  // Call the compute_dt routine to return a time step which we will pass to advance
  Real dt = compute_dt(dx[0]);

  // Write a plotfile of the initial data if plot_int > 0 (plot_int was defined in the inputs file)
  if (plot_int > 0)
  {
     int n = 0;
     const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
     writePlotFile(pltfile, *new_phi, geom);
  }

  // build the flux multifabs
  MultiFab* flux = new MultiFab[BL_SPACEDIM];
  for (int dir = 0; dir < BL_SPACEDIM; dir++)
    {
      BoxArray edge_grids(bs);
      // flux(dir) has one component, zero ghost cells, and is nodal in direction dir
      edge_grids.surroundingNodes(dir);
      flux[dir].define(edge_grids,1,0,Fab_allocate);
    }

  for (int n = 1; n <= nsteps; n++)
  {
     // Swap the pointers so we don't have to allocate and de-allocate data
     std::swap(old_phi, new_phi);

     // new_phi = old_phi + dt * (something)
     advance(old_phi, new_phi, flux, dx, dt, geom); 

     // Tell the I/O Processor to write out which step we're doing
     if (ParallelDescriptor::IOProcessor())
        std::cout << "Advanced step " << n << std::endl;

     // Write a plotfile of the current data (plot_int was defined in the inputs file)
     if (plot_int > 0 && n%plot_int == 0)
     {
        const std::string& pltfile = BoxLib::Concatenate("plt",n,5);
        writePlotFile(pltfile, *new_phi, geom);
     }
  }

  // Call the timer again and compute the maximum difference between the start time and stop time
  //   over all processors
  Real stop_time = ParallelDescriptor::second() - strt_time;
  const int IOProc = ParallelDescriptor::IOProcessorNumber();
  ParallelDescriptor::ReduceRealMax(stop_time,IOProc);

  // Tell the I/O Processor to write out the "run time"
  if (ParallelDescriptor::IOProcessor())
     std::cout << "Run time = " << stop_time << std::endl;
  
  // Say goodbye to MPI, etc...
  BoxLib::Finalize();

}
Exemple #8
0
int main(int argc, char* argv[])
{
  BoxLib::Initialize(argc,argv);

  BL_PROFILE_VAR("main()", pmain);

  std::cout << std::setprecision(15);

  ParmParse ppmg("mg");  
  ppmg.query("v", verbose);
  ppmg.query("maxorder", maxorder);
  
  ParmParse pp;

  {
    std::string solver_type_s;
    pp.get("solver_type",solver_type_s);
    if (solver_type_s == "BoxLib_C") {
      solver_type = BoxLib_C;
    }
    else if (solver_type_s == "BoxLib_C4") {
      solver_type = BoxLib_C4;
    }
    else if (solver_type_s == "BoxLib_F") {
#ifdef USE_F90_SOLVERS
      solver_type = BoxLib_F;      
#else
      BoxLib::Error("Set USE_FORTRAN=TRUE in GNUmakefile");
#endif
    }
    else if (solver_type_s == "Hypre") {
#ifdef USEHYPRE
      solver_type = Hypre;
#else
      BoxLib::Error("Set USE_HYPRE=TRUE in GNUmakefile");
#endif
    }
    else if (solver_type_s == "All") {
      solver_type = All;
    }  
    else {
      if (ParallelDescriptor::IOProcessor()) {
	std::cout << "Don't know this solver type: " << solver_type << std::endl;
      }
      BoxLib::Error("");
    }
  }

  {
    std::string bc_type_s;
    pp.get("bc_type",bc_type_s);
    if (bc_type_s == "Dirichlet") {
      bc_type = Dirichlet;
#ifdef USEHPGMG
      domain_boundary_condition = BC_DIRICHLET;
#endif
    }
    else if (bc_type_s == "Neumann") {
      bc_type = Neumann;
#ifdef USEHPGMG
      BoxLib::Error("HPGMG does not support Neumann boundary conditions");
#endif
    }
    else if (bc_type_s == "Periodic") {
      bc_type = Periodic;
#ifdef USEHPGMG
      domain_boundary_condition = BC_PERIODIC;
#endif
    }
    else {
      if (ParallelDescriptor::IOProcessor()) {
	std::cout << "Don't know this boundary type: " << bc_type << std::endl;
      }
      BoxLib::Error("");
    }
  }

  pp.query("tol_rel", tolerance_rel);
  pp.query("tol_abs", tolerance_abs);
  pp.query("maxiter", maxiter);
  pp.query("plot_rhs" , plot_rhs);
  pp.query("plot_beta", plot_beta);
  pp.query("plot_soln", plot_soln);
  pp.query("plot_asol", plot_asol);
  pp.query("plot_err", plot_err);
  pp.query("comp_norm", comp_norm);

  Real a, b;
  pp.get("a",  a);
  pp.get("b",  b);

  pp.get("n_cell",n_cell);
  pp.get("max_grid_size",max_grid_size);

  // Define a single box covering the domain
  IntVect dom_lo(D_DECL(0,0,0));
  IntVect dom_hi(D_DECL(n_cell-1,n_cell-1,n_cell-1));
  Box domain(dom_lo,dom_hi);

  // Initialize the boxarray "bs" from the single box "bx"
  BoxArray bs(domain);

  // Break up boxarray "bs" into chunks no larger than "max_grid_size" along a direction
  bs.maxSize(max_grid_size);

  // This defines the physical size of the box.  Right now the box is [0,1] in each direction.
  RealBox real_box;
  for (int n = 0; n < BL_SPACEDIM; n++) {
    real_box.setLo(n, 0.0);
    real_box.setHi(n, 1.0);
  }
 
  // This says we are using Cartesian coordinates
  int coord = 0;
  
  // This sets the boundary conditions to be periodic or not
  Array<int> is_per(BL_SPACEDIM,1);
  
  if (bc_type == Dirichlet || bc_type == Neumann) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "Using Dirichlet or Neumann boundary conditions." << std::endl;
    }
    for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 0;
  } 
  else {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "Using periodic boundary conditions." << std::endl;
    }
    for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 1;
  }
 
  // This defines a Geometry object which is useful for writing the plotfiles
  Geometry geom(domain,&real_box,coord,is_per.dataPtr());

  for ( int n=0; n<BL_SPACEDIM; n++ ) {
    dx[n] = ( geom.ProbHi(n) - geom.ProbLo(n) )/domain.length(n);
  }

  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "Grid resolution : " << n_cell << " (cells)" << std::endl;
    std::cout << "Domain size     : " << real_box.hi(0) - real_box.lo(0) << " (length unit) " << std::endl;
    std::cout << "Max_grid_size   : " << max_grid_size << " (cells)" << std::endl;
    std::cout << "Number of grids : " << bs.size() << std::endl;
  }

  // Allocate and define the right hand side.
  bool do_4th = (solver_type==BoxLib_C4 || solver_type==All);
  int ngr = (do_4th ? 1 : 0);
  MultiFab rhs(bs, Ncomp, ngr); 
  setup_rhs(rhs, geom);

  // Set up the Helmholtz operator coefficients.
  MultiFab alpha(bs, Ncomp, 0);
  PArray<MultiFab> beta(BL_SPACEDIM, PArrayManage);
  for ( int n=0; n<BL_SPACEDIM; ++n ) {
    BoxArray bx(bs);
    beta.set(n, new MultiFab(bx.surroundingNodes(n), Ncomp, 0, Fab_allocate));
  }

  // The way HPGMG stores face-centered data is completely different than the
  // way BoxLib does it, and translating between the two directly via indexing
  // magic is a nightmare. Happily, the way this tutorial calculates
  // face-centered values is by first calculating cell-centered values and then
  // interpolating to the cell faces. HPGMG can do the same thing, so rather
  // than converting directly from BoxLib's face-centered data to HPGMG's, just
  // give HPGMG the cell-centered data and let it interpolate itself.

  MultiFab beta_cc(bs,Ncomp,1); // cell-centered beta
  setup_coeffs(bs, alpha, beta, geom, beta_cc);

  MultiFab alpha4, beta4;
  if (do_4th) {
    alpha4.define(bs, Ncomp, 4, Fab_allocate);
    beta4.define(bs, Ncomp, 3, Fab_allocate);
    setup_coeffs4(bs, alpha4, beta4, geom);
  }

  MultiFab anaSoln;
  if (comp_norm || plot_err || plot_asol) {
    anaSoln.define(bs, Ncomp, 0, Fab_allocate);
    compute_analyticSolution(anaSoln,Array<Real>(BL_SPACEDIM,0.5));
    
    if (plot_asol) {
      writePlotFile("ASOL", anaSoln, geom);
    }
  }

  // Allocate the solution array 
  // Set the number of ghost cells in the solution array.
  MultiFab soln(bs, Ncomp, 1);
  MultiFab soln4;
  if (do_4th) {
    soln4.define(bs, Ncomp, 3, Fab_allocate);
  }
  MultiFab gphi(bs, BL_SPACEDIM, 0);

#ifdef USEHYPRE
  if (solver_type == Hypre || solver_type == All) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "----------------------------------------" << std::endl;
      std::cout << "Solving with Hypre " << std::endl;
    }

    solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, Hypre);
  }
#endif

  if (solver_type == BoxLib_C || solver_type == All) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "----------------------------------------" << std::endl;
      std::cout << "Solving with BoxLib C++ solver " << std::endl;
    }
    solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, BoxLib_C);
  }

  if (solver_type == BoxLib_C4 || solver_type == All) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "----------------------------------------" << std::endl;
      std::cout << "Solving with BoxLib C++ 4th order solver " << std::endl;
    }

    solve4(soln4, anaSoln, a, b, alpha4, beta4, rhs, bs, geom);
  }

#ifdef USE_F90_SOLVERS
  if (solver_type == BoxLib_F || solver_type == All) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "----------------------------------------" << std::endl;
      std::cout << "Solving with BoxLib F90 solver " << std::endl;
    }

    solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, BoxLib_F);
  }
#endif

#ifdef USEHPGMG
  if (solver_type == HPGMG || solver_type == All) {
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "----------------------------------------" << std::endl;
      std::cout << "Solving with HPGMG solver " << std::endl;
    }

    solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, HPGMG);
  }
#endif

  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "----------------------------------------" << std::endl;
  }
  
  BL_PROFILE_VAR_STOP(pmain);

  BoxLib::Finalize();
}
Exemple #9
0
void solve_with_HPGMG(MultiFab& soln, MultiFab& gphi, Real a, Real b, MultiFab& alpha, PArray<MultiFab>& beta,
                      MultiFab& beta_cc, MultiFab& rhs, const BoxArray& bs, const Geometry& geom, int n_cell)
{
  BndryData bd(bs, 1, geom);
  set_boundary(bd, rhs, 0);

  ABecLaplacian abec_operator(bd, dx);
  abec_operator.setScalars(a, b);
  abec_operator.setCoefficients(alpha, beta);

  int minCoarseDim;
  if (domain_boundary_condition == BC_PERIODIC)
  {
    minCoarseDim = 2; // avoid problems with black box calculation of D^{-1} for poisson with periodic BC's on a 1^3 grid
  }
  else
  {
    minCoarseDim = 1; // assumes you can drop order on the boundaries
  }

  level_type level_h;
  mg_type MG_h;
  int numVectors = 12;

  int my_rank = 0, num_ranks = 1;

#ifdef BL_USE_MPI
  MPI_Comm_size (MPI_COMM_WORLD, &num_ranks);
  MPI_Comm_rank (MPI_COMM_WORLD, &my_rank);
#endif /* BL_USE_MPI */

  const double h0 = dx[0];
  // Create the geometric structure of the HPGMG grid using the RHS MultiFab as
  // a template. This doesn't copy any actual data.
  CreateHPGMGLevel(&level_h, rhs, n_cell, max_grid_size, my_rank, num_ranks, domain_boundary_condition, numVectors, h0);

  // Set up the coefficients for the linear operator L.
  SetupHPGMGCoefficients(a, b, alpha, beta_cc, &level_h);

  // Now that the HPGMG grid is built, populate it with RHS data.
  ConvertToHPGMGLevel(rhs, n_cell, max_grid_size, &level_h, VECTOR_F);

#ifdef USE_HELMHOLTZ
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "Creating Helmholtz (a=" << a << ", b=" << b << ") test problem" << std::endl;;
  }
#else
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "Creating Poisson (a=" << a << ", b=" << b << ") test problem" << std::endl;;
  }
#endif /* USE_HELMHOLTZ */

  if (level_h.boundary_condition.type == BC_PERIODIC)
  {
    double average_value_of_f = mean (&level_h, VECTOR_F);
    if (average_value_of_f != 0.0)
    {
      if (ParallelDescriptor::IOProcessor())
      {
        std::cerr << "WARNING: Periodic boundary conditions, but f does not sum to zero... mean(f)=" << average_value_of_f << std::endl;
      }
      //shift_vector(&level_h,VECTOR_F,VECTOR_F,-average_value_of_f);
    }
  }
  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  rebuild_operator(&level_h,NULL,a,b);    // i.e. calculate Dinv and lambda_max
  MGBuild(&MG_h,&level_h,a,b,minCoarseDim,ParallelDescriptor::Communicator()); // build the Multigrid Hierarchy
  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  if (ParallelDescriptor::IOProcessor())
      std::cout << std::endl << std::endl << "===== STARTING SOLVE =====" << std::endl << std::flush;

  MGResetTimers (&MG_h);
  zero_vector (MG_h.levels[0], VECTOR_U);
#ifdef USE_FCYCLES
  FMGSolve (&MG_h, 0, VECTOR_U, VECTOR_F, a, b, tolerance_abs, tolerance_rel);
#else
  MGSolve (&MG_h, 0, VECTOR_U, VECTOR_F, a, b, tolerance_abs, tolerance_rel);
#endif /* USE_FCYCLES */

  MGPrintTiming (&MG_h, 0);   // don't include the error check in the timing results
  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  if (ParallelDescriptor::IOProcessor())
    std::cout << std::endl << std::endl << "===== Performing Richardson error analysis ==========================" << std::endl;
  // solve A^h u^h = f^h
  // solve A^2h u^2h = f^2h
  // solve A^4h u^4h = f^4h
  // error analysis...
  MGResetTimers(&MG_h);
  const double dtol = tolerance_abs;
  const double rtol = tolerance_rel;
  int l;for(l=0;l<3;l++){
    if(l>0)restriction(MG_h.levels[l],VECTOR_F,MG_h.levels[l-1],VECTOR_F,RESTRICT_CELL);
           zero_vector(MG_h.levels[l],VECTOR_U);
    #ifdef USE_FCYCLES
    FMGSolve(&MG_h,l,VECTOR_U,VECTOR_F,a,b,dtol,rtol);
    #else
     MGSolve(&MG_h,l,VECTOR_U,VECTOR_F,a,b,dtol,rtol);
    #endif
  }
  richardson_error(&MG_h,0,VECTOR_U);

  // Now convert solution from HPGMG back to rhs MultiFab.
  ConvertFromHPGMGLevel(soln, &level_h, VECTOR_U);

  const double norm_from_HPGMG = norm(&level_h, VECTOR_U);
  const double mean_from_HPGMG = mean(&level_h, VECTOR_U);
  const Real norm0 = soln.norm0();
  const Real norm2 = soln.norm2();
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "mean from HPGMG: " << mean_from_HPGMG << std::endl;
    std::cout << "norm from HPGMG: " << norm_from_HPGMG << std::endl;
    std::cout << "norm0 of RHS copied to MF: " << norm0 << std::endl;
    std::cout << "norm2 of RHS copied to MF: " << norm2 << std::endl;
  }

  // Write the MF to disk for comparison with the in-house solver
  if (plot_soln)
  {
    writePlotFile("SOLN-HPGMG", soln, geom);
  }

  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  MGDestroy(&MG_h);
  destroy_level(&level_h);
  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  PArray<MultiFab> grad_phi(BL_SPACEDIM, PArrayManage);
  for (int n = 0; n < BL_SPACEDIM; ++n)
      grad_phi.set(n, new MultiFab(BoxArray(soln.boxArray()).surroundingNodes(n), 1, 0));

#if (BL_SPACEDIM == 2)
  abec_operator.compFlux(grad_phi[0],grad_phi[1],soln);
#elif (BL_SPACEDIM == 3)
  abec_operator.compFlux(grad_phi[0],grad_phi[1],grad_phi[2],soln);
#endif

  // Average edge-centered gradients to cell centers.
  BoxLib::average_face_to_cellcenter(gphi, grad_phi, geom);
}
Exemple #10
0
void solve(MultiFab& soln, const MultiFab& anaSoln, MultiFab& gphi,
	   Real a, Real b, MultiFab& alpha, PArray<MultiFab>& beta, MultiFab& beta_cc,
	   MultiFab& rhs, const BoxArray& bs, const Geometry& geom,
	   solver_t solver)
{
  BL_PROFILE("solve()");
  std::string ss;

  soln.setVal(0.0);

  const Real run_strt = ParallelDescriptor::second();

  if (solver == BoxLib_C) {
    ss = "CPP";
    solve_with_Cpp(soln, gphi, a, b, alpha, beta, rhs, bs, geom);
  }
#ifdef USE_F90_SOLVERS
  else if (solver == BoxLib_F) {
    ss = "F90";
    solve_with_F90(soln, gphi, a, b, alpha, beta, rhs, bs, geom);
  }
#endif
#ifdef USEHYPRE
  else if (solver == Hypre) {
    ss = "Hyp";
    solve_with_hypre(soln, a, b, alpha, beta, rhs, bs, geom);
  }
#endif
#ifdef USEHPGMG
  else if (solver == HPGMG) {
    ss = "HPGMG";
    solve_with_HPGMG(soln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, n_cell);
  }
#endif
  else {
    BoxLib::Error("Invalid solver");
  }

  Real run_time = ParallelDescriptor::second() - run_strt;

  ParallelDescriptor::ReduceRealMax(run_time, ParallelDescriptor::IOProcessorNumber());
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "   Run time      : " << run_time << std::endl;
  }

  if (plot_soln) {
    writePlotFile("SOLN-"+ss, soln, geom);
    writePlotFile("GPHI-"+ss, gphi, geom);
  }

  if (plot_err || comp_norm) {
    soln.minus(anaSoln, 0, Ncomp, 0); // soln contains errors now
    MultiFab& err = soln;

    if (plot_err) {
      writePlotFile("ERR-"+ss, soln, geom);
    }
    
    if (comp_norm) {
      Real twoNorm = err.norm2();
      Real maxNorm = err.norm0();
      
      err.setVal(1.0);
      Real vol = err.norm2();
      twoNorm /= vol;
      
      if (ParallelDescriptor::IOProcessor()) {
	std::cout << "   2 norm error  : " << twoNorm << std::endl;
	std::cout << "   max norm error: " << maxNorm << std::endl;
      }
    }
  }
}
Exemple #11
0
void solve4(MultiFab& soln, const MultiFab& anaSoln, 
	     Real a, Real b, MultiFab& alpha, MultiFab& beta, 
	     MultiFab& rhs, const BoxArray& bs, const Geometry& geom)
{
  std::string ss = "CPP";
  soln.setVal(0.0);

  const Real run_strt = ParallelDescriptor::second();

  BndryData bd(bs, 1, geom);
  set_boundary(bd, rhs, 0);

  ABec4 abec_operator(bd, dx);
  abec_operator.setScalars(a, b);

  MultiFab betaca(bs,1,2);
  ABec4::cc2ca(beta,betaca,0,0,1);

  MultiFab alphaca(bs,1,2);
  ABec4::cc2ca(alpha,alphaca,0,0,1);
  abec_operator.setCoefficients(alphaca, betaca);

  MultiFab rhsca(bs,1,0);
  ABec4::cc2ca(rhs,rhsca,0,0,1);

  MultiFab out(bs,1,0);

  compute_analyticSolution(soln,Array<Real>(BL_SPACEDIM,0.5));

  MultiFab solnca(bs,1,2);
  solnca.setVal(0);

  MultiGrid mg(abec_operator);

  mg.setVerbose(verbose);
  mg.solve(solnca, rhsca, tolerance_rel, tolerance_abs);

  Real run_time = ParallelDescriptor::second() - run_strt;

  ParallelDescriptor::ReduceRealMax(run_time, ParallelDescriptor::IOProcessorNumber());
  if (ParallelDescriptor::IOProcessor()) {
    std::cout << "   Run time      : " << run_time << std::endl;
  }

  if (plot_soln) {
    writePlotFile("SOLN-"+ss, solnca, geom);
  }

  if (plot_err || comp_norm) {
    soln.minus(anaSoln, 0, Ncomp, 0); // soln contains errors now
    MultiFab& err = soln;

    if (plot_err) {
      writePlotFile("ERR-"+ss, soln, geom);
    }
    
    if (comp_norm) {
      Real twoNorm = err.norm2();
      Real maxNorm = err.norm0();
      
      err.setVal(1.0);
      Real vol = err.norm2();
      twoNorm /= vol;
      
      if (ParallelDescriptor::IOProcessor()) {
	std::cout << "   2 norm error  : " << twoNorm << std::endl;
	std::cout << "   max norm error: " << maxNorm << std::endl;
      }
    }
  }
}
Exemple #12
0
void
SMC::evolve ()
{
    int istep = 0;
    int last_plt_written = -1;

    if (plot_int > 0) {
	writePlotFile(istep);
	last_plt_written = istep;
    }
    
    int init_step = 1;

    if (ParallelDescriptor::IOProcessor()) {
	std::cout << "\n" << "BEGIN MAIN EVOLUTION LOOP" << "\n" << std::endl;
    }

    ParallelDescriptor::Barrier();
    Real wt0 = ParallelDescriptor::second();

    if ( (max_step >= init_step) && (t < stop_time || stop_time < 0.0) ) 
    {
	for (istep = init_step; istep <= max_step; ++istep) 
	{
	    if (ParallelDescriptor::IOProcessor()) {
		std::cout << "Advancing time step " << istep << " time = " << t << "\n";
	    }

	    advance(istep);

	    t = t + dt;

	    if (ParallelDescriptor::IOProcessor()) {
		std::cout << "End of step " << istep << " time = " << t << "\n" << std::endl;
	    }

	    if (plot_int > 0 && istep%plot_int == 0) {
		writePlotFile(istep);
		last_plt_written = istep;
	    }

	    if (stop_time >= 0.0 && t >= stop_time) {
		break;
	    }
	}

	if (istep > max_step) istep = max_step;

	if (plot_int > 0 && last_plt_written != istep) {
	    writePlotFile(istep);
	}
    }

#ifdef BL_USE_UPCXX
    upcxx::barrier();
#else
    ParallelDescriptor::Barrier();
#endif

    Real wt1 = ParallelDescriptor::second();

    Real wt_fb = wt_fb1 + wt_fb2;
    Real wt_chem = wt_chem1 + wt_chem2;

    ParallelDescriptor::ReduceRealMax(wt_fb     , ParallelDescriptor::IOProcessorNumber());
    ParallelDescriptor::ReduceRealMax(wt_chem   , ParallelDescriptor::IOProcessorNumber());
    ParallelDescriptor::ReduceRealMax(wt_hypdiff, ParallelDescriptor::IOProcessorNumber());
    if (ParallelDescriptor::IOProcessor()) {
	std::cout << "======================================" << std::endl;
	std::cout << " Total Time            : " << wt1-wt0 << "\n";
	std::cout << "     Communication time: " << wt_fb << "\n";
	std::cout << "     Chemistry     time: " << wt_chem << "\n";
	std::cout << "     Hyp-Diff      time: " << wt_hypdiff << "\n";
	std::cout << "======================================" << std::endl;
    }
}