int main(void){
  double *u_past;
  double *u_present;

  double delta_x=0.01;
  int n_x = (int)(10.0/delta_x);
  double delta_t = 1E-4;
  int n_t = (int)(2.0/delta_t);  
  double c = 1.0;
  int i;

  /*reserva memoria*/
  u_past = malloc(n_x * sizeof(double));
  u_present = malloc(n_x * sizeof(double));
  
  /*inicializacion*/
  initial_condition(u_past, n_x, delta_x);

  for(i=0;i<n_t;i++){
    update_u(u_present, u_past, n_x,delta_x, delta_t, c); 
    copy(u_present, u_past, n_x);
  }

  /*imprime en pantalla*/
  print_u(u_past, n_x);
  return 0;
}
Exemplo n.º 2
0
tree
hide_evolution_in_other_loops_than_loop (tree chrec,
					 unsigned loop_num)
{
  struct loop *loop = get_loop (cfun, loop_num), *chloop;
  if (automatically_generated_chrec_p (chrec))
    return chrec;

  switch (TREE_CODE (chrec))
    {
    case POLYNOMIAL_CHREC:
      chloop = get_chrec_loop (chrec);

      if (chloop == loop)
	return build_polynomial_chrec
	  (loop_num,
	   hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec),
						    loop_num),
	   CHREC_RIGHT (chrec));

      else if (flow_loop_nested_p (chloop, loop))
	/* There is no evolution in this loop.  */
	return initial_condition (chrec);

      else
	{
	  gcc_assert (flow_loop_nested_p (loop, chloop));
	  return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec),
							  loop_num);
	}

    default:
      return chrec;
    }
}
Exemplo n.º 3
0
tree 
hide_evolution_in_other_loops_than_loop (tree chrec, 
					 unsigned loop_num)
{
  if (automatically_generated_chrec_p (chrec))
    return chrec;
  
  switch (TREE_CODE (chrec))
    {
    case POLYNOMIAL_CHREC:
      if (CHREC_VARIABLE (chrec) == loop_num)
	return build_polynomial_chrec 
	  (loop_num, 
	   hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
						    loop_num), 
	   CHREC_RIGHT (chrec));
      
      else if (CHREC_VARIABLE (chrec) < loop_num)
	/* There is no evolution in this loop.  */
	return initial_condition (chrec);
      
      else
	return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
							loop_num);
      
    default:
      return chrec;
    }
}
Exemplo n.º 4
0
tree
initial_condition (tree chrec)
{
  if (automatically_generated_chrec_p (chrec))
    return chrec;

  if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
    return initial_condition (CHREC_LEFT (chrec));
  else
    return chrec;
}
Exemplo n.º 5
0
int main()
{
  const double ti=0.0;
  const double te=17.0652165601579625588917206249;
  std::vector<double> position;
  std::vector<double> velocity;
  initial_condition(position, velocity);
  //euler(position, velocity, ti, te);
  rk4(position, velocity, ti, te);
  return 0;
}
Exemplo n.º 6
0
static bool main_loop (void) {
  unsigned int app_state = 0;
  unsigned long int counter = 0;
  double s, t;

  initial_condition(n, px, py, vx, vy, m);

  s = 0.0;

  NBODY_OMP_PARALLEL
    do {
      NBODY_OMP_MASTER
	{
	  t = timer();
	}

      physics_advance(dt, n, px, py, vx, vy, m);

      NBODY_OMP_MASTER
	{
	  t = timer() - t;
	  s += t;

	  if (draw_redraw()) {
	    draw_particles(dt, n, px, py, vx, vy, m);
	    app_state = draw_input(app_state, &dt);
	  }

	  counter += 1;

	  if ((counter % 1000LU) == 0)
	    printf("%lu\n", counter);
	}
      NBODY_OMP_BARRIER
	;
    } while (! (app_state & EXIT) &&
	     ! (app_state & RESET));

  printf("%lu physics iterations over %f seconds, ratio %f\n",
  	 counter, s, counter/s);

  return app_state & RESET;
}
int main(){


	double x_f = 1.0;
	int n_x = 1000;
	double delta_x = 0.001;

	double delta_t = 5E-4;
	int n_t = 350.0;
	double c = 1.0;
	double r = c * delta_t/delta_x;

	double *u_past = malloc(n_x*sizeof(double));
	double *u_present = malloc(n_x*sizeof(double));
	double *u_future = malloc(n_x*sizeof(double));
	
	initial_condition(u_past, n_x, delta_x);
	/*print_u(u_past, n_x, delta_x);*/
	
	u_past[0] = 0.0;
	u_past[n_x-1] = 0.0;
	
	u_present[0] = 0.0;
	u_present[n_x-1] = 0.0;
	
	first_iteration(u_present, u_past, n_x, r);
	copy(u_present, u_past, n_x);
	/*print_u(u_present, n_x, delta_x);*/
	
	int i;
	for(i=0;i<n_t;i++){
		update_u(u_future, u_present, u_past, n_x, r);
		copy(u_present, u_past, n_x);
		copy(u_future, u_present, n_x);
	}
	print_u(u_present, n_x, delta_x);

	return 0;
}
int main ( )

/******************************************************************************/
/*
  Purpose:

    FD1D_ADVECTION_FTCS solves the advection equation using the FTCS method.

  Discussion:

    The FTCS method is unstable for the advection problem.

    Given a smooth initial condition, successive FTCS approximations will
    exhibit erroneous oscillations of increasing magnitude.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    25 December 2012

  Author:

    John Burkardt
*/
{
  double a;
  double b;
  double c;
  char command_filename[] = "advection_commands.txt";
  FILE *command_unit;
  char data_filename[] = "advection_data.txt";
  FILE *data_unit;
  double dt;
  double dx;
  int i;
  int j;
  int jm1;
  int jp1;
  int nx;
  int nt;
  int nt_step;
  int plotstep;
  double t;
  double *u;
  double *unew;
  double *x;

  timestamp ( );
  printf ( "\n" );
  printf ( "FD1D_ADVECTION_FTCS:\n" );
  printf ( "  C version\n" );
  printf ( "\n" );
  printf ( "  Solve the constant-velocity advection equation in 1D,\n" );
  printf ( "    du/dt = - c du/dx\n" );
  printf ( "  over the interval:\n" );
  printf ( "    0.0 <= x <= 1.0\n" );
  printf ( "  with periodic boundary conditions, and\n" );
  printf ( "  with a given initial condition\n" );
  printf ( "    u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" );
  printf ( "           = 0 elsewhere.\n" );
  printf ( "\n" );
  printf ( "  We use a method known as FTCS:\n" );
  printf ( "   FT: Forward Time  : du/dt = (u(t+dt,x)-u(t,x))/dt\n" );
  printf ( "   CS: Centered Space: du/dx = (u(t,x+dx)-u(t,x-dx))/2/dx\n" );

  nx = 101;
  dx = 1.0 / ( double ) ( nx - 1 );
  a = 0.0;
  b = 1.0;
  x = r8vec_linspace_new ( nx, a, b );
  nt = 1000;
  dt = 1.0 / ( double ) ( nt );
  c = 1.0;

  u = initial_condition ( nx, x );
/*
  Open data file, and write solutions as they are computed.
*/
  data_unit = fopen ( data_filename, "wt" );

  t = 0.0;
  fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[0], t, u[0] );
  for ( j = 0; j < nx; j++ )
  {
    fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[j], t, u[j] );
  }
  fprintf ( data_unit, "\n" );

  nt_step = 100;

  printf ( "\n" );
  printf ( "  Number of nodes NX = %d\n", nx );
  printf ( "  Number of time steps NT = %d\n", nt );
  printf ( "  Constant velocity C = %g\n", c );

  unew = ( double * ) malloc ( nx * sizeof ( double ) );

  for ( i = 0; i < nt; i++ )
  {
    for ( j = 0; j < nx; j++ )
    {
      jm1 = i4_wrap ( j - 1, 0, nx - 1 );
      jp1 = i4_wrap ( j + 1, 0, nx - 1 );
      unew[j] = u[j] - c * dt / dx / 2.0 * ( u[jp1] - u[jm1] );
    }
    for ( j = 0; j < nx; j++ )
    {
      u[j] = unew[j];
    }
    if ( i == nt_step - 1 )
    {
      t = ( double ) ( i ) * dt;
      for ( j = 0; j < nx; j++ )
      {
        fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[j], t, u[j] );
      }
      fprintf ( data_unit, "\n" );
      nt_step = nt_step + 100;
    }
  }
/*
  Close the data file once the computation is done.
*/
  fclose ( data_unit );

  printf ( "\n" );
  printf ( "  Plot data written to the file \"%s\"\n", data_filename );
/*
  Write gnuplot command file.
*/
  command_unit = fopen ( command_filename, "wt" );

  fprintf ( command_unit, "set term png\n" );
  fprintf ( command_unit, "set output 'advection.png'\n" );
  fprintf ( command_unit, "set grid\n" );
  fprintf ( command_unit, "set style data lines\n" );
  fprintf ( command_unit, "unset key\n" );
  fprintf ( command_unit, "set xlabel '<---X--->'\n");
  fprintf ( command_unit, "set ylabel '<---Time--->'\n" );
  fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename );
  fprintf ( command_unit, "quit\n" );

  fclose ( command_unit );

  printf ( "  Gnuplot command data written to the file \"%s\"\n",  
    command_filename );
/*
  Free memory.
*/
  free ( u );
  free ( unew );
  free ( x );
/*
  Terminate.
*/
  printf ( "\n" );
  printf ( "FD1D_ADVECTION_FTCS\n" );
  printf ( "  Normal end of execution.\n" );
  printf ( "\n" );
  timestamp ( );

  return 0;
}
int main ( )

/******************************************************************************/
/*
  Purpose:

    FD1D_ADVECTION_LAX_WENDROFF: advection equation using Lax-Wendroff method.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    11 March 2013

  Author:

    John Burkardt
*/
{
  double a;
  double b;
  double c;
  double c1;
  double c2;
  char command_filename[] = "advection_commands.txt";
  FILE *command_unit;
  char data_filename[] = "advection_data.txt";
  FILE *data_unit;
  double dt;
  double dx;
  int i;
  int j;
  int jm1;
  int jp1;
  int nx;
  int nt;
  int nt_step;
  int plotstep;
  double t;
  double *u;
  double *unew;
  double *x;

  timestamp ( );
  printf ( "\n" );
  printf ( "FD1D_ADVECTION_LAX_WENDROFF:\n" );
  printf ( "  C version\n" );
  printf ( "\n" );
  printf ( "  Solve the constant-velocity advection equation in 1D,\n" );
  printf ( "    du/dt = - c du/dx\n" );
  printf ( "  over the interval:\n" );
  printf ( "    0.0 <= x <= 1.0\n" );
  printf ( "  with periodic boundary conditions, and\n" );
  printf ( "  with a given initial condition\n" );
  printf ( "    u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" );
  printf ( "           = 0 elsewhere.\n" );
  printf ( "\n" );
  printf ( "  We modify the FTCS method using the Lax-Wendroff method:\n" );

  nx = 101;
  dx = 1.0 / ( double ) ( nx - 1 );
  a = 0.0;
  b = 1.0;
  x = r8vec_linspace_new ( nx, a, b );
  nt = 1000;
  dt = 1.0 / ( double ) ( nt );
  c = 1.0;
  c1 = 0.5 * c * dt / dx;
  c2 = 0.5 * pow ( c * dt / dx, 2 );

  u = initial_condition ( nx, x );
/*
  Open data file, and write solutions as they are computed.
*/
  data_unit = fopen ( data_filename, "wt" );

  t = 0.0;
  fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[0], t, u[0] );
  for ( j = 0; j < nx; j++ )
  {
    fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[j], t, u[j] );
  }
  fprintf ( data_unit, "\n" );

  nt_step = 100;

  printf ( "\n" );
  printf ( "  Number of nodes NX = %d\n", nx );
  printf ( "  Number of time steps NT = %d\n", nt );
  printf ( "  Constant velocity C = %g\n", c );
  printf ( "  CFL condition: dt (%g) <= dx / c (%g)\n", dt, dx / c );

  unew = ( double * ) malloc ( nx * sizeof ( double ) );

  for ( i = 0; i < nt; i++ )
  {
    for ( j = 0; j < nx; j++ )
    {
      jm1 = i4_wrap ( j - 1, 0, nx - 1 );
      jp1 = i4_wrap ( j + 1, 0, nx - 1 );
      unew[j] = u[j] - c1 * ( u[jp1] - u[jm1] ) 
        + c2 * ( u[jp1] - 2.0 * u[j] + u[jm1] );
    }
    for ( j = 0; j < nx; j++ )
    {
      u[j] = unew[j];
    }
    if ( i == nt_step - 1 )
    {
      t = ( double ) ( i ) * dt;
      for ( j = 0; j < nx; j++ )
      {
        fprintf ( data_unit, "%10.4f  %10.4f  %10.4f\n", x[j], t, u[j] );
      }
      fprintf ( data_unit, "\n" );
      nt_step = nt_step + 100;
    }
  }
/*
  Close the data file once the computation is done.
*/
  fclose ( data_unit );

  printf ( "\n" );
  printf ( "  Plot data written to the file \"%s\"\n", data_filename );
/*
  Write gnuplot command file.
*/
  command_unit = fopen ( command_filename, "wt" );

  fprintf ( command_unit, "set term png\n" );
  fprintf ( command_unit, "set output 'advection_lax_wendroff.png'\n" );
  fprintf ( command_unit, "set grid\n" );
  fprintf ( command_unit, "set style data lines\n" );
  fprintf ( command_unit, "unset key\n" );
  fprintf ( command_unit, "set xlabel '<---X--->'\n");
  fprintf ( command_unit, "set ylabel '<---Time--->'\n" );
  fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename );
  fprintf ( command_unit, "quit\n" );

  fclose ( command_unit );

  printf ( "  Gnuplot command data written to the file \"%s\"\n",  
    command_filename );
/*
  Free memory.
*/
  free ( u );
  free ( unew );
  free ( x );
/*
  Terminate.
*/
  printf ( "\n" );
  printf ( "FD1D_ADVECTION_LAX_WENDROFF\n" );
  printf ( "  Normal end of execution.\n" );
  printf ( "\n" );
  timestamp ( );

  return 0;
}
Exemplo n.º 10
0
void update ( int id, int p )

/******************************************************************************/
/*
  Purpose:

    UPDATE computes the solution of the heat equation.

  Discussion:

    If there is only one processor ( P == 1 ), then the program writes the
    values of X and H to files.

  Parameters:

    Input, int ID, the id of this processor.

    Input, int P, the number of processors.
*/
{
  double cfl;

  double *h;
  FILE *h_file;
  double *h_new;
  int i;
  int j;
  int j_min = 0;
  int j_max = 400;
  double k = 0.002;
  int n = 11;
  MPI_Status status;
  int tag;
  double time;
  double time_delta;
  double time_max = 10.0;
  double time_min = 0.0;
  double time_new;
  double *x;
  double x_delta;
  FILE *x_file;
  double x_max = 1.0;
  double x_min = 0.0;
/*
  Have process 0 print out some information.
*/
  if ( id == 0 )
  {
    printf ( "\n" );
    printf ( "  Compute an approximate solution to the time dependent\n" );
    printf ( "  one dimensional heat equation:\n" );
    printf ( "\n" );
    printf ( "    dH/dt - K * d2H/dx2 = f(x,t)\n" );
    printf ( "\n" );
    printf ( "  for %f = x_min < x < x_max = %f\n", x_min, x_max );
    printf ( "\n" );
    printf ( "  and %f = time_min < t <= t_max = %f\n", time_min, time_max );
    printf ( "\n" );
    printf ( "  Boundary conditions are specified at x_min and x_max.\n" );
    printf ( "  Initial conditions are specified at time_min.\n" );
    printf ( "\n" );
    printf ( "  The finite difference method is used to discretize the\n" );
    printf ( "  differential equation.\n" );
    printf ( "\n" );
    printf ( "  This uses %d equally spaced points in X\n", p * n );
    printf ( "  and %d equally spaced points in time.\n", j_max );
    printf ( "\n" );
    printf ( "  Parallel execution is done using %d processors.\n", p );
    printf ( "  Domain decomposition is used.\n" );
    printf ( "  Each processor works on %d nodes, \n", n );
    printf ( "  and shares some information with its immediate neighbors.\n" );
  }
/*
  Set the X coordinates of the N nodes.
  We don't actually need ghost values of X but we'll throw them in
  as X[0] and X[N+1].
*/
  x = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) );

  for ( i = 0; i <= n + 1; i++ )
  {
    x[i] = ( ( double ) (         id * n + i - 1 ) * x_max
           + ( double ) ( p * n - id * n - i     ) * x_min )
           / ( double ) ( p * n              - 1 );
  }
/*
  In single processor mode, write out the X coordinates for display.
*/
  if ( p == 1 )
  {
    x_file = fopen ( "x_data.txt", "w" );
    for ( i = 1; i <= n; i++ )
    {
      fprintf ( x_file, "  %f", x[i] );
    }
    fprintf ( x_file, "\n" );

    fclose ( x_file );
  }
/*
  Set the values of H at the initial time.
*/
  time = time_min;
  h = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) );
  h_new = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) );
  h[0] = 0.0;
  for ( i = 1; i <= n; i++ )
  {
    h[i] = initial_condition ( x[i], time );
  }
  h[n+1] = 0.0;
  
  time_delta = ( time_max - time_min ) / ( double ) ( j_max - j_min );
  x_delta = ( x_max - x_min ) / ( double ) ( p * n - 1 );
/*
  Check the CFL condition, have processor 0 print out its value,
  and quit if it is too large.
*/
  cfl = k * time_delta / x_delta / x_delta;

  if ( id == 0 ) 
  {
    printf ( "\n" );
    printf ( "UPDATE\n" );
    printf ( "  CFL stability criterion value = %f\n", cfl );
  }

  if ( 0.5 <= cfl ) 
  {
    if ( id == 0 )
    {
      printf ( "\n" );
      printf ( "UPDATE - Warning!\n" );
      printf ( "  Computation cancelled!\n" );
      printf ( "  CFL condition failed.\n" );
      printf ( "  0.5 <= K * dT / dX / dX = %f\n", cfl );
    }
    return;
  }
/*
  In single processor mode, write out the values of H.
*/
  if ( p == 1 )
  {
    h_file = fopen ( "h_data.txt", "w" );

    for ( i = 1; i <= n; i++ )
    {
      fprintf ( h_file, "  %f", h[i] );
    }
    fprintf ( h_file, "\n" );
  }
/*
  Compute the values of H at the next time, based on current data.
*/
  for ( j = 1; j <= j_max; j++ )
  {

    time_new = ( ( double ) (         j - j_min ) * time_max
               + ( double ) ( j_max - j         ) * time_min )
               / ( double ) ( j_max     - j_min );
/*
  Send H[1] to ID-1.
*/
    if ( 0 < id )
    {
      tag = 1;
      MPI_Send ( &h[1], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD );
    }
/*
  Receive H[N+1] from ID+1.
*/
    if ( id < p-1 )
    {
      tag = 1;
      MPI_Recv ( &h[n+1], 1,  MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD, &status );
    }
/*
  Send H[N] to ID+1.
*/
    if ( id < p-1 )
    {
      tag = 2;
      MPI_Send ( &h[n], 1, MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD );
    }
/*
  Receive H[0] from ID-1.
*/
    if ( 0 < id )
    {
      tag = 2;
      MPI_Recv ( &h[0], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD, &status );
    }
/*
  Update the temperature based on the four point stencil.
*/
    for ( i = 1; i <= n; i++ )
    {
      h_new[i] = h[i] 
      + ( time_delta * k / x_delta / x_delta ) * ( h[i-1] - 2.0 * h[i] + h[i+1] ) 
      + time_delta * rhs ( x[i], time );
    }
/*
  H at the extreme left and right boundaries was incorrectly computed
  using the differential equation.  Replace that calculation by
  the boundary conditions.
*/
    if ( 0 == id )
    {
      h_new[1] = boundary_condition ( x[1], time_new );
    }
    if ( id == p - 1 )
    {
      h_new[n] = boundary_condition ( x[n], time_new );
    }
/*
  Update time and temperature.
*/
    time = time_new;

    for ( i = 1; i <= n; i++ )
    {
      h[i] = h_new[i];
    }
/*
  In single processor mode, add current solution data to output file.
*/
    if ( p == 1 )
    {
      for ( i = 1; i <= n; i++ )
      {
        fprintf ( h_file, "  %f", h[i] );
      }
      fprintf ( h_file, "\n" );
    }
  }

  if ( p == 1 )
  {
    fclose ( h_file );
  }

  free ( h );
  free ( h_new );
  free ( x );

  return;
}
Exemplo n.º 11
0
int main(int argc, char **argv){
  int i,j,k,n; 
  int nsteps=150;
  double dt =0.01;
  
  /* Computational (2D polar) grid coordinates */
  int nx1 = 400;
  int nx2 = 400;

  //number of ghost cells on both sides of each dimension
  //only need 1 for piecewise constant method
  //need 2 for piecewise linear reconstruction
  int num_ghost = 2;
  int nx1_r = nx1;
  int nx2_r = nx2;
  nx1 += 2*num_ghost; 
  nx2 += 2*num_ghost; 

  /*non-ghost indices */
  int is = num_ghost;
  int ie= is+nx1_r; 
  int js = num_ghost;
  int je = js+nx2_r; 

  //convention: these ranges refer to the non-ghost cells
  //however, the ghost cells have real coordinate interpretations
  //this means that we must be sure that the number of ghost cells makes sense with the range of coordinates
  //this is a big problem if the phi polar coordinate runs the whole range [0,2pi) for example

  //further, all mesh structures (zonal and nodal) will be nx1 x nx2, although we may not fill the ghost entries with anything meaningful
  //this is to standardize the loop indexing from is:ie

  /*another convention: when the phi coordinate is periodic, do we repeat the boundary mesh points? yes for now */

  double lx1 = 2.0;//these values are inclusive [x1_i, x1_f]
  double lx2 = M_PI;
  double x1_i = 0.5;
  double x2_i = 0.0;

  double dx2 = lx2/(nx2_r-1);   
  double x2_f = x2_i + lx2;

  if(X2_PERIODIC){
    dx2 = 2*M_PI/(nx2_r);   
    lx2 = dx2*(nx2_r-1); 
    x2_i = 0.0;
  }

  double dx1 = lx1/(nx1_r-1);   
  double x1_f = x1_i + lx1;

  printf("dx1=%lf dx2=%lf \n",dx1,dx2); 
  
  /*Cell centered (zonal) values of computational coordinate position */
  double *x1 = (double *) malloc(sizeof(double)*nx1); 
  double *x2 = (double *) malloc(sizeof(double)*nx2);
  x1[is] = x1_i;
  x2[js] = x2_i;
  for(i=is+1; i<ie; i++){ 
    x1[i] = x1[i-1] + dx1;
    //    printf("%lf\n",x1[i]);
  }
  for(i=js+1; i<je; i++){
    x2[i] = x2[i-1] + dx2;
    //printf("%lf\n",x2[i]);
  } 

  /*Mesh edge (nodal) values of computational coordinate position */
  double *x1_b = (double *) malloc(sizeof(double)*(nx1+1)); 
  double *x2_b = (double *) malloc(sizeof(double)*(nx2+1));
  x1_b[is] = x1_i - dx1/2;
  x2_b[js] = x2_i - dx2/2;
  for(i=is+1; i<=ie; i++){ 
    x1_b[i] = x1_b[i-1] + dx1;
    //    printf("%lf\n",x1_b[i]);
  }
  for(i=js+1; i<=je; i++){
    x2_b[i] = x2_b[i-1] + dx2;
    //printf("%lf\n",x2_b[i]);
  } 

  /*Cell centered (zonal) values of physical coordinate position */
  //These must be 2D arrays since coordinate transformation is not diagonal
  //indexed by x1 rows and x2 columns
  double **x = (double **) malloc(sizeof(double *)*nx1); 
  double **y = (double **) malloc(sizeof(double *)*nx1);
  double *dataX = (double *) malloc(sizeof(double)*nx1*nx2);
  double *dataY = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    x[i] = &(dataX[nx2*i]);
    y[i] = &(dataY[nx2*i]);
  }

  /*precompute coordinate mappings */
  for(i=is; i<ie; i++){
    for(j=js; j<je; j++){
      x[i][j] = X_physical(x1[i],x2[j]); 
      y[i][j] = Y_physical(x1[i],x2[j]); 
    }
  }
  /*Mesh edge (nodal) values of physical coordinate position */
  double **x_b = (double **) malloc(sizeof(double *)*(nx1+1)); 
  double **y_b = (double **) malloc(sizeof(double *)*(nx1+1));
  double *dataXb = (double *) malloc(sizeof(double)*(nx1+1)*(nx2+1));
  double *dataYb = (double *) malloc(sizeof(double)*(nx1+1)*(nx2+1));
  for(i=0; i<=nx1; i++){
    x_b[i] = &(dataXb[(nx2+1)*i]);
    y_b[i] = &(dataYb[(nx2+1)*i]);
  }
  for(i=is; i<=ie; i++){
    for(j=js; j<=je; j++){
      x_b[i][j] = X_physical(x1_b[i],x2_b[j]); 
      y_b[i][j] = Y_physical(x1_b[i],x2_b[j]); 
    }
  }
  /*Edge normal vectors in Cartesian coordinates */
  // point radially outward and +\phi
  

  /*Coordinate cell capacity */
  double **kappa;
  double *datakappa;
  kappa = (double **) malloc(sizeof(double *)*nx1);
  datakappa = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    kappa[i] = &(datakappa[nx2*i]);
  }
  
  for(i=is; i<ie; i++){
    for(j=js; j<je; j++){
      kappa[i][j] = x1[i]*dx1*dx2/(dx1*dx2); // C_ij/(dx1*dx2)
      //capacity in ghost cells
      kappa[ie][j] = (x1[ie-1]+dx1)*dx1*dx2/(dx1*dx2); 
    }
    kappa[i][je] = (x1[i]+dx1)*dx1*dx2/(dx1*dx2); 
  }
 
  /*Average normal edge velocities */
  //now we move from cell centered quantities to edge quantities 
  //the convention in this code is that index i refers to i-1/2 edge
  double **U, **V;
  double *dataU, *dataV; 
  U = (double **) malloc(sizeof(double *)*nx1);
  V = (double **) malloc(sizeof(double *)*nx1);
  dataU = (double *) malloc(sizeof(double)*nx1*nx2);
  dataV = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    U[i] = &(dataU[nx2*i]);
    V[i] = &(dataV[nx2*i]);
  }
  
  /*Option #1 for computing edge velocities: path integral of Cartesian stream function */
  /* Stream function */ //probably dont need this array
  //this variable is cell centered stream 
  /* double **stream;
  double *datastream;
  stream = (double **) malloc(sizeof(double *)*nx1);
  datastream = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    stream[i] = &(datastream[nx2*i]);
  }
  for(i=is; i<ie; i++){
    for(j=js; j<je; j++){
      stream[i][j] = stream_function(x[i][j],y[i][j]);
    }
  }
 
   for(i=is; i<ie; i++){
    for(j=js; j<je; j++){ //go an additional step to capture nx2_r+1/2
      //average the corner stream functions
      U[i][j]= (stream_function(X_physical(x1[i]-dx1/2,x2[j]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j]+dx2/2)) - 
		stream_function(X_physical(x1[i]-dx1/2,x2[j]-dx2/2),Y_physical(x1[i]-dx1/2,x2[j]-dx2/2)))/(dx2);
      V[i][j]= -(stream_function(X_physical(x1[i]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i]+dx1/2,x2[j]-dx2/2)) - 
      	 stream_function(X_physical(x1[i]-dx1/2,x2[j]-dx2/2),Y_physical(x1[i]-dx1/2,x2[j]-dx2/2)))/dx1;
      if(j==10)
	printf("i=%d, u,v=%lf,%lf\n",i,U[i][j],V[i][j]); 
    }
    j=je;
    U[i][j]= (stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+3*dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+3*dx2/2)) - 
	      stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+dx2/2)))/(dx2);
    V[i][j]= -(stream_function(X_physical(x1[i]+dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]+dx1/2,x2[j-1]+dx2/2)) - 
	       stream_function(X_physical(x1[i]-dx1/2,x2[j-1]+dx2/2),Y_physical(x1[i]-dx1/2,x2[j-1]+dx2/2)))/dx1;
  }
  i=ie;
  for(j=js; j<je; j++){
    U[i][j]= (stream_function(X_physical(x1[i-1]+dx1/2,x2[j]+dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]+dx2/2)) - 
	      stream_function(X_physical(x1[i-1]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]-dx2/2)))/(dx2);
    V[i][j]= -(stream_function(X_physical(x1[i-1]+3*dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+3*dx1/2,x2[j]-dx2/2)) - 
	      stream_function(X_physical(x1[i-1]+dx1/2,x2[j]-dx2/2),Y_physical(x1[i-1]+dx1/2,x2[j]-dx2/2)))/dx1;
  } 
  */
  double ux,vy,temp; 
  for(i=is; i<=ie; i++){
    for(j=js; j<=je; j++){ 
      /*Option #2: directly specify velocity in Cartesian coordinate basis as a function of cartesian position*/   
      
      //radial face i-1/2
      velocity_physical(X_physical(x1_b[i],x2_b[j]+dx2/2),Y_physical(x1_b[i],x2_b[j]+dx2/2),&ux,&vy);
      // Average normal edge velocity: just transform face center velocity to local orthonormal basis? 
      vector_physical_to_coordinate(ux,vy,x2_b[j]+dx2/2,&U[i][j],&temp); 
      
#ifdef HORIZONTAL
      //EXACT SOLUTION FOR EDGE VELOCITY FOR HORIZONTAL FLOW
      //      printf("U_before = %lf\n",U[i][j]);
      U[i][j] = (sin(x2_b[j]+dx2) - sin(x2_b[j]))/(dx2); 
      //      printf("U_after = %lf\n",U[i][j]);
#endif

      //phi face j-1/2
      velocity_physical(X_physical(x1_b[i]+dx1/2,x2_b[j]),Y_physical(x1_b[i]+dx1/2,x2_b[j]),&ux,&vy);
      vector_physical_to_coordinate(ux,vy,x2_b[j],&temp,&V[i][j]); 
#if defined(SEMI_CLOCK) || defined(GAUSS_CLOCK)
      velocity_coordinate(x1_b[i],x2_b[j],&U[i][j],&V[i][j]);
#endif
      //      printf("U,V = %lf,%lf\n",U[i][j],V[i][j]);
    }
  } 

  /* check normalization of velocities  */
  /* these are naturally not normalized because the cell has finite volume so the edge velocities arent the velocity of the same point */
  double norm; 
  double max_deviation =0.0; 
  for(i=is; i<=ie; i++){
    for(j=js; j<=je; j++){ 
      norm = sqrt(U[i][j]*U[i][j] + V[i][j]*V[i][j]); 
      if (fabs(norm-1.0) > max_deviation)
	max_deviation = fabs(norm-1.0); 
      //  printf("%0.12lf\n",norm);
    }
  }
  //  printf("maximum deviation from 1.0 = %0.12lf\n",max_deviation); 



  /*Option #3: specify velocity in polar coordinates */


  /*Check CFL condition, reset timestep */
  float **cfl_array;
  float *dataCFL;
  cfl_array = (float **) malloc(sizeof(float *)*nx1);
  dataCFL = (float *) malloc(sizeof(float)*nx1*nx2);
  for(i=0; i<nx1; i++){
    cfl_array[i] = &(dataCFL[nx2*i]);
  }
  for(i=1; i<nx1; i++){
    for(j=1; j<nx2; j++){ //based on edge velocities or cell centered u,v?
      if (i >=is && i< ie && j >=js && j <je)
	cfl_array[i][j] = fabs(U[i][j])*dt/dx1 + fabs(V[i][j])*dt/(x1_b[i]*dx2); //use boundary radius
      else
	cfl_array[i][j] =0.0; 
    }
  }
  //find maximum CFL value in domain
  float  max_cfl = find_max(dataCFL,nx1*nx2); 
  printf("Largest CFL number = %lf\n",max_cfl); 
  if (max_cfl > CFL || AUTO_TIMESTEP){//reset timestep if needed
    dt = CFL*dt/max_cfl; 
    for(i=1; i<nx1; i++){
      for(j=1; j<nx2; j++){ 
	if (i >=is && i< ie && j >=js && j <je)
	  cfl_array[i][j] = fabs(U[i][j])*dt/dx1 + fabs(V[i][j])*dt/(x1_b[i]*dx2);
	else
	  cfl_array[i][j] =0.0; 
      }
    } 
  }
  max_cfl = find_max(dataCFL,nx1*nx2); 
  printf("Largest CFL number = %lf\n",max_cfl); 
  
#ifdef SEMI_CLOCK
  nsteps = M_PI/dt;
  printf("nsteps = %d, dt = %lf, t_final = %lf\n",nsteps,dt,nsteps*dt);
#endif
  
#ifdef GAUSS_CLOCK
  nsteps = 2*M_PI/dt;
  //turn dt down until mod(2*MPI,nsteps) = 0
  double remainder = 2*M_PI -nsteps*dt;
  double extra = remainder/nsteps; 
  double dt_new = dt +extra; 
  printf("nsteps = %d, dt = %lf, dt_new =%lf, remainder = %lf, t_final = %lf t_final_new =%lf\n",nsteps,dt,dt_new,remainder,nsteps*dt,nsteps*dt_new);
  max_cfl *= dt_new/dt; 
  dt = dt_new; 
  printf("Largest CFL number = %lf\n",max_cfl); 
#endif

  /*Conserved variable on the computational coordinate mesh*/
  double **Q;
  double *dataQ;
  //make contiguous multiarray                                                                                                
  Q = (double **) malloc(sizeof(double *)*nx1);
  dataQ = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    Q[i] = &(dataQ[nx2*i]);
  }
  /*Initial condition */
  //specified as a function of cartesian physical cooridnates, as is the stream function
  for(i=is; i<ie; i++){
    for(j=js; j<je; j++){
      Q[i][j] = initial_condition(x[i][j],y[i][j]); 
    }
  }

  //net fluctuations/fluxes
  double U_plus,U_minus,V_plus,V_minus;
  double **net_fluctuation;
  double *dataFlux;
  net_fluctuation = (double **) malloc(sizeof(double *)*nx1);
  dataFlux = (double *) malloc(sizeof(double)*nx1*nx2);
  for(i=0; i<nx1; i++){
    net_fluctuation[i] = &(dataFlux[nx2*i]);
  }

  /* Using Visit VTK writer */
  char filename[20];
  int dims[] = {nx1_r+1, nx2_r+1, 1}; //dont output ghost cells. //nodal variables have extra edge point
  int nvars = 2;
  int vardims[] = {1, 3}; //Q is a scalar, velocity is a 3-vector 
  int centering[] = {0, 1}; // Q is cell centered, velocity is defined at edges
  const char *varnames[] = {"Q", "edge_velocity"};
  /* Curvilinear mesh points stored x0,y0,z0,x1,y1,z1,...*/
  //An array of size nI*nJ*nK*3 . These points are nodal, not zonal... unfortunatley
  float *pts = (float *) malloc(sizeof(float)*(nx1_r+1)*(nx2_r+1)*3); 
  //The array should be layed out as (pt(i=0,j=0,k=0), pt(i=1,j=0,k=0), ...
  //pt(i=nI-1,j=0,k=0), pt(i=0,j=1,k=0), ...).
  int index=0; 
  for(k=0; k<1; k++){
    for(j=js; j<=je; j++){
      for(i=is; i<=ie; i++){
	pts[index] = x_b[i][j];
	pts[++index] = y_b[i][j];
	pts[++index] = 0.0;
	index++;
      }
    }
  }

  /* pack U and V into a vector */
  float *edge_vel = (float *) malloc(sizeof(float)*(nx1_r+1)*(nx2_r+1)*3); //An array of size nI*nJ*nK*3 
  index=0; 
  for(k=0; k<1; k++){
    for(j=js; j<=je; j++){
      for(i=is; i<=ie; i++){
	vector_coordinate_to_physical(U[i][j],V[i][j], x2[j], &ux,&vy);
	//edge_vel[index] = U[i][j];
	//edge_vel[++index] = V[i][j]; 
	edge_vel[index] = ux;
	edge_vel[++index] = vy;
	edge_vel[++index] = 0.0;
	index++;
      }
    }
  } 

  //  vars       An array of variables.  The size of vars should be nvars.
  //                 The size of vars[i] should be npts*vardim[i].
  float *realQ; 
  realQ =(float *) malloc(sizeof(double)*nx1_r*nx2_r);
  float *vars[] = {(float *) realQ, (float *)edge_vel};

  /*-----------------------*/
  /* Main timestepping loop */
  /*-----------------------*/
  for (n=0; n<nsteps; n++){
    /*Boundary conditions */
    //bcs are specified along a computational coord direction, but are a function of the physical coordinate of adjacent "real cells"
    for(k=0;k<num_ghost; k++){
      for (j=js; j<je; j++){
	Q[k][j] = bc_x1i(x[is][j],y[is][j]);
	Q[nx1-1-k][j] = bc_x1f(x[ie-1][j],y[ie-1][j],(n+1)*dt);
      }
      for (i=is; i<ie; i++){
	if(X2_PERIODIC){
	  Q[i][k] = Q[i][je-1-k];
	  Q[i][nx2-1-k] = Q[i][js+k];
	}
	else{
	Q[i][k] = bc_x2i(x[i][js],y[i][js]);
	Q[i][nx2-1-k] = bc_x2f(x[i][je-1],y[i][je-1]);
	}
      }
    }

    double flux_limiter =0.0; 
    double *qmu = (double *) malloc(sizeof(double)*3); //manually copy array for computing slope limiters
    /* Donor cell upwinding */
    for (i=is; i<ie; i++){
      for (j=js; j<je; j++){
	/* First coordinate */
	U_plus = fmax(U[i][j],0.0); // max{U_{i-1/2,j},0.0} LHS boundary
	U_minus = fmin(U[i+1][j],0.0); // min{U_{i+1/2,j},0.0} RHS boundary
	/*Fluctuations: A^+ \Delta Q_{i-1/2,j} + A^- \Delta Q_{i+1/2,j} */
	//	net_fluctuation[i][j] = dt/(kappa[i][j]*dx1)*(U_plus*(Q[i][j] - Q[i-1][j]) + U_minus*(Q[i+1][j] - Q[i][j]));
	/* First order fluxes: F_i+1/2 - F_i-1/2 */
	net_fluctuation[i][j] = dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(fmax(U[i+1][j],0.0)*Q[i][j] + U_minus*Q[i+1][j])-x1_b[i]*(U_plus*Q[i-1][j] + fmin(U[i][j],0.0)*Q[i][j]));
#ifdef SECOND_ORDER
	/* Second order fluxes */
	if (U[i+1][j] > 0.0){ //middle element is always the upwind element
	  qmu[0] = Q[i-1][j];
	  qmu[1] = Q[i][j];  
	  qmu[2] = Q[i+1][j];  
	  flux_limiter= flux_PLM(dx1,qmu);
	}
	else{
	  qmu[0] = Q[i+2][j];
	  qmu[1] = Q[i+1][j];  
	  qmu[2] = Q[i][j];  
	  flux_limiter= flux_PLM(dx1,qmu);
	  /*	  if (flux_limiter != 0.0){
	    printf("i,j: %d,%d F_{i+1/2} flux limiter: %lf\n",i,j,flux_limiter);
	    printf("Q0 = %lf Q1= %lf Q2 = %lf\n",qmu[0],qmu[1],qmu[2]); } */
	}
	//F^H_{i+1/2,j}
	net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(1-dt*fabs(U[i+1][j])/(dx1))*fabs(U[i+1][j])*flux_limiter/2);
	//	net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*((kappa[i][j]/x1_b[i+1]-dt*fabs(U[i+1][j])/(x1_b[i+1]*dx1))*fabs(U[i+1][j])*flux_limiter/2);
	//	net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*(x1_b[i+1]*(kappa[i][j]/x1_b[i+1]-dt*fabs(U[i+1][j])/(x1_b[i+1]*dx1))*fabs(U[i+1][j])*flux_limiter/2);
	if (U[i][j] > 0.0){
	  qmu[0] = Q[i-2][j];  //points to the two preceeding bins; 
	  qmu[1] = Q[i-1][j];  
	  qmu[2] = Q[i][j];  
	  flux_limiter= flux_PLM(dx1,qmu);
	}
	else{
	  qmu[0] = Q[i+1][j]; //centered around current bin
	  qmu[1] = Q[i][j];  
	  qmu[2] = Q[i-1][j];  
	  flux_limiter= flux_PLM(dx1,qmu);
	}
	//F^H_{i-1/2,j}
	net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*(x1_b[i]*(1-dt*fabs(U[i][j])/(dx1))*fabs(U[i][j])*flux_limiter/2);
	//	net_fluctuation[i][j] += dt/(kappa[i][j]*dx1)*((kappa[i-1][j]/x1_b[i]-dt*fabs(U[i][j])/(x1_b[i]*dx1))*fabs(U[i][j])*flux_limiter/2);
	//net_fluctuation[i][j] -= dt/(kappa[i][j]*dx1)*(x1_b[i]*(kappa[i-1][j]/x1_b[i]-dt*fabs(U[i][j])/(x1_b[i]*dx1))*fabs(U[i][j])*flux_limiter/2);
#endif
	/* Second coordinate */
	V_plus = fmax(V[i][j],0.0); // max{V_{i,j-1/2},0.0} LHS boundary
	V_minus = fmin(V[i][j+1],0.0); // min{V_{i,j+1/2},0.0} RHS boundary
	/*Fluctuations: B^+ \Delta Q_{i,j-1/2} + B^- \Delta Q_{i,j+1/2} */
	//net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*(V_plus*(Q[i][j] - Q[i][j-1]) + V_minus*(Q[i][j+1] - Q[i][j]));	
	/* Fluxes: G_i,j+1/2 - G_i,j-1/2 */
	net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((fmax(V[i][j+1],0.0)*Q[i][j] + V_minus*Q[i][j+1])-(V_plus*Q[i][j-1] + fmin(V[i][j],0.0)*Q[i][j]));
#ifdef SECOND_ORDER
	/* Second order fluxes */
	if (V[i][j+1] > 0.0){
	  qmu[0] = Q[i][j-1];  //points to the two preceeding bins; 
	  qmu[1] = Q[i][j];  
	  qmu[2] = Q[i][j+1];  
	  flux_limiter= flux_PLM(dx2,qmu);
	}
	else{
	  qmu[0] = Q[i][j+2]; //centered around current bin
	  qmu[1] = Q[i][j+1];  
	  qmu[2] = Q[i][j];  
	  flux_limiter= flux_PLM(dx2,qmu);
	  /*	  if (flux_limiter != 0.0){
	    printf("i,j: %d,%d F_{i+1/2} flux limiter: %lf\n",i,j,flux_limiter);
	    printf("Q0 = %lf Q1= %lf Q2 = %lf\n",qmu[0],qmu[1],qmu[2]); } */
	}
	//G^H_{i,j+1/2}
	net_fluctuation[i][j] -= dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j+1])/(kappa[i][j]*dx2))*fabs(V[i][j+1])*flux_limiter/2);
	//net_fluctuation[i][j] -= dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j+1])/(dx2))*fabs(V[i][j+1])*flux_limiter/2);
	if (V[i][j] > 0.0){
	  qmu[0] = Q[i][j-2];  //points to the two preceeding bins; 
	  qmu[1] = Q[i][j-1];  
	  qmu[2] = Q[i][j];  
	  flux_limiter = flux_PLM(dx2,qmu);
	}
	else{
	  qmu[0] = Q[i][j+1]; //centered around current bin
	  qmu[1] = Q[i][j];  
	  qmu[2] = Q[i][j-1];  
	  flux_limiter= flux_PLM(dx2,qmu);
	}
	//G^H_{i,j-1/2}
	net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j])/(kappa[i][j]*dx2))*fabs(V[i][j])*flux_limiter/2);
	//net_fluctuation[i][j] += dt/(kappa[i][j]*dx2)*((1-dt*fabs(V[i][j])/(dx2))*fabs(V[i][j])*flux_limiter/2);
#endif
      }
    }

    /*Apply fluctuations */
    for (i=is; i<ie; i++)
      for (j=js; j<je; j++){
	Q[i][j] -= net_fluctuation[i][j];
      }
    
    /*Source terms */
    for (i=is; i<ie; i++)
      for (j=js; j<je; j++){
      }

    /*Output */
    //for now, explicitly copy subarray corresponding to real zonal info:
    index=0; 
    for (k=0; k<1; k++){
      for (j=js; j<je; j++){
	for (i=is; i<ie; i++){
	  //index =(j-num_ghost)*nx2_r + (i-num_ghost); 
	  realQ[index] = (float) Q[i][j];//*kappa[i][j]; //\bar{q}=qk density in computational space
	  index++;
	}
      }
    }
    //debug only horizontal flow
    /*    if (find_max(realQ,nx1_r*nx2_r) > 1.1){
      printf("Q greater than 1.0!\n"); 
      for (i=1;i<nx1; i++){
	for (j=1; j<nx2; j++){
	  if (Q[i][j] > 1.0){
	    printf("i=%d j=%d Q[i][j] = %0.10lf\n",i,j,Q[i][j]); 
	    return(0); 
	  }
	}
      }
      }*/

    sprintf(filename,"advect-%.3d.vtk",n); 
    if(!OUTPUT_INTERVAL){
      if (n==nsteps-1) //for only the final result
	write_curvilinear_mesh(filename,3,dims, pts, nvars,vardims, centering, varnames, vars);}
    else{
      if (!(n%OUTPUT_INTERVAL)) //HAVENT CHECKED THIS
	write_curvilinear_mesh(filename,3,dims, pts, nvars,vardims, centering, varnames, vars);}
      
      printf("step: %d time: %lf max{Q} = %0.7lf min{Q} = %0.7lf sum{Q} = %0.7lf \n",
	     n+1,(n+1)*dt,find_max(realQ,nx1_r*nx2_r),find_min(realQ,nx1_r*nx2_r),sum(realQ,nx1_r*nx2_r));
  }
  return(0); 
}