void problem(DomainS *pDomain) { GridS *pGrid=(pDomain->Grid); int i,il,iu,j,jl,ju,k,kl,ku; int is,ie,js,je,ks,ke,nx1,nx2,nx3; int shk_dir; /* Shock direction: {1,2,3} -> {x1,x2,x3} */ Real ang_2, ang_3; /* Rotation angles about the y and z' axis */ Real sin_a2, cos_a2, sin_a3, cos_a3; Real x1,x2,x3; Prim1DS Wl, Wr; Cons1DS U1d, Ul, Ur; Real Bxl=0.0, Bxr=0.0, Bxb=0.0; /* speeds of shock, contact, head and foot of rarefaction for Sod test */ /* speeds of slow/fast shocks, Alfven wave and contact in RJ2a test */ Real tlim; int err_test; Real r,xs,xc,xf,xh,vs,vc,vf,vh; Real xfp,xrp,xsp,xsm,xrm,xfm,vfp,vrp,vsp,vsm,vrm,vfm; Real d0,v0,Mx,My,Mz,E0,r0,Bx,By,Bz; #if (NSCALARS > 0) int n; #endif is = pGrid->is; ie = pGrid->ie; js = pGrid->js; je = pGrid->je; ks = pGrid->ks; ke = pGrid->ke; nx1 = (ie-is)+1 + 2*nghost; nx2 = (je-js)+1 + 2*nghost; nx3 = (ke-ks)+1 + 2*nghost; printf("here1\n"); if (pDomain->Level == 0){ if ((RootSoln = (ConsS***)calloc_3d_array(nx3,nx2,nx1,sizeof(ConsS))) == NULL) ath_error("[problem]: Error alloc memory for RootSoln\n"); } /* Parse left state read from input file: dl,pl,ul,vl,wl,bxl,byl,bzl */ Wl.d = par_getd("problem","dl"); #ifdef ADIABATIC Wl.P = par_getd("problem","pl"); #endif Wl.Vx = par_getd("problem","v1l"); Wl.Vy = par_getd("problem","v2l"); Wl.Vz = par_getd("problem","v3l"); #ifdef MHD Bxl = par_getd("problem","b1l"); Wl.By = par_getd("problem","b2l"); Wl.Bz = par_getd("problem","b3l"); #endif #if (NSCALARS > 0) Wl.r[0] = par_getd("problem","r0l"); #endif /* Parse right state read from input file: dr,pr,ur,vr,wr,bxr,byr,bzr */ Wr.d = par_getd("problem","dr"); #ifdef ADIABATIC Wr.P = par_getd("problem","pr"); #endif Wr.Vx = par_getd("problem","v1r"); Wr.Vy = par_getd("problem","v2r"); Wr.Vz = par_getd("problem","v3r"); #ifdef MHD Bxr = par_getd("problem","b1r"); Wr.By = par_getd("problem","b2r"); Wr.Bz = par_getd("problem","b3r"); if (Bxr != Bxl) ath_error(0,"[shkset1d] L/R values of Bx not the same\n"); #endif #if (NSCALARS > 0) Wr.r[0] = par_getd("problem","r0r"); #endif printf("here2\n"); #ifdef SAC_INTEGRATOR Ul = Prim1D_to_Cons1D(&Wl, &Bxl,&Bxb); Ur = Prim1D_to_Cons1D(&Wr, &Bxr,&Bxb); #elif defined SMAUG_INTEGRATOR Ul = Prim1D_to_Cons1D(&Wl, &Bxl,&Bxb); Ur = Prim1D_to_Cons1D(&Wr, &Bxr,&Bxb); #else Ul = Prim1D_to_Cons1D(&Wl, &Bxl); Ur = Prim1D_to_Cons1D(&Wr, &Bxr); #endif printf("here3\n"); /* Parse shock direction */ shk_dir = par_geti("problem","shk_dir"); if (shk_dir != 1 && shk_dir != 2 && shk_dir != 3) { ath_error("[problem]: shk_dir = %d must be either 1,2 or 3\n",shk_dir); } /* Set up the index bounds for initializing the grid */ iu = pGrid->ie + nghost; il = pGrid->is - nghost; if (pGrid->Nx[1] > 1) { ju = pGrid->je + nghost; jl = pGrid->js - nghost; } else { ju = pGrid->je; jl = pGrid->js; } if (pGrid->Nx[2] > 1) { ku = pGrid->ke + nghost; kl = pGrid->ks - nghost; } else { ku = pGrid->ke; kl = pGrid->ks; } printf("here4\n"); /* Initialize the grid including the ghost cells. Discontinuity is always * located at x=0, so xmin/xmax in input file must be set appropriately. */ switch(shk_dir) { /*--- shock in 1-direction ---------------------------------------------------*/ case 1: /* shock in 1-direction */ ang_2 = 0.0; ang_3 = 0.0; for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive and conserved variables to be L or R state */ if (x1 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = U1d.Mx; pGrid->U[k][j][i].M2 = U1d.My; pGrid->U[k][j][i].M3 = U1d.Mz; #ifdef MHD pGrid->B1i[k][j][i] = Bxl; pGrid->B2i[k][j][i] = U1d.By; pGrid->B3i[k][j][i] = U1d.Bz; pGrid->U[k][j][i].B1c = Bxl; pGrid->U[k][j][i].B2c = U1d.By; pGrid->U[k][j][i].B3c = U1d.Bz; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; /*--- shock in 2-direction ---------------------------------------------------*/ case 2: /* shock in 2-direction */ ang_2 = 0.0; ang_3 = PI/2.0; for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive variables to be L or R state */ if (x2 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = -U1d.My; pGrid->U[k][j][i].M2 = U1d.Mx; pGrid->U[k][j][i].M3 = U1d.Mz; #ifdef MHD pGrid->B1i[k][j][i] = -U1d.By; pGrid->B2i[k][j][i] = Bxl; pGrid->B3i[k][j][i] = U1d.Bz; pGrid->U[k][j][i].B1c = -U1d.By; pGrid->U[k][j][i].B2c = Bxl; pGrid->U[k][j][i].B3c = U1d.Bz; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; /*--- shock in 3-direction ---------------------------------------------------*/ case 3: /* shock in 3-direction */ ang_2 = PI/2.0; ang_3 = 0.0; for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive variables to be L or R state */ if (x3 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = -U1d.Mz; pGrid->U[k][j][i].M2 = U1d.My; pGrid->U[k][j][i].M3 = U1d.Mx; #ifdef MHD pGrid->B1i[k][j][i] = -U1d.Bz; pGrid->B2i[k][j][i] = U1d.By; pGrid->B3i[k][j][i] = Bxl; pGrid->U[k][j][i].B1c = -U1d.Bz; pGrid->U[k][j][i].B2c = U1d.By; pGrid->U[k][j][i].B3c = Bxl; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; default: ath_error("[shkset1d]: invalid shk_dir = %i\n",shk_dir); } /* Compute Analytic solution for Sod and RJ4a tests, if required */ tlim = par_getd("time","tlim"); err_test = par_getd_def("problem","error_test",0); if (err_test == 1) { sin_a3 = sin(ang_3); cos_a3 = cos(ang_3); sin_a2 = sin(ang_2); cos_a2 = cos(ang_2); /* wave speeds for Sod test */ #ifdef HYDRO vs = 1.7522; xs = vs*tlim; vc = 0.92745; xc = vc*tlim; vf = -0.07027; xf = vf*tlim; vh = -1.1832; xh = vh*tlim; #endif /* HYDRO */ /* wave speeds for RJ2a test */ #ifdef MHD vfp = 2.2638; xfp = vfp*tlim; vrp = (0.53432 + 1.0/sqrt(PI*1.309)); xrp = vrp*tlim; vsp = (0.53432 + 0.48144/1.309); xsp = vsp*tlim; vc = 0.57538; xc = vc*tlim; vsm = (0.60588 - 0.51594/1.4903); xsm = vsm*tlim; vrm = (0.60588 - 1.0/sqrt(PI*1.4903)); xrm = vrm*tlim; vfm = (1.2 - 2.3305/1.08); xfm = vfm*tlim; #endif /* MHD */ for (k=ks; k<=ke; k++) { for (j=js; j<=je; j++) { for (i=is; i<=ie; i++) { cc_pos(pGrid,i,j,k,&x1,&x2,&x3); r = cos_a2*(x1*cos_a3 + x2*sin_a3) + x3*sin_a2; /* Sod solution */ #ifdef HYDRO My = Mz = 0.0; if (r > xs) { d0 = 0.125; Mx = 0.0; E0 = 0.25; r0 = 0.0; } else if (r > xc) { d0 = 0.26557; Mx = 0.92745*d0; E0 = 0.87204; r0 = 0.0; } else if (r > xf) { d0 = 0.42632; Mx = 0.92745*d0; E0 = 0.94118; r0 = 1.0; } else if (r > xh) { v0 = 0.92745*(r-xh)/(xf-xh); d0 = 0.42632*pow((1.0+0.20046*(0.92745-v0)),5); E0 = (0.30313*pow((1.0+0.20046*(0.92745-v0)),7))/0.4 + 0.5*d0*v0*v0; r0 = 1.0; Mx = v0*d0; } else { d0 = 1.0; Mx = 0.0; E0 = 2.5; r0 = 1.0; } #endif /* HYDRO */ /* RJ2a solution (Dai & Woodward 1994 Tables Ia and Ib) */ #ifdef MHD Bx = 2.0/sqrt(4.0*PI); if (r > xfp) { d0 = 1.0; Mx = 0.0; My = 0.0; Mz = 0.0; By = 4.0/sqrt(4.0*PI); Bz = 2.0/sqrt(4.0*PI); E0 = 1.0/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 0.0; } else if (r > xrp) { d0 = 1.3090; Mx = 0.53432*d0; My = -0.094572*d0; Mz = -0.047286*d0; By = 5.3452/sqrt(4.0*PI); Bz = 2.6726/sqrt(4.0*PI); E0 = 1.5844/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 0.0; } else if (r > xsp) { d0 = 1.3090; Mx = 0.53432*d0; My = -0.18411*d0; Mz = 0.17554*d0; By = 5.7083/sqrt(4.0*PI); Bz = 1.7689/sqrt(4.0*PI); E0 = 1.5844/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 0.0; } else if (r > xc) { d0 = 1.4735; Mx = 0.57538*d0; My = 0.047601*d0; Mz = 0.24734*d0; By = 5.0074/sqrt(4.0*PI); Bz = 1.5517/sqrt(4.0*PI); E0 = 1.9317/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 0.0; } else if (r > xsm) { d0 = 1.6343; Mx = 0.57538*d0; My = 0.047601*d0; Mz = 0.24734*d0; By = 5.0074/sqrt(4.0*PI); Bz = 1.5517/sqrt(4.0*PI); E0 = 1.9317/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 1.0; } else if (r > xrm) { d0 = 1.4903; Mx = 0.60588*d0; My = 0.22157*d0; Mz = 0.30125*d0; By = 5.5713/sqrt(4.0*PI); Bz = 1.7264/sqrt(4.0*PI); E0 = 1.6558/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 1.0; } else if (r > xfm) { d0 = 1.4903; Mx = 0.60588*d0; My = 0.11235*d0; Mz = 0.55686*d0; By = 5.0987/sqrt(4.0*PI); Bz = 2.8326/sqrt(4.0*PI); E0 = 1.6558/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 1.0; } else { d0 = 1.08; Mx = 1.2*d0; My = 0.01*d0; Mz = 0.5*d0; By = 3.6/sqrt(4.0*PI); Bz = 2.0/sqrt(4.0*PI); E0 = 0.95/Gamma_1 + 0.5*((Mx*Mx+My*My+Mz*Mz)/d0 + (Bx*Bx+By*By+Bz*Bz)); r0 = 1.0; } #endif /* MHD */ RootSoln[k][j][i].d = d0; RootSoln[k][j][i].M1 = Mx*cos_a2*cos_a3 - My*sin_a3 - Mz*sin_a2*cos_a3; RootSoln[k][j][i].M2 = Mx*cos_a2*sin_a3 + My*cos_a3 - Mz*sin_a2*sin_a3; RootSoln[k][j][i].M3 = Mx*sin_a2 + Mz*cos_a2; #ifdef MHD RootSoln[k][j][i].B1c = Bx*cos_a2*cos_a3 - By*sin_a3 - Bz*sin_a2*cos_a3; RootSoln[k][j][i].B2c = Bx*cos_a2*sin_a3 + By*cos_a3 - Bz*sin_a2*sin_a3; RootSoln[k][j][i].B3c = Bx*sin_a2 + Bz*cos_a2; #endif /* MHD */ #ifndef ISOTHERMAL RootSoln[k][j][i].E = E0; #endif /* ISOTHERMAL */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) RootSoln[k][j][i].s[n] = r0*d0; #endif } }} } /* end calculation of analytic (root) solution */ return; }
void integrate_2d_smaug(DomainS *pD) { GridS *pG=(pD->Grid); Real dtodx1=pG->dt/pG->dx1, dtodx2=pG->dt/pG->dx2, dtodx3=pG->dt/pG->dx3; Real hdt = 0.5*pG->dt, dx2=pG->dx2; Real q1 = 0.5*dtodx1, q2 = 0.5*dtodx2, q3 = 0.5*dtodx3; int dir; int i,il,iu, is = pG->is, ie = pG->ie; int j,jl,ju, js = pG->js, je = pG->je; int k,kl,ku, ks = pG->ks, ke = pG->ke; Real x1,x2,x3,phicl,phicr,phifc,phil,phir,phic,M1h,M2h,M3h,Bx=0.0,Bxb=0.0; /*Used for hyperdiffusion computations*/ int ii1, dim, ii, ii0; int field; /*integers map to following index rho, mom1, mom2, energy, b1, b2,energyb,rhob,b1b,b2b*/ #ifdef MHD Real MHD_src_By,MHD_src_Bz,mdb1,mdb2,mdb3; Real db1,db2,db3,l1,l2,l3,B1,B2,B3,V1,V2,V3; Real B1ch,B2ch,B3ch; #endif // #if defined(MHD) || defined(SELF_GRAVITY) Real dx1i=1.0/pG->dx1, dx2i=1.0/pG->dx2, dx3i=1.0/pG->dx3; // #endif #if (NSCALARS > 0) int n; #endif #ifdef SELF_GRAVITY Real gxl,gxr,gyl,gyr,gzl,gzr,flx_m1l,flx_m1r,flx_m2l,flx_m2r,flx_m3l,flx_m3r; #endif #ifdef FEEDBACK Real dt1 = 1.0/pG->dt; #endif #ifdef STATIC_MESH_REFINEMENT int ncg,npg,dim; int ii,ics,ice,jj,jcs,jce,kk,kcs,kce,ips,ipe,jps,jpe,kps,kpe; #endif Real g,gl,gr; Real lsf=1.0, rsf=1.0; /* With particles, one more ghost cell must be updated in predict step */ #ifdef PARTICLES Real d1; il = is - 3; iu = ie + 3; jl = js - 3; ju = je + 3; kl = ks - 3; ku = ke + 3; #else il = is - 2; iu = ie + 2; jl = js - 2; ju = je + 2; kl = ks - 2; ku = ke + 2; #endif /* Set etah=0 so first calls to flux functions do not use H-correction */ etah = 0.0; /* Compute predictor feedback from particle drag */ #ifdef FEEDBACK feedback_predictor(pD); exchange_gpcouple(pD,1); #endif /*=== STEP 1: Compute L/R x1-interface states and 1D x1-Fluxes ===============*/ /*--- Step 1a ------------------------------------------------------------------ * Load 1D vector of conserved variables; * U1d = (d, M1, M2, M3, E, B2c, B3c, s[n]) */ for (j=jl; j<=ju; j++) { for (i=is-nghost; i<=ie+nghost; i++) { U1d[i].d = pG->U[ks][j][i].d; U1d[i].Mx = pG->U[ks][j][i].M1; U1d[i].My = pG->U[ks][j][i].M2; U1d[i].Mz = pG->U[ks][j][i].M3; #ifndef BAROTROPIC U1d[i].E = pG->U[ks][j][i].E; #endif /* BAROTROPIC */ #ifdef MHD U1d[i].By = pG->U[ks][j][i].B2c; U1d[i].Bz = pG->U[ks][j][i].B3c; Bxc[i] = pG->U[ks][j][i].B1c; Bxi[i] = pG->B1i[ks][j][i]; B1_x1[j][i] = pG->B1i[ks][j][i]; #endif /* MHD */ #ifdef BKG U1d[i].db = pG->U[ks][j][i].db; U1d[i].Byb = pG->U[ks][j][i].B2cb; U1d[i].Bzb = pG->U[ks][j][i].B3cb; #endif #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) U1d[i].s[n] = pG->U[ks][j][i].s[n]; #endif } /*--- Step 1b ------------------------------------------------------------------ * Compute L and R states at X1-interfaces, add "MHD source terms" for 0.5*dt */ for (i=is-nghost; i<=ie+nghost; i++) { W[i] = Cons1D_to_Prim1D(&U1d[i],&Bxc[i],&Bxb); /*--- Step 1c ------------------------------------------------------------------ * Add source terms from static gravitational potential for 0.5*dt to L/R states */ /*if (StaticGravPot != NULL){ for (i=il+1; i<=iu; i++) { cc_pos(pG,i,j,ks,&x1,&x2,&x3); phicr = (*StaticGravPot)( x1 ,x2,x3); phicl = (*StaticGravPot)((x1- pG->dx1),x2,x3); phifc = (*StaticGravPot)((x1-0.5*pG->dx1),x2,x3); gl = 2.0*(phifc - phicl)*dx1i; gr = 2.0*(phicr - phifc)*dx1i; #if defined(CYLINDRICAL) && defined(FARGO) gl -= r[i-1]*SQR((*OrbitalProfile)(r[i-1])); gr -= r[i ]*SQR((*OrbitalProfile)(r[i ])); #endif W[i].Vx -= hdt*gl; } }*/ /*--- Step 1c (cont) ----------------------------------------------------------- * Add the geometric source-terms now using cell-centered primitive * variables at time t^n */ /*--- Step 1d ------------------------------------------------------------------ * Compute 1D fluxes in x1-direction, storing into 3D array */ for (i=il+1; i<=iu; i++) { Uc_x1[j][i] = Prim1D_to_Cons1D(&W[i],&Bxi[i],&Bxb); #ifdef MHD Bx = B1_x1[j][i]; Bxb=0.0;//????????????????????????? #endif fluxes(Uc_x1[j][i],Uc_x1[j][i],W[i],W[i],Bx,Bxb,&x1Flux[j][i]); } } /*=== STEP 2: Compute L/R x2-interface states and 1D x2-Fluxes ===============*/ /*--- Step 2a ------------------------------------------------------------------ * Load 1D vector of conserved variables; * U1d = (d, M2, M3, M1, E, B3c, B1c, s[n]) */ for (i=il; i<=iu; i++) { #ifdef CYLINDRICAL dx2 = r[i]*pG->dx2; dx2i = 1.0/dx2; dtodx2 = pG->dt*dx2i; hdtodx2 = 0.5*dtodx2; #endif for (j=js-nghost; j<=je+nghost; j++) { U1d[j].d = pG->U[ks][j][i].d; U1d[j].Mx = pG->U[ks][j][i].M2; U1d[j].My = pG->U[ks][j][i].M3; U1d[j].Mz = pG->U[ks][j][i].M1; #ifndef BAROTROPIC U1d[j].E = pG->U[ks][j][i].E; #endif /* BAROTROPIC */ #ifdef MHD U1d[j].By = pG->U[ks][j][i].B3c; U1d[j].Bz = pG->U[ks][j][i].B1c; Bxc[j] = pG->U[ks][j][i].B2c; Bxi[j] = pG->B2i[ks][j][i]; B2_x2[j][i] = pG->B2i[ks][j][i]; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) U1d[j].s[n] = pG->U[ks][j][i].s[n]; #endif } /*--- Step 2b ------------------------------------------------------------------ * Compute L and R states at X2-interfaces, add "MHD source terms" for 0.5*dt */ /*--- Step 2c ------------------------------------------------------------------ * Add source terms from static gravitational potential for 0.5*dt to L/R states */ /* if (StaticGravPot != NULL){ for (j=jl+1; j<=ju; j++) { cc_pos(pG,i,j,ks,&x1,&x2,&x3); phicr = (*StaticGravPot)(x1, x2 ,x3); phicl = (*StaticGravPot)(x1,(x2- pG->dx2),x3); phifc = (*StaticGravPot)(x1,(x2-0.5*pG->dx2),x3); W[j].Vx -= dtodx2*(phifc - phicl); } }*/ /*--- Step 2d ------------------------------------------------------------------ * Compute 1D fluxes in x2-direction, storing into 3D array */ for (j=jl+1; j<=ju; j++) { Uc_x2[j][i] = Prim1D_to_Cons1D(&W[j],&Bxi[j],&Bxb); #ifdef MHD Bx = B2_x2[j][i]; Bxb=0.0;//????????????????????????? #endif fluxes(Uc_x2[j][i],Uc_x2[j][i],W[j],W[j],Bx,Bxb,&x2Flux[j][i]); } } /*--- Step 3c ------------------------------------------------------------------ * Add source terms from static gravitational potential for 0.5*dt to L/R states */ /* if (StaticGravPot != NULL){ for (k=kl+1; k<=ku; k++) { cc_pos(pG,i,j,ks,&x1,&x2,&x3); phicr = (*StaticGravPot)(x1,x2, x3 ); phicl = (*StaticGravPot)(x1,x2,(x3- pG->dx3)); phifc = (*StaticGravPot)(x1,x2,(x3-0.5*pG->dx3)); W[k].Vx -= dtodx3*(phifc - phicl); } }*/ /*--- Step 3d ------------------------------------------------------------------ * Compute 1D fluxes in x3-direction, storing into 3D array */ /*Not needed here for 2d problem*/ /*=== STEP 4: Update face-centered B for 0.5*dt =============================*/ /*--- Step 4a ------------------------------------------------------------------ * Calculate the cell centered value of emf1,2,3 at t^{n} and integrate * to corner. */ /*--- Step 4b ------------------------------------------------------------------ * Update the interface magnetic fields using CT for a half time step. */ /*=== STEP 5: Correct x1-interface states with transverse flux gradients =====*/ /*--- Step 5a ------------------------------------------------------------------ * Correct x1-interface states using x2-fluxes computed in Step 2d. * Since the fluxes come from an x2-sweep, (x,y,z) on RHS -> (z,x,y) on LHS */ /*--- Step 5b ------------------------------------------------------------------ * Correct x1-interface states using x3-fluxes computed in Step 3d. * Since the fluxes come from an x3-sweep, (x,y,z) on RHS -> (y,z,x) on LHS */ /*--- Step 5c ------------------------------------------------------------------ * Add the "MHD source terms" from the x2- and x3-flux-gradients to the * conservative variables on the x1Face. Limiting is used as in GS (2007) */ /*--- Step 5d ------------------------------------------------------------------ * Add source terms for a static gravitational potential arising from x2-Flux * and x3-Flux gradients. To improve conservation of total energy, average * the energy source term computed at cell faces. * S_{M} = -(\rho) Grad(Phi); S_{E} = -(\rho v) Grad{Phi} */ /* if (StaticGravPot != NULL){ for (k=kl+1; k<=ku-1; k++) { for (j=jl+1; j<=ju-1; j++) { for (i=il+1; i<=iu; i++) { cc_pos(pG,i,j,k,&x1,&x2,&x3); phic = (*StaticGravPot)(x1, x2 ,x3); phir = (*StaticGravPot)(x1,(x2+0.5*pG->dx2),x3); phil = (*StaticGravPot)(x1,(x2-0.5*pG->dx2),x3); ---------*/ /* correct right states; x2 and x3 gradients */ /*----------------------------- #ifdef CYLINDRICAL q2 = hdt/(r[i]*pG->dx2); #endif Ur_x1Face[k][j][i].My -= q2*(phir-phil)*pG->U[k][j][i].d; #ifndef BAROTROPIC Ur_x1Face[k][j][i].E -= q2*(x2Flux[k][j ][i ].d*(phic - phil) + x2Flux[k][j+1][i ].d*(phir - phic)); #ifdef ROTATING_FRAME Ur_x1Face[k][j][i].E += hdt * 0.5*(x2Flux[k][j ][i ].d*sin(x2-0.5*pG->dx2) + x2Flux[k][j+1][i ].d*sin(x2+0.5*pG->dx2)) *SQR(Omega_0)*Rc; #endif #endif phir = (*StaticGravPot)(x1,x2,(x3+0.5*pG->dx3)); phil = (*StaticGravPot)(x1,x2,(x3-0.5*pG->dx3)); Ur_x1Face[k][j][i].Mz -= q3*(phir-phil)*pG->U[k][j][i].d; #ifndef BAROTROPIC Ur_x1Face[k][j][i].E -= q3*(x3Flux[k ][j][i ].d*(phic - phil) + x3Flux[k+1][j][i ].d*(phir - phic)); #endif -----------------------*/ /* correct left states; x2 and x3 gradients */ /*-------------------------------------------- phic = (*StaticGravPot)((x1-pG->dx1), x2 ,x3); phir = (*StaticGravPot)((x1-pG->dx1),(x2+0.5*pG->dx2),x3); phil = (*StaticGravPot)((x1-pG->dx1),(x2-0.5*pG->dx2),x3); #ifdef CYLINDRICAL q2 = hdt/(r[i-1]*pG->dx2); #endif Ul_x1Face[k][j][i].My -= q2*(phir-phil)*pG->U[k][j][i-1].d; #ifndef BAROTROPIC Ul_x1Face[k][j][i].E -= q2*(x2Flux[k][j ][i-1].d*(phic - phil) + x2Flux[k][j+1][i-1].d*(phir - phic)); #ifdef ROTATING_FRAME Ul_x1Face[k][j][i].E += hdt * 0.5*(x2Flux[k][j ][i-1].d*sin(x2-0.5*pG->dx2) + x2Flux[k][j+1][i-1].d*sin(x2+0.5*pG->dx2)) *SQR(Omega_0)*Rc; #endif #endif phir = (*StaticGravPot)((x1-pG->dx1),x2,(x3+0.5*pG->dx3)); phil = (*StaticGravPot)((x1-pG->dx1),x2,(x3-0.5*pG->dx3)); Ul_x1Face[k][j][i].Mz -= q3*(phir-phil)*pG->U[k][j][i-1].d; #ifndef BAROTROPIC Ul_x1Face[k][j][i].E -= q3*(x3Flux[k ][j][i-1].d*(phic - phil) + x3Flux[k+1][j][i-1].d*(phir - phic)); #endif } } }}*/ /*=== STEP 6: Correct x2-interface states with transverse flux gradients =====*/ /*--- Step 6a ------------------------------------------------------------------ * Correct x2-interface states using x1-fluxes computed in Step 1d. * Since the fluxes come from an x1-sweep, (x,y,z) on RHS -> (y,z,x) on LHS */ /*--- Step 6b ------------------------------------------------------------------ * Correct x2-interface states using x3-fluxes computed in Step 3d. * Since the fluxes come from an x3-sweep, (x,y,z) on RHS -> (z,x,y) on LHS */ /*--- Step 6c ------------------------------------------------------------------ * Add the "MHD source terms" from the x1- and x3-flux-gradients to the * conservative variables on the x2Face. Limiting is used as in GS (2007) */ /*--- Step 6d ------------------------------------------------------------------ * Add source terms for a static gravitational potential arising from x1-Flux * and x3-Flux gradients. To improve conservation of total energy, * average the energy source term computed at cell faces. * S_{M} = -(\rho) Grad(Phi); S_{E} = -(\rho v) Grad{Phi} */ /*=== STEP 7: Correct x3-interface states with transverse flux gradients =====*/ /*--- Step 7a ------------------------------------------------------------------ * Correct x3-interface states using x1-fluxes computed in Step 1d. * Since the fluxes come from an x1-sweep, (x,y,z) on RHS -> (z,x,y) on LHS */ /*--- Step 7b ------------------------------------------------------------------ * Correct x3-interface states using x2-fluxes computed in Step 2d. * Since the fluxes come from an x2-sweep, (x,y,z) on RHS -> (y,z,x) on LHS */ /*--- Step 7c ------------------------------------------------------------------ * Add the "MHD source terms" from the x1- and x2-flux-gradients to the * conservative variables on the x3Face. Limiting is used as in GS07. */ /*--- Step 7d ------------------------------------------------------------------ * Add source terms for a static gravitational potential arising from x1-Flux * and x2-Flux gradients. To improve conservation of total energy, * average the energy source term computed at cell faces. * S_{M} = -(\rho) Grad(Phi); S_{E} = -(\rho v) Grad{Phi} */ /*--- Step 7e ------------------------------------------------------------------ * Apply density floor */ /*=== STEP 8: Compute cell-centered values at n+1/2 ==========================*/ /*=== STEP 9: Compute 3D x1-Flux, x2-Flux, x3-Flux ===========================*/ /*--- Step 9a ------------------------------------------------------------------ * Compute maximum wavespeeds in multidimensions (eta in eq. 10 from Sanders et * al. (1998)) for H-correction */ /*--- Step 9b ------------------------------------------------------------------ * Compute 3D x1-fluxes from corrected L/R states. */ /*--- Step 9c ------------------------------------------------------------------ * Compute 3D x2-fluxes from corrected L/R states. */ /*--- Step 9d ------------------------------------------------------------------ * Compute 3D x3-fluxes from corrected L/R states. */ /*=== STEP 10: Update face-centered B for a full timestep ====================*/ /*--- Step 10a ----------------------------------------------------------------- * Integrate emf*^{n+1/2} to the grid cell corners */ /*--- Step 10b ----------------------------------------------------------------- * Update the interface magnetic fields using CT for a full time step. */ /*=== STEP 11: Add source terms for a full timestep using n+1/2 states =======*/ /*=== STEP 12: Update cell-centered values for a full timestep ===============*/ /*--- Step 12a ----------------------------------------------------------------- * Update cell-centered variables in pG using 3D x1-Fluxes */ for (j=js; j<=je; j++) { for (i=is; i<=ie; i++) { #ifdef CYLINDRICAL rsf = ri[i+1]/r[i]; lsf = ri[i]/r[i]; #endif pG->U[ks][j][i].d -= dtodx1*(rsf*x1Flux[j][i+1].d - lsf*x1Flux[j][i].d ); pG->U[ks][j][i].M1 -= dtodx1*(rsf*x1Flux[j][i+1].Mx - lsf*x1Flux[j][i].Mx); pG->U[ks][j][i].M2 -= dtodx1*(SQR(rsf)*x1Flux[j][i+1].My - SQR(lsf)*x1Flux[j][i].My); pG->U[ks][j][i].M3 -= dtodx1*(rsf*x1Flux[j][i+1].Mz - lsf*x1Flux[j][i].Mz); #ifndef BAROTROPIC pG->U[ks][j][i].E -= dtodx1*(rsf*x1Flux[j][i+1].E - lsf*x1Flux[j][i].E ); #endif /* BAROTROPIC */ #ifdef MHD pG->U[ks][j][i].B2c -= dtodx1*(x1Flux[j][i+1].By - x1Flux[j][i].By); pG->U[ks][j][i].B3c -= dtodx1*(rsf*x1Flux[j][i+1].Bz - lsf*x1Flux[j][i].Bz); #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->U[ks][j][i].s[n] -= dtodx1*(rsf*x1Flux[j][i+1].s[n] - lsf*x1Flux[j][i ].s[n]); #endif } } /*--- Step 12b ----------------------------------------------------------------- * Update cell-centered variables in pG using 3D x2-Fluxes */ for (j=js; j<=je; j++) { for (i=is; i<=ie; i++) { #ifdef CYLINDRICAL dtodx2 = pG->dt/(r[i]*pG->dx2); #endif pG->U[ks][j][i].d -= dtodx2*(x2Flux[j+1][i].d - x2Flux[j][i].d ); pG->U[ks][j][i].M1 -= dtodx2*(x2Flux[j+1][i].Mz - x2Flux[j][i].Mz); pG->U[ks][j][i].M2 -= dtodx2*(x2Flux[j+1][i].Mx - x2Flux[j][i].Mx); pG->U[ks][j][i].M3 -= dtodx2*(x2Flux[j+1][i].My - x2Flux[j][i].My); #ifndef BAROTROPIC pG->U[ks][j][i].E -= dtodx2*(x2Flux[j+1][i].E - x2Flux[j][i].E ); #endif /* BAROTROPIC */ #ifdef MHD pG->U[ks][j][i].B3c -= dtodx2*(x2Flux[j+1][i].By - x2Flux[j][i].By); pG->U[ks][j][i].B1c -= dtodx2*(x2Flux[j+1][i].Bz - x2Flux[j][i].Bz); #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->U[ks][j][i].s[n] -= dtodx2*(x2Flux[j+1][i].s[n] - x2Flux[j ][i].s[n]); #endif } } /*--- Step 12c ----------------------------------------------------------------- * Update cell-centered variables in pG using 3D x3-Fluxes */ //hyperdifvisc1r //hyperdifvisc1l //computec //computemaxc //density contribution for(dim=0; dim<2; dim++) //each direction { //hyperdifvisc1ir //hyperdifvisc1il //hyperdifrhosource1 ; } //energy hyperdiffusion term for(dim=0; dim<2; dim++) //each direction { //hyperdifvisc1ir //hyperdifvisc1il //hyperdifesource1 ; } //momentum hyperdiffusion term for(dim=0; dim<2; dim++) //each direction { //hyperdifvisc1ir //hyperdifvisc1il //hyperdifesource1 for(ii1=0;ii1<=1;ii1++) { if (ii1 == 0) { ii=dim; ii0=field; //f is field } else { ii=field; ii0=dim; } if(ii==dim) ;// hyperdifmomsource1(ii,ii0,pG->dt); else ;// hyperdifmomsourcene1(ii,ii0,pG->dt); //off diagonal } } #ifdef MHD //b field hyperdiffusion term for(dim=0; dim<2; dim++) //each direction { //hyperdifvisc1ir //hyperdifvisc1il for(ii1=0;ii1<=1;ii1++) { if (ii1 == 0) { ii=dim; ii0=field; //f is field } else { ii=field; ii0=dim; } if(ii==dim) ;// hyperdifbsource(ii,ii0,pG->dt,pG); else ;// hyperdifbsourcene(ii,ii0,pG->dt,pG); //off diagonal } } #endif /*hyperdiffusion source term for bfield*/ /*static mesh refinement part goes here*/ #ifdef STATIC_MESH_REFINEMENT /*--- Step 12e ----------------------------------------------------------------- * With SMR, store fluxes at boundaries of child and parent grids. */ for (ncg=0; ncg<pG->NCGrid; ncg++) { /* x1-boundaries of child Grids (interior to THIS Grid) */ for (dim=0; dim<2; dim++){ if (pG->CGrid[ncg].myFlx[dim] != NULL) { if (dim==0) i = pG->CGrid[ncg].ijks[0]; if (dim==1) i = pG->CGrid[ncg].ijke[0] + 1; jcs = pG->CGrid[ncg].ijks[1]; jce = pG->CGrid[ncg].ijke[1]; for (j=jcs, jj=0; j<=jce; j++, jj++){ pG->CGrid[ncg].myFlx[dim][ks][jj].d = x1Flux[j][i].d; pG->CGrid[ncg].myFlx[dim][ks][jj].M1 = x1Flux[j][i].Mx; pG->CGrid[ncg].myFlx[dim][ks][jj].M2 = x1Flux[j][i].My; pG->CGrid[ncg].myFlx[dim][ks][jj].M3 = x1Flux[j][i].Mz; #ifndef BAROTROPIC pG->CGrid[ncg].myFlx[dim][ks][jj].E = x1Flux[j][i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->CGrid[ncg].myFlx[dim][ks][jj].B1c = 0.0; pG->CGrid[ncg].myFlx[dim][ks][jj].B2c = x1Flux[j][i].By; pG->CGrid[ncg].myFlx[dim][ks][jj].B3c = x1Flux[j][i].Bz; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->CGrid[ncg].myFlx[dim][ks][jj].s[n] = x1Flux[j][i].s[n]; #endif } #ifdef MHD for (j=jcs, jj=0; j<=jce+1; j++, jj++){ pG->CGrid[ncg].myEMF3[dim][ks][jj] = emf3[j][i]; } #endif /* MHD */ } } /* x2-boundaries of child Grids (interior to THIS Grid) */ for (dim=2; dim<4; dim++){ if (pG->CGrid[ncg].myFlx[dim] != NULL) { ics = pG->CGrid[ncg].ijks[0]; ice = pG->CGrid[ncg].ijke[0]; if (dim==2) j = pG->CGrid[ncg].ijks[1]; if (dim==3) j = pG->CGrid[ncg].ijke[1] + 1; for (i=ics, ii=0; i<=ice; i++, ii++){ pG->CGrid[ncg].myFlx[dim][ks][ii].d = x2Flux[j][i].d; pG->CGrid[ncg].myFlx[dim][ks][ii].M1 = x2Flux[j][i].Mz; pG->CGrid[ncg].myFlx[dim][ks][ii].M2 = x2Flux[j][i].Mx; pG->CGrid[ncg].myFlx[dim][ks][ii].M3 = x2Flux[j][i].My; #ifndef BAROTROPIC pG->CGrid[ncg].myFlx[dim][ks][ii].E = x2Flux[j][i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->CGrid[ncg].myFlx[dim][ks][ii].B1c = x2Flux[j][i].Bz; pG->CGrid[ncg].myFlx[dim][ks][ii].B2c = 0.0; pG->CGrid[ncg].myFlx[dim][ks][ii].B3c = x2Flux[j][i].By; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->CGrid[ncg].myFlx[dim][ks][ii].s[n] = x2Flux[j][i].s[n]; #endif } #ifdef MHD for (i=ics, ii=0; i<=ice+1; i++, ii++){ pG->CGrid[ncg].myEMF3[dim][ks][ii] = emf3[j][i]; } #endif /* MHD */ } } } for (npg=0; npg<pG->NPGrid; npg++) { /* x1-boundaries of parent Grids (at boundaries of THIS Grid) */ for (dim=0; dim<2; dim++){ if (pG->PGrid[npg].myFlx[dim] != NULL) { if (dim==0) i = pG->PGrid[npg].ijks[0]; if (dim==1) i = pG->PGrid[npg].ijke[0] + 1; jps = pG->PGrid[npg].ijks[1]; jpe = pG->PGrid[npg].ijke[1]; for (j=jps, jj=0; j<=jpe; j++, jj++){ pG->PGrid[npg].myFlx[dim][ks][jj].d = x1Flux[j][i].d; pG->PGrid[npg].myFlx[dim][ks][jj].M1 = x1Flux[j][i].Mx; pG->PGrid[npg].myFlx[dim][ks][jj].M2 = x1Flux[j][i].My; pG->PGrid[npg].myFlx[dim][ks][jj].M3 = x1Flux[j][i].Mz; #ifndef BAROTROPIC pG->PGrid[npg].myFlx[dim][ks][jj].E = x1Flux[j][i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->PGrid[npg].myFlx[dim][ks][jj].B1c = 0.0; pG->PGrid[npg].myFlx[dim][ks][jj].B2c = x1Flux[j][i].By; pG->PGrid[npg].myFlx[dim][ks][jj].B3c = x1Flux[j][i].Bz; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->PGrid[npg].myFlx[dim][ks][jj].s[n] = x1Flux[j][i].s[n]; #endif } #ifdef MHD for (j=jps, jj=0; j<=jpe+1; j++, jj++){ pG->PGrid[npg].myEMF3[dim][ks][jj] = emf3[j][i]; } #endif /* MHD */ } } /* x2-boundaries of parent Grids (at boundaries of THIS Grid) */ for (dim=2; dim<4; dim++){ if (pG->PGrid[npg].myFlx[dim] != NULL) { ips = pG->PGrid[npg].ijks[0]; ipe = pG->PGrid[npg].ijke[0]; if (dim==2) j = pG->PGrid[npg].ijks[1]; if (dim==3) j = pG->PGrid[npg].ijke[1] + 1; for (i=ips, ii=0; i<=ipe; i++, ii++){ pG->PGrid[npg].myFlx[dim][ks][ii].d = x2Flux[j][i].d; pG->PGrid[npg].myFlx[dim][ks][ii].M1 = x2Flux[j][i].Mz; pG->PGrid[npg].myFlx[dim][ks][ii].M2 = x2Flux[j][i].Mx; pG->PGrid[npg].myFlx[dim][ks][ii].M3 = x2Flux[j][i].My; #ifndef BAROTROPIC pG->PGrid[npg].myFlx[dim][ks][ii].E = x2Flux[j][i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->PGrid[npg].myFlx[dim][ks][ii].B1c = x2Flux[j][i].Bz; pG->PGrid[npg].myFlx[dim][ks][ii].B2c = 0.0; pG->PGrid[npg].myFlx[dim][ks][ii].B3c = x2Flux[j][i].By; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->PGrid[npg].myFlx[dim][ks][ii].s[n] = x2Flux[j][i].s[n]; #endif } #ifdef MHD for (i=ips, ii=0; i<=ipe+1; i++, ii++){ pG->PGrid[npg].myEMF3[dim][ks][ii] = emf3[j][i]; } #endif /* MHD */ } } } #endif /* STATIC_MESH_REFINEMENT */ } return; }
void integrate_1d_vl(DomainS *pD) { GridS *pG=(pD->Grid); 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; 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 int il=is-(nghost-1), iu=ie+(nghost-1); for (i=is-nghost; i<=ie+nghost; i++) { Uhalf[i] = 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 conserved variables; * U1d = (d, M1, M2, M3, E, B2c, B3c, s[n]) */ for (i=is-nghost; i<=ie+nghost; i++) { U1d[i].d = pG->U[ks][js][i].d; U1d[i].Mx = pG->U[ks][js][i].M1; U1d[i].My = pG->U[ks][js][i].M2; U1d[i].Mz = pG->U[ks][js][i].M3; #ifndef BAROTROPIC U1d[i].E = pG->U[ks][js][i].E; #endif /* BAROTROPIC */ #ifdef MHD U1d[i].By = pG->U[ks][js][i].B2c; U1d[i].Bz = pG->U[ks][js][i].B3c; Bxc[i] = pG->U[ks][js][i].B1c; Bxi[i] = pG->B1i[ks][js][i]; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) U1d[i].s[n] = pG->U[ks][js][i].s[n]; #endif } /*--- Step 1b ------------------------------------------------------------------ * Compute first-order L/R states */ for (i=is-nghost; i<=ie+nghost; i++) { W[i] = Cons1D_to_Prim1D(&U1d[i],&Bxc[i]); } for (i=il; i<=ie+nghost; i++) { Wl[i] = W[i-1]; Wr[i] = W[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); #ifndef BAROTROPIC Uhalf[i].E -= hdtodx1*(x1Flux[i+1].E - x1Flux[i].E ); #endif /* BAROTROPIC */ #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 } /*=== 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); #ifndef BAROTROPIC Uhalf[i].E -= hdtodx1*(x1Flux[i ].d*(phic - phil) + x1Flux[i+1].d*(phir - phic)); #endif } } Real accl, accc1, accr; if(1) { accc = pG->AccX[i]; accl = pG->AccX[i-1]; accr = pG->AccX[i+1]; } /*--- Step 6b ------------------------------------------------------------------ * Add source terms for self gravity for 0.5*dt to predict step. * S_{M} = -(\rho) Grad(Phi); S_{E} = -(\rho v) Grad{Phi} */ #ifdef SELF_GRAVITY for (i=il; i<=iu; i++) { phic = pG->Phi[ks][js][i]; phir = 0.5*(pG->Phi[ks][js][i] + pG->Phi[ks][js][i+1]); phil = 0.5*(pG->Phi[ks][js][i] + pG->Phi[ks][js][i-1]); Uhalf[i].M1 -= hdtodx1*pG->U[ks][js][i].d*(phir-phil); #ifndef BAROTROPIC Uhalf[i].E -= hdtodx1*(x1Flux[i ].d*(phic - phil) + x1Flux[i+1].d*(phir - phic)); #endif } #endif /* SELF_GRAVITY */ /*=== STEP 7: Compute second-order L/R x1-interface states ===================*/ /*--- Step 7a ------------------------------------------------------------------ * Load 1D vector of conserved variables; * U = (d, M1, M2, M3, E, B2c, B3c, s[n]) */ for (i=il; i<=iu; i++) { U1d[i].d = Uhalf[i].d; U1d[i].Mx = Uhalf[i].M1; U1d[i].My = Uhalf[i].M2; U1d[i].Mz = Uhalf[i].M3; #ifndef BAROTROPIC U1d[i].E = Uhalf[i].E; #endif /* BAROTROPIC */ #ifdef MHD U1d[i].By = Uhalf[i].B2c; U1d[i].Bz = Uhalf[i].B3c; Bxc[i] = Uhalf[i].B1c; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) U1d[i].s[n] = Uhalf[i].s[n]; #endif /* NSCALARS */ } /*--- Step 7b ------------------------------------------------------------------ * Compute L/R states on x1-interfaces, store into arrays */ for (i=il; i<=iu; i++) { W[i] = Cons1D_to_Prim1D(&U1d[i],&Bxc[i]); } lr_states(pG,W,Bxc,pG->dt,pG->dx1,is,ie,Wl,Wr,1); for (i=is; i<=ie+1; i++) { Wl_x1Face[i] = Wl[i]; Wr_x1Face[i] = Wr[i]; } /*=== STEPS 8-9: Not needed in 1D ===*/ /*=== STEP 10: Compute x1-Flux ===============================================*/ /*--- Step 10b ----------------------------------------------------------------- * 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 11: Not needed in 1D ===*/ /*=== STEP 12: Add source terms for a full timestep using n+1/2 states =======*/ /*--- Step 12a ----------------------------------------------------------------- * 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 12b ----------------------------------------------------------------- * Add gravitational source terms for self-gravity. * A flux correction using Phi^{n+1} in the main loop is required to make * the source terms 2nd order: see selfg_flux_correction(). */ #ifdef SELF_GRAVITY /* Add fluxes and source terms due to (d/dx1) terms */ for (i=is; i<=ie; i++){ phic = pG->Phi[ks][js][i]; phil = 0.5*(pG->Phi[ks][js][i-1] + pG->Phi[ks][js][i ]); phir = 0.5*(pG->Phi[ks][js][i ] + pG->Phi[ks][js][i+1]); /* gx, gy and gz centered at L and R x1-faces */ gxl = (pG->Phi[ks][js][i-1] - pG->Phi[ks][js][i ])/(pG->dx1); gxr = (pG->Phi[ks][js][i ] - pG->Phi[ks][js][i+1])/(pG->dx1); /* momentum fluxes in x1. 2nd term is needed only if Jean's swindle used */ flx_m1l = 0.5*(gxl*gxl)/four_pi_G + grav_mean_rho*phil; flx_m1r = 0.5*(gxr*gxr)/four_pi_G + grav_mean_rho*phir; /* Update momenta and energy with d/dx1 terms */ pG->U[ks][js][i].M1 -= dtodx1*(flx_m1r - flx_m1l); #ifndef BAROTROPIC pG->U[ks][js][i].E -= dtodx1*(x1Flux[i ].d*(phic - phil) + x1Flux[i+1].d*(phir - phic)); #endif /* BAROTROPIC */ } /* Save mass fluxes in Grid structure for source term correction in main loop */ for (i=is; i<=ie+1; i++) { pG->x1MassFlux[ks][js][i] = x1Flux[i].d; } #endif /* SELF_GRAVITY */ /*=== STEP 13: Update cell-centered values for a full timestep ===============*/ /*--- Step 13a ----------------------------------------------------------------- * 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 STATIC_MESH_REFINEMENT /*--- Step 13d ----------------------------------------------------------------- * With SMR, store fluxes at boundaries of child and parent grids. */ /* x1-boundaries of child Grids (interior to THIS Grid) */ for (ncg=0; ncg<pG->NCGrid; ncg++) { for (dim=0; dim<2; dim++){ if (pG->CGrid[ncg].myFlx[dim] != NULL) { if (dim==0) i = pG->CGrid[ncg].ijks[0]; if (dim==1) i = pG->CGrid[ncg].ijke[0] + 1; pG->CGrid[ncg].myFlx[dim][ks][js].d = x1Flux[i].d; pG->CGrid[ncg].myFlx[dim][ks][js].M1 = x1Flux[i].Mx; pG->CGrid[ncg].myFlx[dim][ks][js].M2 = x1Flux[i].My; pG->CGrid[ncg].myFlx[dim][ks][js].M3 = x1Flux[i].Mz; #ifndef BAROTROPIC pG->CGrid[ncg].myFlx[dim][ks][js].E = x1Flux[i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->CGrid[ncg].myFlx[dim][ks][js].B1c = 0.0; pG->CGrid[ncg].myFlx[dim][ks][js].B2c = x1Flux[i].By; pG->CGrid[ncg].myFlx[dim][ks][js].B3c = x1Flux[i].Bz; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->CGrid[ncg].myFlx[dim][ks][js].s[n] = x1Flux[i].s[n]; #endif } } } /* x1-boundaries of parent Grids (at boundaries of THIS Grid) */ for (npg=0; npg<pG->NPGrid; npg++) { for (dim=0; dim<2; dim++){ if (pG->PGrid[npg].myFlx[dim] != NULL) { if (dim==0) i = pG->PGrid[npg].ijks[0]; if (dim==1) i = pG->PGrid[npg].ijke[0] + 1; pG->PGrid[npg].myFlx[dim][ks][js].d = x1Flux[i].d; pG->PGrid[npg].myFlx[dim][ks][js].M1 = x1Flux[i].Mx; pG->PGrid[npg].myFlx[dim][ks][js].M2 = x1Flux[i].My; pG->PGrid[npg].myFlx[dim][ks][js].M3 = x1Flux[i].Mz; #ifndef BAROTROPIC pG->PGrid[npg].myFlx[dim][ks][js].E = x1Flux[i].E; #endif /* BAROTROPIC */ #ifdef MHD pG->PGrid[npg].myFlx[dim][ks][js].B1c = 0.0; pG->PGrid[npg].myFlx[dim][ks][js].B2c = x1Flux[i].By; pG->PGrid[npg].myFlx[dim][ks][js].B3c = x1Flux[i].Bz; #endif /* MHD */ #if (NSCALARS > 0) for (n=0; n<NSCALARS; n++) pG->PGrid[npg].myFlx[dim][ks][js].s[n] = x1Flux[i].s[n]; #endif } } } #endif /* STATIC_MESH_REFINEMENT */ return; }
void problem(DomainS *pDomain) { GridS *pGrid=(pDomain->Grid); int i,il,iu,j,jl,ju,k,kl,ku; int shk_dir; /* Shock direction: {1,2,3} -> {x1,x2,x3} */ Real x1,x2,x3; Prim1DS Wl, Wr; Cons1DS U1d, Ul, Ur; Real Bxl=0.0, Bxr=0.0; /* Parse left state read from input file: dl,pl,ul,vl,wl,bxl,byl,bzl */ Wl.d = par_getd("problem","dl"); #ifdef ADIABATIC Wl.P = par_getd("problem","pl"); #endif Wl.Vx = par_getd("problem","v1l"); Wl.Vy = par_getd("problem","v2l"); Wl.Vz = par_getd("problem","v3l"); #ifdef MHD Bxl = par_getd("problem","b1l"); Wl.By = par_getd("problem","b2l"); Wl.Bz = par_getd("problem","b3l"); #endif #if (NSCALARS > 0) Wl.r[0] = par_getd("problem","r[0]l"); #endif /* Parse right state read from input file: dr,pr,ur,vr,wr,bxr,byr,bzr */ Wr.d = par_getd("problem","dr"); #ifdef ADIABATIC Wr.P = par_getd("problem","pr"); #endif Wr.Vx = par_getd("problem","v1r"); Wr.Vy = par_getd("problem","v2r"); Wr.Vz = par_getd("problem","v3r"); #ifdef MHD Bxr = par_getd("problem","b1r"); Wr.By = par_getd("problem","b2r"); Wr.Bz = par_getd("problem","b3r"); if (Bxr != Bxl) ath_error(0,"[shkset1d] L/R values of Bx not the same\n"); #endif #if (NSCALARS > 0) Wr.r[0] = par_getd("problem","r[0]r"); #endif Ul = Prim1D_to_Cons1D(&Wl, &Bxl); Ur = Prim1D_to_Cons1D(&Wr, &Bxr); /* Parse shock direction */ shk_dir = par_geti("problem","shk_dir"); if (shk_dir != 1 && shk_dir != 2 && shk_dir != 3) { ath_error("[problem]: shk_dir = %d must be either 1,2 or 3\n",shk_dir); } /* Set up the index bounds for initializing the grid */ iu = pGrid->ie + nghost; il = pGrid->is - nghost; if (pGrid->Nx[1] > 1) { ju = pGrid->je + nghost; jl = pGrid->js - nghost; } else { ju = pGrid->je; jl = pGrid->js; } if (pGrid->Nx[2] > 1) { ku = pGrid->ke + nghost; kl = pGrid->ks - nghost; } else { ku = pGrid->ke; kl = pGrid->ks; } /* Initialize the grid including the ghost cells. Discontinuity is always * located at x=0, so xmin/xmax in input file must be set appropriately. */ switch(shk_dir) { /*--- shock in 1-direction ---------------------------------------------------*/ case 1: /* shock in 1-direction */ for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive and conserved variables to be L or R state */ if (x1 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = U1d.Mx; pGrid->U[k][j][i].M2 = U1d.My; pGrid->U[k][j][i].M3 = U1d.Mz; #ifdef MHD pGrid->B1i[k][j][i] = Bxl; pGrid->B2i[k][j][i] = U1d.By; pGrid->B3i[k][j][i] = U1d.Bz; pGrid->U[k][j][i].B1c = Bxl; pGrid->U[k][j][i].B2c = U1d.By; pGrid->U[k][j][i].B3c = U1d.Bz; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; /*--- shock in 2-direction ---------------------------------------------------*/ case 2: /* shock in 2-direction */ for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive variables to be L or R state */ if (x2 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = U1d.Mz; pGrid->U[k][j][i].M2 = U1d.Mx; pGrid->U[k][j][i].M3 = U1d.My; #ifdef MHD pGrid->B1i[k][j][i] = U1d.Bz; pGrid->B2i[k][j][i] = Bxl; pGrid->B3i[k][j][i] = U1d.By; pGrid->U[k][j][i].B1c = U1d.Bz; pGrid->U[k][j][i].B2c = Bxl; pGrid->U[k][j][i].B3c = U1d.By; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; /*--- shock in 3-direction ---------------------------------------------------*/ case 3: /* shock in 3-direction */ for (k=kl; k<=ku; k++) { for (j=jl; j<=ju; j++) { for (i=il; i<=iu; i++) { cc_pos(pGrid, i, j, k, &x1, &x2, &x3); /* set primitive variables to be L or R state */ if (x3 <= 0.0) { U1d = Ul; } else { U1d = Ur; } /* Initialize conserved (and with SR the primitive) variables in Grid */ pGrid->U[k][j][i].d = U1d.d; pGrid->U[k][j][i].M1 = U1d.My; pGrid->U[k][j][i].M2 = U1d.Mz; pGrid->U[k][j][i].M3 = U1d.Mx; #ifdef MHD pGrid->B1i[k][j][i] = U1d.By; pGrid->B2i[k][j][i] = U1d.Bz; pGrid->B3i[k][j][i] = Bxl; pGrid->U[k][j][i].B1c = U1d.By; pGrid->U[k][j][i].B2c = U1d.Bz; pGrid->U[k][j][i].B3c = Bxl; #endif #ifdef ADIABATIC pGrid->U[k][j][i].E = U1d.E; #endif #if (NSCALARS > 0) pGrid->U[k][j][i].s[0] = U1d.s[0]; #endif } } } break; default: ath_error("[shkset1d]: invalid shk_dir = %i\n",shk_dir); } return; }
/*! \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;