Beispiel #1
0
/*! \fn static void flux_output_func(MeshS *pM, OutputS *pOut) 
 *  \brief  New output format which outputs y-integrated angular momentum fluxes
 *  Currently can only be used with 1 proc and 1 domain.
 */
static void flux_output_func(MeshS *pM, OutputS *pOut)
{
  GridS *pG=pM->Domain[0][0].Grid;
  int nx1,nx2,nx3, ind, i,j,k, ind_i,ind_k;
  Real lx1, lx2, lx3;
  PrimS W[7],Ws[7],We[7];
  Real x1[7],x2[7],x3[7],xs1[7],xs2[7],xs3[7],xe1[7],xe2[7],xe3[7];
  Real dmin, dmax;
  Real **Fluxx=NULL;
  Real **FluxH=NULL;
  Real **FluxNu=NULL;
  Real **Th=NULL;
  Real **outCoordsx1=NULL;
  Real **outCoordsx3=NULL;
  Real **vx=NULL;
  Real **vy=NULL;
  Real **sigvx=NULL;
  Real **osigx=NULL;
  Real **davg=NULL;
  
  
  FILE *pfile;
  char *fname;
	
  nx1 = pG->Nx[0]; nx3 = pG->Nx[2]; nx2 = pG->Nx[1];
  lx1 = pG->MaxX[0] - pG->MinX[0];
  lx2 = pG->MaxX[1] - pG->MinX[1];
  lx3 = pG->MaxX[2] - pG->MinX[2];
 printf("%d, %d, %d, %g, %g, %g\n",nx1,nx2,nx3,lx1,lx2,lx3);
#ifdef MPI_PARALLEL  
  printf("%d, %d, %d, %g, %g, %g \n", myID_Comm_world,nx1,nx3,lx1,lx2,lx3); 

  printf("IND %d: (%d,%d), (%d,%d)\n",myID_Comm_world,pG->is,pG->js,pG->ie,pG->je);

#endif

  Fluxx=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (Fluxx == NULL) return;
  FluxH=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (FluxH == NULL) return;
  FluxNu=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (FluxNu == NULL) return;
  Th=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (Th == NULL) return;
  outCoordsx1=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (outCoordsx1 == NULL) return;
  outCoordsx3=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (outCoordsx3 == NULL) return;
  vx=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (vx == NULL) return;
  vy=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (vy == NULL) return;
  sigvx=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (sigvx == NULL) return;
  osigx=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (osigx == NULL) return;
  davg=(Real **)calloc_2d_array(nx3,nx1,sizeof(Real));
  if (davg == NULL) return;
/* Open file and write header */  
  
  if((fname = ath_fname(NULL,pM->outfilename,NULL,NULL,num_digit,
            pOut->num,pOut->id,"tab")) == NULL){
          ath_error("[dump_tab]: Error constructing filename\n");
  }
  if((pfile = fopen(fname,"w")) == NULL){
  	ath_error("[dump_tab]: Unable to open ppm file %s\n",fname);
  }
  free(fname);
  
#ifdef MPI_PARALLEL
  if(myID_Comm_world == 0) 
#endif
  	fprintf(pfile,"#t=%12.8e	x,FH,Fx,Fnu,Th,vx,vy,davg,sigvx,omsigx \n", pOut->t);

/* Compute y-integrated fluxes explicitly.
 * For the derivatives use a central difference method.
 * For the integration use a composite trapezoid method.
 * Both of these make use of the ghost cells for the boundary values.
 * 1	FluxH = < d * vx1 *vx2 >
 * 2	Fluxx = < 0.5 * omega * d * x1 * vx1 >
 * 3	FluxNu = - < nu_iso * d/dx vx2 >
 * 4	Th = - < d * d/dy phi >
 * 5	vx = < vx1 >
 * 6	vy = < vx2 >
 * 7	davg = < d >
 * 8	sigvx = < d * vx1 >
 * 9	osigx = < 0.5 * sig * omega * x1 >
 *
 *         
 *		x	4   x
 *      1   0	2
 *		x	3	x
 *
 * The variables are stored up as arrays of primitives W[7].
 * W = ( W[k][j][i], W[k][j][i-1], W[k][j][i+1], W[k][j-1][i], 
 *		 W[k][j+1][i], W[k-1][j][i], W[k+1][j][i] )
 * This is needed for the integration and differentiation.
 *
 * The background shear is taken out of vy when doing computations.
*/

  for(k=pG->ks; k <=pG->ke; k++) {
  	for(i=pG->is; i<= pG->ie; i++) {
		ind_i=i-pG->is; ind_k=k-pG->ks; 
		for(ind=0; ind < 7; ind++) {
			if (ind==0) {
				cc_pos(pG,i,pG->js,k,&xs1[ind],&xs2[ind],&xs3[ind]);
				cc_pos(pG,i,pG->je,k,&xe1[ind],&xe2[ind],&xe3[ind]);
				Ws[ind] = Cons_to_Prim(&(pG->U[k][pG->js][i])); 
				We[ind] = Cons_to_Prim(&(pG->U[k][pG->je][i])); 
			}
			if (ind > 0 && ind < 3) {
				cc_pos(pG,i+2*ind-3,pG->js,k,&xs1[ind],&xs2[ind],&xs3[ind]);
				cc_pos(pG,i+2*ind-3,pG->je,k,&xe1[ind],&xe2[ind],&xe3[ind]);
				Ws[ind] = Cons_to_Prim(&(pG->U[k][pG->js][i+2*ind-3])); 
				We[ind] = Cons_to_Prim(&(pG->U[k][pG->je][i+2*ind-3]));
			}
			if (ind > 2 && ind < 5) {
				cc_pos(pG,i,pG->js+2*ind-7,k,&xs1[ind],&xs2[ind],&xs3[ind]);
				cc_pos(pG,i,pG->je+2*ind-7,k,&xe1[ind],&xe2[ind],&xe3[ind]);
				Ws[ind] = Cons_to_Prim(&(pG->U[k][pG->js+2*ind-7][i])); 
				We[ind] = Cons_to_Prim(&(pG->U[k][pG->je+2*ind-7][i]));
			}
			if (ind > 4 && ind < 7) {
				if (pG->MinX[2] == pG->MaxX[2]) {
					cc_pos(pG,i,pG->js,k,&xs1[ind],&xs2[ind],&xs3[ind]);
					cc_pos(pG,i,pG->je,k,&xe1[ind],&xe2[ind],&xe3[ind]);
					Ws[ind] = Cons_to_Prim(&(pG->U[k][pG->js][i])); 
					We[ind] = Cons_to_Prim(&(pG->U[k][pG->je][i]));
				}
				else {
					cc_pos(pG,i,pG->js,k+2*ind-11,&xs1[ind],&xs2[ind],&xs3[ind]);
					cc_pos(pG,i,pG->je,k+2*ind-11,&xe1[ind],&xe2[ind],&xe3[ind]);
					Ws[ind] = Cons_to_Prim(&(pG->U[k+2*ind-11][pG->js][i])); 
					We[ind] = Cons_to_Prim(&(pG->U[k+2*ind-11][pG->je][i]));
				}
			}
			Ws[ind].V2 = Ws[ind].V2 + qshear*Omega_0*xs1[ind];
			We[ind].V2 = We[ind].V2 + qshear*Omega_0*xe1[ind];
/* If using d' instead of d then put in
 * W[ind] = W[ind]->d - d0;
 */
		}
/* Set initial values for the integration */
		FluxH[ind_k][ind_i] = 0.5*( Ws[0].d * Ws[0].V1 * Ws[0].V2 + 
						    We[0].d * We[0].V1 * We[0].V2 );  	
		
		Fluxx[ind_k][ind_i] = 0.5*( Ws[0].d * Ws[0].V1 * xs1[0] +
							We[0].d * We[0].V1 * xe1[0] );
		
#ifdef VISCOSITY 
		FluxNu[ind_k][ind_i] = 0.5*( Ws[2].V2 - Ws[1].V2 +
							 We[2].V2 - We[1].V2 ); 
		
#else
		FluxNu[ind_k][ind_i] = 0;
#endif   	
  	
  		Th[ind_k][ind_i] = 0.5*( Ws[0].d * dx2PlanetPot(xs1[0],xs2[0],xs3[0]) +
  						 We[0].d * dx2PlanetPot(xe1[0],xe2[0],xe3[0]) );
		
		vx[ind_k][ind_i] = 0.5*( Ws[0].V1 + We[0].V1 );
		vy[ind_k][ind_i] = 0.5*( Ws[0].V2 + We[0].V2 );
		sigvx[ind_k][ind_i] = 0.5*( Ws[0].d * Ws[0].V1 + We[0].d * We[0].V1 );
		osigx[ind_k][ind_i] = 0.5*( Ws[0].d * xs1[0] + We[0].d * xe1[0] );
		davg[ind_k][ind_i] = 0.5*(Ws[0].d + We[0].d);
  	 	for(j=(pG->js)+1; j < pG->je; j++) {
  			for(ind=0; ind < 7; ind++) {
				if (ind==0) {
					cc_pos(pG,i,j,k,&x1[ind],&x2[ind],&x3[ind]);
					W[ind] = Cons_to_Prim(&(pG->U[k][j][i])); 
				}
				if (ind > 0 && ind < 3) {
					cc_pos(pG,i+2*ind-3,j,k,&x1[ind],&x2[ind],&x3[ind]);
					W[ind] = Cons_to_Prim(&(pG->U[k][j][i+2*ind-3])); 
				}
				if (ind > 2 && ind < 5) {
					cc_pos(pG,i,j+2*ind-7,k,&x1[ind],&x2[ind],&x3[ind]);
					W[ind] = Cons_to_Prim(&(pG->U[k][j+2*ind-7][i])); 
				}
				if (ind > 4 && ind < 7) {
					if (pG->MinX[2] == pG->MaxX[2]) {
						cc_pos(pG,i,j,k,&x1[ind],&x2[ind],&x3[ind]);
						W[ind] = Cons_to_Prim(&(pG->U[k][j][i])); 
					}
					else {
						cc_pos(pG,i,j,k+2*ind-11,&x1[ind],&x2[ind],&x3[ind]);
						W[ind] = Cons_to_Prim(&(pG->U[k+2*ind-11][j][i])); 
					}
				}
				W[ind].V2 = W[ind].V2 + qshear*Omega_0*x1[ind];
				
			}	 
			
			FluxH[ind_k][ind_i] += W[0].d * W[0].V1 * W[0].V2;
			Fluxx[ind_k][ind_i] += W[0].d * W[0].V1 * x1[0];
#ifdef VISCOSITY
			FluxNu[ind_k][ind_i] += W[0].d * (W[2].V2 - W[1].V1);
#endif
			Th[ind_k][ind_i] += W[0].d * dx2PlanetPot(x1[0],x2[0],x3[0]);
			vx[ind_k][ind_i] += W[0].V1;
			vy[ind_k][ind_i] += W[0].V2;
			sigvx[ind_k][ind_i] += W[0].d * W[0].V1;
			osigx[ind_k][ind_i] += W[0].d * x1[0];
			davg[ind_k][ind_i] += W[0].d;
			
  		}	
  		FluxH[ind_k][ind_i] *= (pG->dx2)/lx2;
  		Fluxx[ind_k][ind_i] *= .5*Omega_0*(pG->dx2)/lx2;
#ifdef	VISCOSITY
		FluxNu[ind_k][ind_i] *= -nu_iso*(pG->dx2)/(2*lx2*(pG->dx1));
#endif 
  		Th[ind_k][ind_i] *= -1.0*(pG->dx2)/lx2;				
  		vx[ind_k][ind_i] *= (pG->dx2)/lx2;
  		vy[ind_k][ind_i] *= (pG->dx2)/lx2;
  		sigvx[ind_k][ind_i] *= (pG->dx2)/lx2;
  		osigx[ind_k][ind_i] *= (0.5*Omega_0*(pG->dx2))/lx2;
  		davg[ind_k][ind_i] *= (pG->dx2)/lx2;
  	 	outCoordsx1[ind_k][ind_i]=x1[0]; outCoordsx3[ind_k][ind_i]=x3[0];
  	}
  }  

/* Quantities are ready to be written to output file
 * Format (Not outputting x3 at the moment: 
 * x1	(x3)	FluxH	Fluxx	Fluxnu	Th	vx	vy	davg	sigvx	osigx
*/
  
  
  for(k=pG->ks; k<=pG->ke; k++) {
  	for(i=pG->is; i<=pG->ie; i++) {
 		ind_k=k-pG->ks; ind_i=i-pG->is;
  		if (lx3==0) {
  			fprintf(pfile,"%12.8e %12.8e %12.8e %12.8e %12.8e %12.8e %12.8e %12.8e %12.8e %12.8e\n",
  					outCoordsx1[ind_k][ind_i],FluxH[ind_k][ind_i],
  					Fluxx[ind_k][ind_i],FluxNu[ind_k][ind_i],Th[ind_k][ind_i],
  					vx[ind_k][ind_i],vy[ind_k][ind_i],davg[ind_k][ind_i],sigvx[ind_k][ind_i],
  					osigx[ind_k][ind_i]);
  		}
  		else {
  			fprintf(pfile,"%12.8e	%12.8e	%12.8e	%12.8e	%12.8e	%12.8e %12.8e %12.8e %12.8e %12.8e %12.8e\n",
  					outCoordsx1[ind_k][ind_i],outCoordsx3[ind_k][ind_i],FluxH[ind_k][ind_i],
  					Fluxx[ind_k][ind_i],FluxNu[ind_k][ind_i],Th[ind_k][ind_i],
  					vx[ind_k][ind_i],vy[ind_k][ind_i],davg[ind_k][ind_i],sigvx[ind_k][ind_i],
  					osigx[ind_k][ind_i]);
  		}
  	}
  }
  
  fclose(pfile);
  free_2d_array(Fluxx); 
  free_2d_array(FluxH); 
  free_2d_array(FluxNu); 
  free_2d_array(Th); 
  free_2d_array(outCoordsx1);
  free_2d_array(outCoordsx3);
  free_2d_array(vx);
  free_2d_array(vy);
  free_2d_array(sigvx);
  free_2d_array(osigx);
  free_2d_array(davg);
  return;
}
void dump_history(MeshS *pM, OutputS *pOut)
{
  GridS *pG;
  DomainS *pD;
  int i,j,k,is,ie,js,je,ks,ke,nl,nd;
  double dVol, scal[NSCAL + NSCALARS + MAX_USR_H_COUNT], d1;
  FILE *pfile;
  char *fname,*plev=NULL,*pdom=NULL,*pdir=NULL,fmt[80];
  char levstr[8],domstr[8],dirstr[20];
  int n, total_hst_cnt, mhst, myID_Comm_Domain=1;
#ifdef MPI_PARALLEL
  double my_scal[NSCAL + NSCALARS + MAX_USR_H_COUNT]; /* My Volume averages */
  int ierr;
#endif
#ifdef CYLINDRICAL
  Real x1,x2,x3;
#endif
#ifdef SPECIAL_RELATIVITY
  PrimS W;
  Real g, g2, g_2;
  Real bx, by, bz, vB, b2, Bmag2;
#endif


  total_hst_cnt = 9 + NSCALARS + usr_hst_cnt;
#ifdef ADIABATIC
  total_hst_cnt++;
#endif
#ifdef MHD
  total_hst_cnt += 3;
#endif
#ifdef SELF_GRAVITY
  total_hst_cnt += 1;
#endif
#ifdef CYLINDRICAL
  total_hst_cnt++;  /* for angular momentum */
#endif
#ifdef SPECIAL_RELATIVITY
  total_hst_cnt = 12 + usr_hst_cnt;
#ifdef MHD
   total_hst_cnt += 6;
#endif
#endif

/* Add a white space to the format */
  if(pOut->dat_fmt == NULL){
    sprintf(fmt," %%14.6e"); /* Use a default format */
  }
  else{
    sprintf(fmt," %s",pOut->dat_fmt);
  }

/* store time and dt in first two elements of output vector */

  scal[0] = pM->time;
  scal[1] = pM->dt;

/* Loop over all Domains in Mesh, and output Grid data */

  for (nl=0; nl<(pM->NLevels); nl++){

    for (nd=0; nd<(pM->DomainsPerLevel[nl]); nd++){

      if (pM->Domain[nl][nd].Grid != NULL){
        //printf("calculating local sum ... %d\n",myID_Comm_world);
        pG = pM->Domain[nl][nd].Grid;
        pD = (DomainS*)&(pM->Domain[nl][nd]);
        is = pG->is, ie = pG->ie;
        js = pG->js, je = pG->je;
        ks = pG->ks, ke = pG->ke;

        for (i=2; i<total_hst_cnt; i++) {
          scal[i] = 0.0;
        }
 
/* Compute history variables */

        for (k=ks; k<=ke; k++) {
          for (j=js; j<=je; j++) {
            for (i=is; i<=ie; i++) {
              dVol = 1.0; 
              if (pG->dx1 > 0.0) dVol *= pG->dx1;
              if (pG->dx2 > 0.0) dVol *= pG->dx2;
              if (pG->dx3 > 0.0) dVol *= pG->dx3;
#ifndef SPECIAL_RELATIVITY
#ifdef CYLINDRICAL
              cc_pos(pG,i,j,k,&x1,&x2,&x3);
              dVol *= x1;
#endif

              mhst = 2;
              scal[mhst] += dVol*pG->U[k][j][i].d;
              d1 = 1.0/pG->U[k][j][i].d;
#ifndef BAROTROPIC
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].E;
#endif
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M1;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M2;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M3;
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].M1)*d1;
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].M2)*d1;
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].M3)*d1;
#ifdef MHD
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].B1c);
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].B2c);
              mhst++;
              scal[mhst] += dVol*0.5*SQR(pG->U[k][j][i].B3c);
#endif
#ifdef SELF_GRAVITY
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].d*pG->Phi[k][j][i];
#endif
#if (NSCALARS > 0)
              for(n=0; n<NSCALARS; n++){
                mhst++;
                scal[mhst] += dVol*pG->U[k][j][i].s[n];
              }
#endif

#ifdef CYLINDRICAL
              mhst++;
              scal[mhst] += dVol*(x1*pG->U[k][j][i].M2);
#endif

#else /* SPECIAL_RELATIVITY */

              W = Cons_to_Prim (&(pG->U[k][j][i]));
        
              /* calculate gamma */
              g   = pG->U[k][j][i].d/W.d;
              g2  = SQR(g);
              g_2 = 1.0/g2;

              mhst = 2;
              scal[mhst] += dVol*pG->U[k][j][i].d;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].E;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M1;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M2;
              mhst++;
              scal[mhst] += dVol*pG->U[k][j][i].M3;

              mhst++;
              scal[mhst] += dVol*SQR(g);
              mhst++;
              scal[mhst] += dVol*SQR(g*W.V1);
              mhst++;
              scal[mhst] += dVol*SQR(g*W.V2);
              mhst++;
              scal[mhst] += dVol*SQR(g*W.V3);

	      mhst++;
	      scal[mhst] += dVol*W.P;

#ifdef MHD

              vB = W.V1*pG->U[k][j][i].B1c + W.V2*W.B2c + W.V3*W.B3c;
              Bmag2 = SQR(pG->U[k][j][i].B1c) + SQR(W.B2c) + SQR(W.B3c);
        
              bx = g*(pG->U[k][j][i].B1c*g_2 + vB*W.V1);
              by = g*(W.B2c*g_2 + vB*W.V2);
              bz = g*(W.B3c*g_2 + vB*W.V3);
        
              b2 = Bmag2*g_2 + vB*vB;

              mhst++;
              scal[mhst] += dVol*(g*vB*g*vB);
              mhst++;
              scal[mhst] += dVol*bx*bx;
              mhst++;
              scal[mhst] += dVol*by*by;
              mhst++;
              scal[mhst] += dVol*bz*bz;
              mhst++;
              scal[mhst] += dVol*b2;
              mhst++;
              scal[mhst] += dVol*(Bmag2*(1.0 - 0.5*g_2) - SQR(vB) / 2.0);

#endif /* MHD */

#endif  /* SPECIAL_RELATIVITY */

/* Calculate the user defined history variables */
              for(n=0; n<usr_hst_cnt; n++){
                mhst++;
                scal[mhst] += dVol*(*phst_fun[n])(pG, i, j, k);
              }
            }
          }
        }

/* Compute the sum over all Grids in Domain */
        //printf("calculating global sum ... %d\n",myID_Comm_world);

#ifdef MPI_PARALLEL 
        for(i=2; i<total_hst_cnt; i++){
          my_scal[i] = scal[i];
        }
        ierr = MPI_Reduce(&(my_scal[2]), &(scal[2]), (total_hst_cnt - 2),
          MPI_DOUBLE, MPI_SUM, 0, pD->Comm_Domain);
#endif

/* Only the parent (rank=0) process computes the average and writes output.
 * For single-processor jobs, myID_Comm_world is always zero. */

#ifdef MPI_PARALLEL
        ierr = MPI_Comm_rank(pD->Comm_Domain, &myID_Comm_Domain);
#endif
        if((myID_Comm_Domain==0) || (myID_Comm_world==0)){  /* I'm the parent */

/* Compute volume averages */
//          printf("dump history ... %d\n",myID_Comm_world);

          dVol = pD->MaxX[0] - pD->MinX[0];
#ifdef CYLINDRICAL
          dVol = 0.5*(SQR(pD->MaxX[0]) - SQR(pD->MinX[0]));
#endif
          if (pD->Nx[1] > 1) dVol *= (pD->MaxX[1] - pD->MinX[1]);
          if (pD->Nx[2] > 1) dVol *= (pD->MaxX[2] - pD->MinX[2]);
          for(i=2; i<total_hst_cnt; i++){
            scal[i] /= dVol;
          }

/* Create filename and open file.  History files are always written in lev#
 * directories of root process (rank=0 in MPI_COMM_WORLD) */
#ifdef MPI_PARALLEL
          if (nl>0) {
            plev = &levstr[0];
            sprintf(plev,"lev%d",nl);
            pdir = &dirstr[0];
            sprintf(pdir,"../id0/lev%d",nl);
          }
#else
          if (nl>0) {
            plev = &levstr[0];
            sprintf(plev,"lev%d",nl);
            pdir = &dirstr[0];
            sprintf(pdir,"lev%d",nl);
          }
#endif

          if (nd>0) {
            pdom = &domstr[0];
            sprintf(pdom,"dom%d",nd);
          }

          fname = ath_fname(pdir,pM->outfilename,plev,pdom,0,0,NULL,"hst");
          if(fname == NULL){
            ath_perr(-1,"[dump_history]: Unable to create history filename\n");
          }
          if(pOut->num == 0) pfile = fopen(fname,"w"); 
          else pfile = fopen(fname,"a");
          if(pfile == NULL){
            ath_perr(-1,"[dump_history]: Unable to open the history file\n");
          }
          free(fname);

/* Write out column headers, but only for first dump */

          mhst = 0;
          if(pOut->num == 0){
            fprintf(pfile,
         "# Athena history dump for level=%i domain=%i volume=%e\n",nl,nd,dVol);
            mhst++;
            fprintf(pfile,"#   [%i]=time   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=dt      ",mhst);
#ifndef SPECIAL_RELATIVITY
            mhst++;
            fprintf(pfile,"   [%i]=mass    ",mhst);
#ifdef ADIABATIC
            mhst++;
            fprintf(pfile,"   [%i]=total E ",mhst);
#endif
            mhst++;
            fprintf(pfile,"   [%i]=x1 Mom. ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2 Mom. ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3 Mom. ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x1-KE   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2-KE   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3-KE   ",mhst);
#ifdef MHD
            mhst++;
            fprintf(pfile,"   [%i]=x1-ME   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2-ME   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3-ME   ",mhst);
#endif
#ifdef SELF_GRAVITY
            mhst++;
            fprintf(pfile,"   [%i]=grav PE ",mhst);
#endif
#if (NSCALARS > 0)
            for(n=0; n<NSCALARS; n++){
              mhst++;
              fprintf(pfile,"  [%i]=scalar %i",mhst,n);
            }
#endif

#ifdef CYLINDRICAL
            mhst++;
            fprintf(pfile,"   [%i]=Ang.Mom.",mhst);
#endif

#else /* SPECIAL_RELATIVITY */
            mhst++;
            fprintf(pfile,"   [%i]=mass    ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=total E ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x1 Mom. ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2 Mom. ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3 Mom." ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=Gamma   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x1-KE   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2-KE   ",mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3-KE  " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=Press  " ,mhst);
#ifdef MHD
            mhst++;
            fprintf(pfile,"   [%i]=x0-ME  " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x1-ME  " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x2-ME  " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=x3-ME  " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=bsq    " ,mhst);
            mhst++;
            fprintf(pfile,"   [%i]=T^00_EM" ,mhst);
#endif
#endif /* SPECIAL_RELATIVITY */

            for(n=0; n<usr_hst_cnt; n++){
              mhst++;
              fprintf(pfile,"  [%i]=%s",mhst,usr_label[n]);
            }
            fprintf(pfile,"\n#\n");
          }

/* Write out data, and close file */

          for (i=0; i<total_hst_cnt; i++) {
           //printf("dump history data %d ... %d\n",i,myID_Comm_world);
            fprintf(pfile,fmt,scal[i]);
          }
          fprintf(pfile,"\n");
          fclose(pfile);
  
        }
      }
    }
  }

  return;
}
Beispiel #3
0
void dump_tab_prim(MeshS *pM, OutputS *pOut)
{
  GridS *pG;
  int nl,nd,i,j,k,il,iu,jl,ju,kl,ku;
  FILE *pfile;
  char *fname,*plev=NULL,*pdom=NULL;
  char levstr[8],domstr[8];
  PrimS W;
  Real x1,x2,x3;
  char zone_fmt[20], fmt[80];
  int col_cnt, nmax;
#ifdef PARTICLES
  Real d1;
#endif
#if (NSCALARS > 0)
  int n;
#endif

/* Add a white space to the format, setup format for integer zone columns */
  if(pOut->dat_fmt == NULL){
    sprintf(fmt," %%12.8e"); /* Use a default format */
  }
  else{
    sprintf(fmt," %s",pOut->dat_fmt);
  }

/* Loop over all Domains in Mesh, and output Grid data */

  for (nl=0; nl<(pM->NLevels); nl++){
    for (nd=0; nd<(pM->DomainsPerLevel[nl]); nd++){
      if (pM->Domain[nl][nd].Grid != NULL){

/* write files if domain and level match input, or are not specified (-1) */
      if ((pOut->nlevel == -1 || pOut->nlevel == nl) &&
          (pOut->ndomain == -1 || pOut->ndomain == nd)){
        pG = pM->Domain[nl][nd].Grid;
        col_cnt = 1;

/* construct output filename. */
        if (nl>0) {
          plev = &levstr[0];
          sprintf(plev,"lev%d",nl);
        }
        if (nd>0) {
          pdom = &domstr[0];
          sprintf(pdom,"dom%d",nd);
        }

        if((fname = ath_fname(plev,pM->outfilename,plev,pdom,num_digit,
            pOut->num,NULL,"tab")) == NULL){
          ath_error("[dump_tab]: Error constructing filename\n");
        }

/* open output file */
        if((pfile = fopen(fname,"w")) == NULL){
          ath_error("[dump_tab]: Unable to open ppm file %s\n",fname);
        }
        free(fname);

/* Upper and Lower bounds on i,j,k for data dump */

        il = pG->is; iu = pG->ie;
        jl = pG->js; ju = pG->je;
        kl = pG->ks; ku = pG->ke;

        nmax =  pG->Nx[0] > pG->Nx[1]  ? pG->Nx[0] : pG->Nx[1];
        nmax = (pG->Nx[2] > nmax ? pG->Nx[2] : nmax);

#ifdef WRITE_GHOST_CELLS
        iu = pG->ie + nghost;
        il = pG->is - nghost;

        if(pG->Nx[1] > 1) {
          ju = pG->je + nghost;
          jl = pG->js - nghost;
        }

        if(pG->Nx[2] > 1) {
          ku = pG->ke + nghost;
          kl = pG->ks - nghost;
        }
        nmax += 2*nghost;
#endif
        sprintf(zone_fmt,"%%%dd", (int)(2+log10((double)(nmax))));

/* Write out some header information */

        if (pG->Nx[0] > 1) {
          fprintf(pfile,"# Nx1 = %d\n",iu-il+1);
          fprintf(pfile,"# x1-size = %g\n",(iu-il+1)*pG->dx1);
        }
        if (pG->Nx[1] > 1) {
          fprintf(pfile,"# Nx2 = %d\n",ju-jl+1);
          fprintf(pfile,"# x2-size = %g\n",(ju-jl+1)*pG->dx2);
        }
        if (pG->Nx[2] > 1) {
          fprintf(pfile,"# Nx3 = %d\n",ku-kl+1);
          fprintf(pfile,"# x3-size = %g\n",(ku-kl+1)*pG->dx3);
        }
        fprintf(pfile,"# PRIMITIVE vars at Time = %g, level= %i, domain= %i\n",
          pM->time,nl,nd);

/* write out i,j,k column headers.  Note column number is embedded in header */

        fprintf(pfile,"# [%d]=i-zone",col_cnt);
        col_cnt++;
        if (pG->Nx[1] > 2) {
          fprintf(pfile," [%d]=j-zone",col_cnt);
          col_cnt++;
        }
        if (pG->Nx[2] > 3) {
          fprintf(pfile," [%d]=k-zone",col_cnt);
          col_cnt++;
        }

/* write out x1,x2,x3 column headers.  */

        fprintf(pfile," [%d]=x1",col_cnt);
        col_cnt++;
        if (pG->Nx[1] > 2) {
          fprintf(pfile," [%d]=x2",col_cnt);
          col_cnt++;
        }
        if (pG->Nx[2] > 3) {
          fprintf(pfile," [%d]=x3",col_cnt);
          col_cnt++;
        }

/* write out d,V1,V2,V3 column headers */

        fprintf(pfile," [%d]=d",col_cnt);
        col_cnt++;
        fprintf(pfile," [%d]=V1",col_cnt);
        col_cnt++;
        fprintf(pfile," [%d]=V2",col_cnt);
        col_cnt++;
        fprintf(pfile," [%d]=V3",col_cnt);
        col_cnt++;

/* write out P column header, if not barotropic */
#ifndef BAROTROPIC
        fprintf(pfile," [%d]=P",col_cnt);
        col_cnt++;
#endif /* BAROTROPIC */

/* write out magnetic field component column headers, if mhd */
#ifdef MHD
        fprintf(pfile," [%d]=B1c",col_cnt);
        col_cnt++;
        fprintf(pfile," [%d]=B2c",col_cnt);
        col_cnt++;
        fprintf(pfile," [%d]=B3c",col_cnt);
        col_cnt++;
#endif /* MHD */

/* write out column header for gravitational potential (self-gravity) */
#ifdef SELF_GRAVITY
        fprintf(pfile," [%d]=Phi",col_cnt);
        col_cnt++;
#endif

/* write out column headers for particles */
#ifdef PARTICLES
        if (pOut->out_pargrid) {
          fprintf(pfile," [%d]=dpar",col_cnt);
          col_cnt++;
          fprintf(pfile," [%d]=V1par",col_cnt);
          col_cnt++;
          fprintf(pfile," [%d]=V2par",col_cnt);
          col_cnt++;
          fprintf(pfile," [%d]=V3par",col_cnt);
          col_cnt++;
        }
#endif

/* write out column headers for passive scalars */
#if (NSCALARS > 0)
        for (n=0; n<NSCALARS; n++) {
          fprintf(pfile," [%d]=s%d",col_cnt,n);
          col_cnt++;
        }
#endif
        fprintf(pfile,"\n");

/* Write out data */

        for(k=kl; k<=ku; k++){
          for(j=jl; j<=ju; j++){
            for(i=il; i<=iu; i++){
              cc_pos(pG,i,j,k,&x1,&x2,&x3);
              W = Cons_to_Prim(&(pG->U[k][j][i])); 

              if (pG->Nx[0] > 1) fprintf(pfile,zone_fmt,i);
              if (pG->Nx[1] > 1) fprintf(pfile,zone_fmt,j);
              if (pG->Nx[2] > 1) fprintf(pfile,zone_fmt,k);
              if (pG->Nx[0] > 1) fprintf(pfile,fmt,x1);
              if (pG->Nx[1] > 1) fprintf(pfile,fmt,x2);
              if (pG->Nx[2] > 1) fprintf(pfile,fmt,x3);

/* Dump all variables */

              fprintf(pfile,fmt,W.d);
              fprintf(pfile,fmt,W.V1);
              fprintf(pfile,fmt,W.V2);
              fprintf(pfile,fmt,W.V3);

#ifndef BAROTROPIC
              fprintf(pfile,fmt,W.P);
#endif /* BAROTROPIC */

#ifdef MHD
              fprintf(pfile,fmt,W.B1c);
              fprintf(pfile,fmt,W.B2c);
              fprintf(pfile,fmt,W.B3c);
#endif

#ifdef SELF_GRAVITY
              fprintf(pfile,fmt,pG->Phi[k][j][i]);
#endif

#ifdef PARTICLES
              if (pOut->out_pargrid) {
                fprintf(pfile,fmt,pG->Coup[k][j][i].grid_d);
                if (pG->Coup[k][j][i].grid_d>0.0)
                  d1 = 1.0/pG->Coup[k][j][i].grid_d;
                else
                  d1 = 0.0;
                fprintf(pfile,fmt,pG->Coup[k][j][i].grid_v1*d1);
                fprintf(pfile,fmt,pG->Coup[k][j][i].grid_v2*d1);
                fprintf(pfile,fmt,pG->Coup[k][j][i].grid_v3*d1);
              }
#endif

#if (NSCALARS > 0)
              for (n=0; n<NSCALARS; n++) fprintf(pfile,fmt,W.r[n]);
#endif
              fprintf(pfile,"\n");
            }
          }
        }
      }}
    } /* end loop over domains */
  } /* end loop over levels */

  fclose(pfile);

  return;
}
Beispiel #4
0
void dump_binary(MeshS *pM, OutputS *pOut)
{
  GridS *pGrid;
  PrimS ***W;
  FILE *p_binfile;
  char *fname,*plev=NULL,*pdom=NULL;
  char levstr[8],domstr[8];
  int n,ndata[7];
/* Upper and Lower bounds on i,j,k for data dump */
  int i,j,k,il,iu,jl,ju,kl,ku,nl,nd;
  Real dat[2],*datax,*datay,*dataz;
  Real *pData,x1,x2,x3;
  int coordsys = -1;

/* Loop over all Domains in Mesh, and output Grid data */

  for (nl=0; nl<(pM->NLevels); nl++){
    for (nd=0; nd<(pM->DomainsPerLevel[nl]); nd++){
      if (pM->Domain[nl][nd].Grid != NULL){

/* write files if domain and level match input, or are not specified (-1) */ 
      if ((pOut->nlevel == -1 || pOut->nlevel == nl) &&
          (pOut->ndomain == -1 || pOut->ndomain == nd)){
        pGrid = pM->Domain[nl][nd].Grid;

        il = pGrid->is, iu = pGrid->ie;
        jl = pGrid->js, ju = pGrid->je;
        kl = pGrid->ks, ku = pGrid->ke;

#ifdef WRITE_GHOST_CELLS
        il = pGrid->is - nghost;
        iu = pGrid->ie + nghost;

        if(pGrid->Nx[1] > 1){
          jl = pGrid->js - nghost;
          ju = pGrid->je + nghost;
        }

        if(pGrid->Nx[2] > 1){
          kl = pGrid->ks - nghost;
          ku = pGrid->ke + nghost;
        }
#endif /* WRITE_GHOST_CELLS */

        ndata[0] = iu-il+1;
        ndata[1] = ju-jl+1;
        ndata[2] = ku-kl+1;

/* calculate primitive variables, if needed */

        if(strcmp(pOut->out,"prim") == 0) {
          if((W = (PrimS***)
            calloc_3d_array(ndata[2],ndata[1],ndata[0],sizeof(PrimS))) == NULL)
            ath_error("[dump_bin]: failed to allocate Prim array\n");

          for (k=kl; k<=ku; k++) {
          for (j=jl; j<=ju; j++) {
          for (i=il; i<=iu; i++) {
            W[k-kl][j-jl][i-il] = Cons_to_Prim(&(pGrid->U[k][j][i]));
          }}}
        }

/* construct filename, open file */
        if (nl>0) {
          plev = &levstr[0];
          sprintf(plev,"lev%d",nl);
        }
        if (nd>0) {
          pdom = &domstr[0];
          sprintf(pdom,"dom%d",nd);
        }
        if((fname = ath_fname(plev,pM->outfilename,plev,pdom,num_digit,
            pOut->num,NULL,"bin")) == NULL){
          ath_error("[dump_binary]: Error constructing filename\n");
        }

        if((p_binfile = fopen(fname,"wb")) == NULL){
          ath_error("[dump_binary]: Unable to open binary dump file\n");
          return;
        }
        free(fname);

/* Write the coordinate system information */
#if defined CARTESIAN
        coordsys = -1;
#elif defined CYLINDRICAL
        coordsys = -2;
#elif defined SPHERICAL
        coordsys = -3;
#endif
        fwrite(&coordsys,sizeof(int),1,p_binfile);

/* Write number of zones and variables */
        ndata[3] = NVAR;
        ndata[4] = NSCALARS;
#ifdef SELF_GRAVITY
        ndata[5] = 1;
#else
        ndata[5] = 0;
#endif
#ifdef PARTICLES
        ndata[6] = 1;
#else
        ndata[6] = 0;
#endif
        fwrite(ndata,sizeof(int),7,p_binfile);

/* Write (gamma-1) and isothermal sound speed */

#ifdef ISOTHERMAL
        dat[0] = (Real)0.0;
        dat[1] = (Real)Iso_csound;
#elif defined ADIABATIC
        dat[0] = (Real)Gamma_1 ;
        dat[1] = (Real)0.0;
#else
        dat[0] = dat[1] = 0.0; /* Anything better to put here? */
#endif
        fwrite(dat,sizeof(Real),2,p_binfile);

/* Write time, dt */

        dat[0] = (Real)pGrid->time;
        dat[1] = (Real)pGrid->dt;
        fwrite(dat,sizeof(Real),2,p_binfile);
 
/* Allocate Memory */

        if((datax = (Real *)malloc(ndata[0]*sizeof(Real))) == NULL){
          ath_error("[dump_binary]: malloc failed for temporary array\n");
          return;
        }
        if((datay = (Real *)malloc(ndata[1]*sizeof(Real))) == NULL){
          ath_error("[dump_binary]: malloc failed for temporary array\n");
          return;
        }
        if((dataz = (Real *)malloc(ndata[2]*sizeof(Real))) == NULL){
          ath_error("[dump_binary]: malloc failed for temporary array\n");
          return;
        }

/* compute x,y,z coordinates of cell centers, and write out */

        for (i=il; i<=iu; i++) {
          cc_pos(pGrid,i,jl,kl,&x1,&x2,&x3);
          pData = ((Real *) &(x1));
          datax[i-il] = (Real)(*pData);
        }
        fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);

        for (j=jl; j<=ju; j++) {
          cc_pos(pGrid,il,j,kl,&x1,&x2,&x3);
          pData = ((Real *) &(x2));
          datay[j-jl] = (Real)(*pData);
        }
        fwrite(datay,sizeof(Real),(size_t)ndata[1],p_binfile);

        for (k=kl; k<=ku; k++) {
          cc_pos(pGrid,il,jl,k,&x1,&x2,&x3);
          pData = ((Real *) &(x3));
          dataz[k-kl] = (Real)(*pData);
        }
        fwrite(dataz,sizeof(Real),(size_t)ndata[2],p_binfile);

/* Write cell-centered data (either conserved or primitives) */

        for (n=0;n<NVAR; n++) {
          for (k=0; k<ndata[2]; k++) {
          for (j=0; j<ndata[1]; j++) {
            for (i=0; i<ndata[0]; i++) {

              if (strcmp(pOut->out,"cons") == 0){
                pData = ((Real*)&(pGrid->U[k+kl][j+jl][i+il])) + n;
              } else if(strcmp(pOut->out,"prim") == 0) {
                pData = ((Real*)&(W[k][j][i])) + n;
              }
              datax[i] = (Real)(*pData);

            }
            fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);

          }}
        }

#ifdef SELF_GRAVITY
        for (k=0; k<ndata[2]; k++) {
        for (j=0; j<ndata[1]; j++) {
          for (i=0; i<ndata[0]; i++) {
            pData = &(pGrid->Phi[k+kl][j+jl][i+il]);
            datax[i] = (Real)(*pData);
          }
          fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);
        }}
#endif

#ifdef PARTICLES
        if (pOut->out_pargrid) {
          for (k=0; k<ndata[2]; k++) {
          for (j=0; j<ndata[1]; j++) {
            for (i=0; i<ndata[0]; i++) {
              datax[i] = pGrid->Coup[k+kl][j+jl][i+il].grid_d;
            }
            fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);
          }}
          for (k=0; k<ndata[2]; k++) {
          for (j=0; j<ndata[1]; j++) {
            for (i=0; i<ndata[0]; i++) {
              datax[i] = pGrid->Coup[k+kl][j+jl][i+il].grid_v1;
            }
            fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);
          }}
          for (k=0; k<ndata[2]; k++) {
          for (j=0; j<ndata[1]; j++) {
            for (i=0; i<ndata[0]; i++) {
              datax[i] = pGrid->Coup[k+kl][j+jl][i+il].grid_v2;
            }
            fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);
          }}
          for (k=0; k<ndata[2]; k++) {
          for (j=0; j<ndata[1]; j++) {
            for (i=0; i<ndata[0]; i++) {
              datax[i] = pGrid->Coup[k+kl][j+jl][i+il].grid_v3;
            }
            fwrite(datax,sizeof(Real),(size_t)ndata[0],p_binfile);
          }}
        }
#endif

/* close file and free memory */
        fclose(p_binfile); 
        free(datax); 
        free(datay); 
        free(dataz); 
        if(strcmp(pOut->out,"prim") == 0) free_3d_array(W);
      }}
    }
  }
}
Beispiel #5
0
/*! \fn void integrate_1d_vl(DomainS *pD)
 *  \brief 1D version of van Leer unsplit integrator for MHD.
 *
 *   The numbering of steps follows the numbering in the 3D version.
 *   NOT ALL STEPS ARE NEEDED IN 1D.
 */
void integrate_1d_vl(DomainS *pD)
{
    GridS *pG=(pD->Grid);
    ConsS U;
    Real dtodx1=pG->dt/pG->dx1, hdtodx1=0.5*pG->dt/pG->dx1;
    int i, is = pG->is, ie = pG->ie;
    int js = pG->js;
    int ks = pG->ks;
    int cart_x1 = 1, cart_x2 = 2, cart_x3 = 3;
    Real x1,x2,x3,phicl,phicr,phifc,phil,phir,phic;
#if (NSCALARS > 0)
    int n;
#endif
#ifdef SELF_GRAVITY
    Real gxl,gxr,flx_m1l,flx_m1r;
#endif
#ifdef STATIC_MESH_REFINEMENT
    int ncg,npg,dim;
#endif
#ifdef FIRST_ORDER_FLUX_CORRECTION
    int flag_cell=0,negd=0,negP=0,superl=0,NaNFlux=0;
    int fail=0,final=0;
    Real Vsq,Bx;
    PrimS Wcheck;
    Int3Vect BadCell;
#endif


    int il=is-(nghost-1), iu=ie+(nghost-1);

    for (i=is-nghost; i<=ie+nghost; i++) {
        Uhalf[i] = pG->U[ks][js][i];
        W[i] = Cons_to_Prim(&(pG->U[ks][js][i]));
    }

    /*=== STEP 1: Compute first-order fluxes at t^{n} in x1-direction ============*/
    /* No source terms are needed since there is no temporal evolution */

    /*--- Step 1a ------------------------------------------------------------------
     * Load 1D vector of primitive variables;
     * W1d = (d, V1, V2, V3, P, B2c, B3c, s[n])
     */

    for (i=is-nghost; i<=ie+nghost; i++) {
        W1d[i].d  = W[i].d;
        W1d[i].Vx = W[i].V1;
        W1d[i].Vy = W[i].V2;
        W1d[i].Vz = W[i].V3;
        W1d[i].P  = W[i].P;
#ifdef MHD
        W1d[i].By = W[i].B2c;
        W1d[i].Bz = W[i].B3c;
        Bxc[i] = W[i].B1c;
        Bxi[i] = pG->B1i[ks][js][i];
#endif /* MHD */
#if (NSCALARS > 0)
        for (n=0; n<NSCALARS; n++) W1d[i].s[n] = W[i].s[n];
#endif
    }

    /*--- Step 1b ------------------------------------------------------------------
     * Compute first-order L/R states */

    /* Ensure that W & U are consistent */
    for (i=is-nghost; i<=ie+nghost; i++) {
        U1d[i] = Prim1D_to_Cons1D(&W1d[i],&Bxc[i]);
    }

    for (i=il; i<=ie+nghost; i++) {
        Wl[i] = W1d[i-1];
        Wr[i] = W1d[i  ];

        Ul[i] = U1d[i-1];
        Ur[i] = U1d[i  ];
    }

    /*--- Step 1c ------------------------------------------------------------------
     * No source terms needed */

    /*--- Step 1d ------------------------------------------------------------------
     * Compute flux in x1-direction */

    for (i=il; i<=ie+nghost; i++) {
        fluxes(Ul[i],Ur[i],Wl[i],Wr[i],Bxi[i],&x1Flux[i]);
    }

    /*=== STEPS 2-4: Not needed in 1D ===*/

    /*=== STEP 5: Update cell-centered variables to half-timestep ================*/

    /*--- Step 5a ------------------------------------------------------------------
     * Update cell-centered variables (including B2c and B3c) to half-timestep
     */

    for (i=il; i<=iu; i++) {
        Uhalf[i].d   -= hdtodx1*(x1Flux[i+1].d  - x1Flux[i].d );
        Uhalf[i].M1  -= hdtodx1*(x1Flux[i+1].Mx - x1Flux[i].Mx);
        Uhalf[i].M2  -= hdtodx1*(x1Flux[i+1].My - x1Flux[i].My);
        Uhalf[i].M3  -= hdtodx1*(x1Flux[i+1].Mz - x1Flux[i].Mz);
        Uhalf[i].E   -= hdtodx1*(x1Flux[i+1].E  - x1Flux[i].E );
#ifdef MHD
        Uhalf[i].B2c -= hdtodx1*(x1Flux[i+1].By - x1Flux[i].By);
        Uhalf[i].B3c -= hdtodx1*(x1Flux[i+1].Bz - x1Flux[i].Bz);
#endif /* MHD */
#if (NSCALARS > 0)
        for (n=0; n<NSCALARS; n++)
            Uhalf[i].s[n] -= hdtodx1*(x1Flux[i+1].s[n] - x1Flux[i].s[n]);
#endif
#ifdef FIRST_ORDER_FLUX_CORRECTION
        x1FluxP[i] = x1Flux[i];
#endif
    }

    /*=== STEP 6: Add source terms to predict values at half-timestep ============*/

    /*--- Step 6a ------------------------------------------------------------------
     * Add source terms from a static gravitational potential for 0.5*dt to predict
     * step.  To improve conservation of total energy, we average the energy
     * source term computed at cell faces.
     *    S_{M} = -(\rho) Grad(Phi);   S_{E} = -(\rho v) Grad{Phi}
     */

    if (StaticGravPot != NULL) {
        for (i=il; i<=iu; i++) {
            cc_pos(pG,i,js,ks,&x1,&x2,&x3);
            phic = (*StaticGravPot)((x1            ),x2,x3);
            phir = (*StaticGravPot)((x1+0.5*pG->dx1),x2,x3);
            phil = (*StaticGravPot)((x1-0.5*pG->dx1),x2,x3);

            Uhalf[i].M1 -= hdtodx1*pG->U[ks][js][i].d*(phir-phil);
            Uhalf[i].E -= hdtodx1*(x1Flux[i  ].d*(phic - phil) +
                                   x1Flux[i+1].d*(phir - phic));
        }
    }

    /*=== STEP 7: Conserved->Primitive variable inversion at t^{n+1/2} ===========*/

    /* Invert conserved variables at t^{n+1/2} to primitive variables. With FOFC,
     * if cell-centered d < 0, P< 0, or v^2 > 1, correct by switching back to
     * values at beginning of step, rendering update first order in time for that
     * cell.
     */

#ifdef FIRST_ORDER_FLUX_CORRECTION
    negd = 0;
    negP = 0;
    superl = 0;
    flag_cell = 0;
#endif
    for (i=il; i<=iu; i++) {
        Whalf[i] = Cons_to_Prim(&Uhalf[i]);
#ifdef FIRST_ORDER_FLUX_CORRECTION
        if (Whalf[i].d < 0.0) {
            flag_cell = 1;
            negd++;
        }
        if (Whalf[i].P < 0.0) {
            flag_cell = 1;
            negP++;
        }
        Vsq = SQR(Whalf[i].V1) + SQR(Whalf[i].V2) + SQR(Whalf[i].V3);
        if (Vsq > 1.0) {
            flag_cell = 1;
            superl++;
        }
        if (flag_cell != 0) {
            Whalf[i].d = W[i].d;
            Whalf[i].V1 = W[i].V1;
            Whalf[i].V2 = W[i].V2;
            Whalf[i].V3 = W[i].V3;
            Whalf[i].P = W[i].P;
            flag_cell=0;
        }
#endif
    }

#ifdef FIRST_ORDER_FLUX_CORRECTION
    if (negd > 0 || negP > 0 || superl > 0)
        printf("[Step7]: %i cells had d<0; %i cells had P<0; %i cells had v>1\n"
               ,negd,negP,superl);
#endif


    /*=== STEP 8: Compute second-order L/R x1-interface states ===================*/

    /*--- Step 8a ------------------------------------------------------------------
     * Load 1D vector of primitive variables;
     * W = (d, V1, V2, V3, P, B2c, B3c, s[n])
     */

    for (i=il; i<=iu; i++) {
        W1d[i].d  = Whalf[i].d;
        W1d[i].Vx = Whalf[i].V1;
        W1d[i].Vy = Whalf[i].V2;
        W1d[i].Vz = Whalf[i].V3;
        W1d[i].P  = Whalf[i].P;
#ifdef MHD
        W1d[i].By = Whalf[i].B2c;
        W1d[i].Bz = Whalf[i].B3c;
        Bxc[i]  = Whalf[i].B1c;
#endif /* MHD */
#if (NSCALARS > 0)
        for (n=0; n<NSCALARS; n++) W1d[i].s[n] = Whalf[i].s[n];
#endif /* NSCALARS */
    }

    /*--- Step 8b ------------------------------------------------------------------
     * Compute L/R states on x1-interfaces, store into arrays
     */

    lr_states(pG,W1d,Bxc,pG->dt,pG->dx1,is,ie,Wl,Wr,cart_x1);

#ifdef FIRST_ORDER_FLUX_CORRECTION
    for (i=il; i<=iu; i++) {
        Vsq = SQR(Wl[i].Vx) + SQR(Wl[i].Vy) + SQR(Wl[i].Vz);
        if (Vsq > 1.0) {
            Wl[i] = W1d[i];
            Wr[i] = W1d[i];
        }
        Vsq = SQR(Wr[i].Vx) + SQR(Wr[i].Vy) + SQR(Wr[i].Vz);
        if (Vsq > 1.0) {
            Wl[i] = W1d[i];
            Wr[i] = W1d[i];
        }
    }
#endif

    for (i=is; i<=ie+1; i++) {
        Wl_x1Face[i] = Wl[i];
        Wr_x1Face[i] = Wr[i];
    }

    /*=== STEPS 9-10: Not needed in 1D ===*/

    /*=== STEP 11: Compute x1-Flux ===============================================*/

    /*--- Step 11b -----------------------------------------------------------------
     * Compute second-order fluxes in x1-direction
     */

    for (i=is; i<=ie+1; i++) {
        Ul[i] = Prim1D_to_Cons1D(&Wl_x1Face[i],&Bxi[i]);
        Ur[i] = Prim1D_to_Cons1D(&Wr_x1Face[i],&Bxi[i]);

        fluxes(Ul[i],Ur[i],Wl_x1Face[i],Wr_x1Face[i],Bxi[i],&x1Flux[i]);
    }

    /*=== STEP 12: Not needed in 1D ===*/

    /*=== STEP 13: Add source terms for a full timestep using n+1/2 states =======*/

    /*--- Step 13a -----------------------------------------------------------------
     * Add gravitational source terms due to a Static Potential
     * To improve conservation of total energy, we average the energy
     * source term computed at cell faces.
     *    S_{M} = -(\rho)^{n+1/2} Grad(Phi);   S_{E} = -(\rho v)^{n+1/2} Grad{Phi}
     */

    if (StaticGravPot != NULL) {
        for (i=is; i<=ie; i++) {
            cc_pos(pG,i,js,ks,&x1,&x2,&x3);
            phic = (*StaticGravPot)((x1            ),x2,x3);
            phir = (*StaticGravPot)((x1+0.5*pG->dx1),x2,x3);
            phil = (*StaticGravPot)((x1-0.5*pG->dx1),x2,x3);

            pG->U[ks][js][i].M1 -= dtodx1*Uhalf[i].d*(phir-phil);
#ifndef BAROTROPIC
            pG->U[ks][js][i].E -= dtodx1*(x1Flux[i  ].d*(phic - phil) +
                                          x1Flux[i+1].d*(phir - phic));
#endif
        }
    }

    /*=== STEP 14: Update cell-centered values for a full timestep ===============*/

    /*--- Step 14a -----------------------------------------------------------------
     * Update cell-centered variables in pG (including B2c and B3c) using x1-Fluxes
     */

    for (i=is; i<=ie; i++) {
        pG->U[ks][js][i].d  -= dtodx1*(x1Flux[i+1].d  - x1Flux[i].d );
        pG->U[ks][js][i].M1 -= dtodx1*(x1Flux[i+1].Mx - x1Flux[i].Mx);
        pG->U[ks][js][i].M2 -= dtodx1*(x1Flux[i+1].My - x1Flux[i].My);
        pG->U[ks][js][i].M3 -= dtodx1*(x1Flux[i+1].Mz - x1Flux[i].Mz);
#ifndef BAROTROPIC
        pG->U[ks][js][i].E  -= dtodx1*(x1Flux[i+1].E  - x1Flux[i].E );
#endif /* BAROTROPIC */
#ifdef MHD
        pG->U[ks][js][i].B2c -= dtodx1*(x1Flux[i+1].By - x1Flux[i].By);
        pG->U[ks][js][i].B3c -= dtodx1*(x1Flux[i+1].Bz - x1Flux[i].Bz);
        /* For consistency, set B2i and B3i to cell-centered values.  */
        pG->B2i[ks][js][i] = pG->U[ks][js][i].B2c;
        pG->B3i[ks][js][i] = pG->U[ks][js][i].B3c;
#endif /* MHD */
#if (NSCALARS > 0)
        for (n=0; n<NSCALARS; n++)
            pG->U[ks][js][i].s[n] -= dtodx1*(x1Flux[i+1].s[n] - x1Flux[i].s[n]);
#endif
    }

#ifdef FIRST_ORDER_FLUX_CORRECTION
    /*=== STEP 15: First-order flux correction ===================================*/

    /*--- Step 15a -----------------------------------------------------------------
     * If cell-centered d or P have gone negative, or if v^2 > 1, correct
     * by using 1st order predictor fluxes */

    for (i=is; i<=ie; i++) {
        Wcheck = check_Prim(&(pG->U[ks][js][i]));
        if (Wcheck.d < 0.0) {
            flag_cell = 1;
            BadCell.i = i;
            BadCell.j = js;
            BadCell.k = ks;
            negd++;
        }
        if (Wcheck.P < 0.0) {
            flag_cell = 1;
            BadCell.i = i;
            BadCell.j = js;
            BadCell.k = ks;
            negP++;
        }
        Vsq = SQR(Wcheck.V1) + SQR(Wcheck.V2) + SQR(Wcheck.V3);
        if (Vsq > 1.0) {
            flag_cell = 1;
            BadCell.i = i;
            BadCell.j = js;
            BadCell.k = ks;
            superl++;
        }
        if (flag_cell != 0) {
            FixCell(pG, BadCell);
            flag_cell=0;
        }

    }

    if (negd > 0 || negP > 0 || superl > 0) {
        printf("[Step15a]: %i cells had d<0; %i cells had P<0;\n",negd,negP);
        printf("[Step15a]: %i cells had v>1 at 1st correction\n",superl);
    }

    /*--- Step 15b -----------------------------------------------------------------
     * In SR the first-order flux correction can fail to fix an unphysical state.
     * We must fix these cells in order to avoid NaN's at the next timestep,
     * particuarly if v^2 > 1. We have 2 approaches; firstly, we use the entropy
     * equation (which we have not applied a 1st order flux correction to) to
     * calculate the pressure and the Lorentz factor of the gas. If this produces
     * and unphysical state, then we floor the pressure and iterate on v^2 until
     * v^2 < 1. Possibly could improved by averaging density and pressure from
     * adjacent cells and then calculating pressure.
     */

#ifdef MHD
    fail = 0;
    negd = 0;
    negP = 0;
    final = 0;