コード例 #1
0
ファイル: main.cpp プロジェクト: muzmostofi/cudaseg
int main(int argc, char** argv){

	const char *image_path = IMAGE;
	
	//TODO : declare ALL variables here

	LoadBMPFile(&h_Src, &imageW, &imageH, image_path);
	D = (float *)malloc(imageW*imageH*sizeof(float));

	//printf("Input Image\n");
	for(r=0;r<imageH;r++){
		for(c=0;c<imageW;c++){
			D[r*imageW+c] = h_Src[r*imageW+c].x;
			/*printf("%3.0f ", D[r*imageW+c]);*/
		}
		//printf("\n");
	}

	N = imageW*imageH;

	for(i=0;i<N;i++){
		D[i] = EPSILON - abs(D[i] - THRESHOLD);
	}

	//printf("Speed Function\n");	
	//for(int r=0;r<imageH;r++){
	//	for(int c=0;c<imageW;c++){
	//		printf("%3.0f ", D[r*imageW+c]);
	//	}
	//	printf("\n");
	//}

	// Set up CUDA Timer
	cutCreateTimer(&Timer);
	cutCreateTimer(&ReInitTimer);

	cutStartTimer(Timer);

	init_phi();
	if((contour=(float *)malloc(imageW*imageH*sizeof(float)))==NULL)printf("Contour\n");
	if((phi1=(float *)malloc(imageW*imageH*sizeof(float)))==NULL)printf("GRADPHI\n");
//update_phi();

		  // GL initialisation
		  glutInit(&argc, argv);
		  glutInitDisplayMode(GLUT_ALPHA | GLUT_DOUBLE);
		  glutInitWindowSize(imageW,imageH);
		  glutInitWindowPosition(100,100);
		  glutCreateWindow("GL Level Set Evolution");
		  glClearColor(0.0,0.0,0.0,0.0);


		  glutDisplayFunc(disp);
		  glutMainLoop();

	//printf("phi+1\n");
	//for(int r=0;r<imageH;r++){
	//	for(int c=0;c<imageW;c++){
	//		printf("%6.3f ", phi[r*imageW+c]);
	//	}
	//	printf("\n");
	//}
}
コード例 #2
0
ファイル: medstc.cpp プロジェクト: aykutfirat/MedSTC-R
/*
* learn dictionary and find optimum code.
*/
int MedSTC::train(char* start, char* directory, Corpus* pC, Params *param)
{
	m_dDeltaEll = param->DELTA_ELL;
	m_dLambda   = param->LAMBDA;
	m_dRho      = param->RHO;
	m_dGamma    = m_dLambda;
	long runtime_start = get_runtime();

	// allocate variational parameters
	double ***phi = (double***)malloc(sizeof(double**) * pC->num_docs);
	for ( int d=0; d<pC->num_docs; d++ ) {
		phi[d] = (double**)malloc(sizeof(double*)*pC->docs[d].length);
		for (int n=0; n<pC->docs[d].length; n++) {
			phi[d][n] = (double*)malloc(sizeof(double) * param->NTOPICS);
		}
	}
	double **theta = (double**)malloc(sizeof(double*)*(pC->num_docs));
	for (int d=0; d<pC->num_docs; d++) {
		theta[d] = (double*)malloc(sizeof(double) * param->NTOPICS);
	}
	for ( int d=0; d<pC->num_docs; d++ ) {
		init_phi(&(pC->docs[d]), phi[d], theta[d], param);
	}

	// initialize model
	if (strcmp(start, "random")==0) {
		new_model(pC->num_docs, pC->num_terms, param->NTOPICS, 
								param->NLABELS, param->INITIAL_C);
		init_param( pC );
	} else {
		load_model(start);
		m_dC = param->INITIAL_C;
	}
	strcpy(m_directory, directory);

	char filename[100];
	

	// run expectation maximization
	sprintf(filename, "%s/lhood.dat", directory);
	FILE* lhood_file = fopen(filename, "w");

	Document *pDoc = NULL;
	double dobj, obj_old = 1, converged = 1;
	int nIt = 0;
	while (((converged < 0) || (converged > param->EM_CONVERGED) 
		|| (nIt <= 2)) && (nIt <= param->EM_MAX_ITER))
	{

		dobj = 0;
		double dLogLoss = 0;
		for ( int d=0; d<pC->num_docs; d++ ) {
			pDoc = &(pC->docs[d]);
			dobj += sparse_coding( pDoc, d, param, theta[d], phi[d] );
			dLogLoss += m_dLogLoss;
		}

		// m-step

		dict_learn(pC, theta, phi, param, false);

		if ( param->SUPERVISED == 1 ) { // for supervised MedLDA.
			char buff[512];
			get_train_filename( buff, m_directory, param );
			outputLowDimData( buff, pC, theta );

			svmStructSolver(buff, param, m_dMu);

			if ( param->PRIMALSVM == 1 ) { // solve svm in the primal form
				for ( int d=0; d<pC->num_docs; d++ ) {
					loss_aug_predict( &(pC->docs[d]), theta[d] );
				}
			}
			dobj += m_dsvm_primalobj;
		} else ;

		// check for convergence
		converged = fabs(1 - dobj / obj_old);
		obj_old = dobj;

		// output model and lhood
		if ( param->SUPERVISED == 1 ) {
			fprintf(lhood_file, "%10.10f\t%10.10f\t%5.5e\t%.5f\n", dobj-m_dsvm_primalobj, dobj, converged, dLogLoss);
		} else {
			fprintf(lhood_file, "%10.10f\t%5.5e\t%.5f\n", dobj, converged, dLogLoss);
		}
		fflush(lhood_file);
		if ( nIt > 0 && (nIt % LAG) == 0) {
			sprintf( filename, "%s/%d", directory, nIt + 1);
			save_model( filename, -1 );
			sprintf( filename, "%s/%d.theta", directory, nIt + 1 );
			save_theta( filename, theta, pC->num_docs, m_nK );
		}
		nIt ++;
	}
	// learn the final SVM.
	if ( param->SUPERVISED == 0 ) {
		char buff[512];
		get_train_filename(buff, m_directory, param);
		outputLowDimData(buff, pC, theta);

		svmStructSolver(buff, param, m_dMu);
	}
	long runtime_end = get_runtime();
	double dTrainTime = ((double)runtime_end-(double)runtime_start) / 100.0;


	// output the final model
	sprintf( filename, "%s/final", directory);
	save_model( filename, dTrainTime );

	// output the word assignments (for visualization)
	int nNum = 0, nAcc = 0;
	sprintf(filename, "%s/word-assignments.dat", directory);
	FILE* w_asgn_file = fopen(filename, "w");
	for (int d=0; d<pC->num_docs; d++) {

		sparse_coding( &(pC->docs[d]), d, param, theta[d], phi[d] );
		write_word_assignment(w_asgn_file, &(pC->docs[d]), phi[d]);

		nNum ++;
		pC->docs[d].predlabel = predict(theta[d]);
		if ( pC->docs[d].gndlabel == pC->docs[d].predlabel ) nAcc ++;
	}
	fclose(w_asgn_file);
	fclose(lhood_file);

	sprintf(filename,"%s/train.theta",directory);
	save_theta(filename, theta, pC->num_docs, m_nK);

	for (int d=0; d<pC->num_docs; d++) {
		free( theta[d] );
		for (int n=0; n<pC->docs[d].length; n++)
			free( phi[d][n] );
		free( phi[d] );
	}
	free( theta );
	free( phi );

	return nIt;
}
コード例 #3
0
ファイル: main.cpp プロジェクト: BoxLib-Codes/BoxLib
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();
}
コード例 #4
0
ファイル: pviterbi.c プロジェクト: tempbottle/ghmm
/*============================================================================*/
int *ghmm_dpmodel_viterbi_variable_tb(ghmm_dpmodel *mo, ghmm_dpseq * X, ghmm_dpseq * Y,
				 double *log_p, int *path_length,
				 int start_traceback_with) {
#define CUR_PROC "ghmm_dpmodel_viterbi"
  int u, v, j, i, off_x, off_y, current_state_index;
  double value, max_value, previous_prob;  
  plocal_store_t *pv;
  int *state_seq = NULL;
  int emission;
  double log_b_i, log_in_a_ij;
  double (*log_in_a)(plocal_store_t*, int, int, ghmm_dpseq*, ghmm_dpseq*, int, int);

  /* printf("---- viterbi -----\n"); */
  i_list * state_list;
  state_list = ighmm_list_init_list();
  log_in_a = &sget_log_in_a;
  /* int len_path  = mo->N*len; the length of the path is not known apriori */

/*   if (mo->model_type & kSilentStates &&  */
/*       mo->silent != NULL &&  */
/*       mo->topo_order == NULL) { */
/*     ghmm_dmodel_topo_order( mo );  */
/*   } */

  /* Allocate the matrices log_in_a, log_b,Vektor phi, phi_new, Matrix psi */
  pv = pviterbi_alloc(mo, X->length, Y->length);
  if (!pv)                        { GHMM_LOG_QUEUED(LCONVERTED); goto STOP; }

  /* Precomputing the log(a_ij) and log(bj(ot)) */
  pviterbi_precompute(mo, pv);
  /* Initialize the lookback matrix (for positions [-offsetX,0], [-1, len_y]*/
  init_phi(pv, X, Y);
  
  /* u > max_offset_x , v starts -1 to allow states with offset_x == 0 
     which corresponds to a series of gap states before reading the first 
     character of x at position x=0, y=v */
  /** THIS IS THE MAIN RECURRENCE **/
  for (u = mo->max_offset_x + 1; u < X->length; u++) {
    for (v = -mo->max_offset_y; v < Y->length; v++) {
      for (j = 0; j < mo->N; j++) 
	{
	  /** initialization of phi (lookback matrix), psi (traceback) **/
	  set_phi(pv, u, v, j, +1);
	  set_psi(pv, u, v, j, -1);
	}
      
      for (i = 0; i < mo->N; i++) {
	/* Determine the maximum */
	/* max_phi = phi[i] + log_in_a[j][i] ... */
	if (!(mo->model_type & GHMM_kSilentStates) || !mo->silent[i] ) {
	  max_value = -DBL_MAX;
	  set_psi(pv, u, v, i, -1);
	  for (j = 0; j < mo->s[i].in_states; j++) {
	    /* look back in the phi matrix at the offsets */
	    previous_prob = get_phi(pv, u, v, mo->s[i].offset_x, mo->s[i].offset_y, mo->s[i].in_id[j]);
	    log_in_a_ij = (*log_in_a)(pv, i, j, X, Y, u, v);
	    if ( previous_prob != +1 && log_in_a_ij != +1) {
	      value = previous_prob + log_in_a_ij;
	      if (value > max_value) {
		max_value = value;
		set_psi(pv, u, v, i, mo->s[i].in_id[j]);
	      }
	    }
	    else
	      {;} /* fprintf(stderr, " %d --> %d = %f, \n", i,i,v->log_in_a[i][i]); */
	  }

	  emission = ghmm_dpmodel_pair(ghmm_dpseq_get_char(X, mo->s[i].alphabet, u), 
			      ghmm_dpseq_get_char(Y, mo->s[i].alphabet, v),
			      mo->size_of_alphabet[mo->s[i].alphabet],
			      mo->s[i].offset_x, mo->s[i].offset_y);
#ifdef DEBUG
	  if (emission > ghmm_dpmodel_emission_table_size(mo, i)){
	    printf("State %i\n", i);
	    ghmm_dpmodel_state_print(&(mo->s[i]));
	    printf("charX: %i charY: %i alphabet size: %i emission table: %i emission index: %i\n", 
		   ghmm_dpseq_get_char(X, mo->s[i].alphabet, u),
		   ghmm_dpseq_get_char(Y, mo->s[i].alphabet, v),
		   mo->size_of_alphabet[mo->s[i].alphabet],
		   ghmm_dpmodel_emission_table_size(mo, i), emission);
	  }
#endif
	  log_b_i = log_b(pv, i, ghmm_dpmodel_pair(ghmm_dpseq_get_char(X, mo->s[i].alphabet, u), 
				      ghmm_dpseq_get_char(Y, mo->s[i].alphabet, v),
				      mo->size_of_alphabet[mo->s[i].alphabet],
				      mo->s[i].offset_x, mo->s[i].offset_y));

	  /* No maximum found (that is, state never reached)
	     or the output O[t] = 0.0: */
	  if (max_value == -DBL_MAX ||/* and then also: (v->psi[t][j] == -1) */
	      log_b_i == +1 ) {
	    set_phi(pv, u, v, i, +1);
	  }
	  else
	    set_phi(pv, u, v, i, max_value + log_b_i);
	}
      } /* complete time step for emitting states */
    
	/* last_osc = osc; */ 
        /* save last transition class */

      /*if (mo->model_type & kSilentStates) { 
	p__viterbi_silent( mo, t, v );
	}*/ /* complete time step for silent states */
      
      /**************
    for (j = 0; j < mo->N; j++) 
      {      
	printf("\npsi[%d],in:%d, phi=%f\n", t, v->psi[t][j], v->phi[j]);
       }
      
    for (i = 0; i < mo->N; i++){
      printf("%d\t", former_matchcount[i]);
    }

    for (i = 0; i < mo->N; i++){
      printf("%d\t", recent_matchcount[i]);
    }
      ****************/
    } /* End for v in Y */
    /* Next character in X */
    push_back_phi(pv, Y->length);
  } /* End for u in X */

  /* Termination */
  max_value = -DBL_MAX;
  ighmm_list_append(state_list, -1);
  /* if start_traceback_with is -1 (it is by default) search for the most 
     likely state at the end of both sequences */
  if (start_traceback_with == -1) {
    for (j = 0; j < mo->N; j++){
#ifdef DEBUG
      printf("phi(len_x)(len_y)(%i)=%f\n", j, get_phi(pv, u, Y->length-1, 0, 0, j));
#endif
      if ( get_phi(pv, u, Y->length-1, 0, 0, j) != +1 && 
	   get_phi(pv, u, Y->length-1, 0, 0, j) > max_value) { 
	max_value = get_phi(pv, X->length-1, Y->length-1, 0, 0, j);
	state_list->last->val = j;
      }
    }
  }
  /* this is the special traceback mode for the d & c algorithm that also 
     connects the traceback to the first state of the rest of the path */
  else {
#ifdef DEBUG
    printf("D & C traceback from state %i!\n", start_traceback_with);
    printf("Last characters emitted X: %i, Y: %i\n", 
	   ghmm_dpseq_get_char(X, mo->s[start_traceback_with].alphabet, 
			       X->length-1),
	   ghmm_dpseq_get_char(Y, mo->s[start_traceback_with].alphabet, 
			       Y->length-1));
    for (j = 0; j < mo->N; j++){
      printf("phi(len_x)(len_y)(%i)=%f\n", j, get_phi(pv, X->length-1, Y->length-1, 0, 0, j)); 
    }
#endif
    max_value = get_phi(pv, X->length-1, Y->length-1, 0, 0, start_traceback_with);
    if (max_value != 1 && max_value > -DBL_MAX)
      state_list->last->val = start_traceback_with;
  }
  if (max_value == -DBL_MAX) {
    /* Sequence can't be generated from the model! */
    *log_p = +1;
    /* Backtracing doesn't work, because state_seq[*] allocated with -1 */
    /* for (t = len - 2; t >= 0; t--)
       state_list->last->val = -1;    */
  }
  else {
    /* Backtracing, should put DEL path nicely */
    *log_p = max_value;
    /* removed the handling of silent states here */
    /* start trace back at the end of both sequences */
    u = X->length - 1;
    v = Y->length - 1;
    current_state_index = state_list->first->val;
    off_x = mo->s[current_state_index].offset_x;
    off_y = mo->s[current_state_index].offset_y;
    while (u - off_x >= -1 && v - off_y >= -1 && current_state_index != -1) { 
      /* while (u > 0 && v > 0) { */
      /* look up the preceding state and save it in the first position of the
	 state list */
      /* printf("Current state %i at (%i,%i) -> preceding state %i\n", 
	 current_state_index, u, v, get_psi(pv, u, v, current_state_index)); */
      /* update the current state */
      current_state_index = get_psi(pv, u, v, current_state_index);
      if (current_state_index != -1)
	ighmm_list_insert(state_list, current_state_index);
      /* move in the alignment matrix */
      u -= off_x;
      v -= off_y; 
      /* get the next offsets */
      off_x = mo->s[current_state_index].offset_x;
      off_y = mo->s[current_state_index].offset_y;
    }
  }
  
  /* Free the memory space */
  pviterbi_free(&pv, mo->N, X->length, Y->length, mo->max_offset_x , 
		mo->max_offset_y);
  /* printf("After traceback: last state = %i\n", state_list->last->val); */
  state_seq = ighmm_list_to_array(state_list);
  *path_length = state_list->length;
  /* PRINT PATH */
  
/*   fprintf(stderr, "Viterbi path: " ); */
/*   int t; */
/*   for(t=0; t < *path_length; t++) */
/*     if (state_seq[t] >= 0) fprintf(stderr, " %d ",  state_seq[t]); */
/*   fprintf(stderr, "\n Freeing ... \n");  */
  return (state_seq);
STOP:     /* Label STOP from ARRAY_[CM]ALLOC */
  /* Free the memory space */
  pviterbi_free(&pv, mo->N, X->length, Y->length, mo->max_offset_x, 
		mo->max_offset_y);
  m_free(state_seq);
  ighmm_list_free(state_list);
  return NULL;
#undef CUR_PROC
} /* viterbi */
コード例 #5
0
ファイル: main.cpp プロジェクト: BoxLib-Codes/BoxLib
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;
  }
}