static int Utoprim_new_body( FTYPE U[NPR], FTYPE gcov[NDIM][NDIM], FTYPE gcon[NDIM][NDIM], FTYPE gdet, FTYPE prim[NPR]) { static void func_1d_dbl( FTYPE x[], FTYPE dx[], FTYPE resid[], FTYPE jac[][NEWT_DIM], FTYPE *f, FTYPE *df, int n); static int general_newton_raphson( FTYPE x[], int n, void (*funcd) (FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *, FTYPE *, int) ); FTYPE x_1d[1]; FTYPE QdotB,Bcon[NDIM],Bcov[NDIM],Qcov[NDIM],Qcon[NDIM],ncov[NDIM],ncon[NDIM],Qsq,Qtcon[NDIM]; FTYPE rho0,u,p,w,gammasq,gamma,gtmp,W_last,W,utsq,vsq,tmpdiff ; int i,j, retval, i_increase ; // Assume ok initially: retval = 0; for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; // Calculate various scalars (Q.B, Q^2, etc) from the conserved variables: Bcon[0] = 0. ; for(i=1;i<4;i++) Bcon[i] = U[BCON1+i-1] ; lower_g(Bcon,gcov,Bcov) ; for(i=0;i<4;i++) Qcov[i] = U[QCOV0+i] ; raise_g(Qcov,gcon,Qcon) ; Bsq = 0. ; for(i=1;i<4;i++) Bsq += Bcon[i]*Bcov[i] ; QdotB = 0. ; for(i=0;i<4;i++) QdotB += Qcov[i]*Bcon[i] ; QdotBsq = QdotB*QdotB ; ncov_calc(gcon,ncov) ; raise_g(ncov,gcon,ncon); Qdotn = Qcon[0]*ncov[0] ; Qsq = 0. ; for(i=0;i<4;i++) Qsq += Qcov[i]*Qcon[i] ; Qtsq = Qsq + Qdotn*Qdotn ; D = Dc = U[RHO] ; Ec = -Qdotn; Ssq = QdotBsq; igam1 = (GAMMA - 1.)/GAMMA ; /* calculate W from last timestep and use for guess */ utsq = 0. ; for(i=1;i<4;i++) for(j=1;j<4;j++) utsq += gcov[i][j]*prim[UTCON1+i-1]*prim[UTCON1+j-1] ; if( (utsq < 0.) && (fabs(utsq) < 1.0e-13) ) { utsq = fabs(utsq); } if(utsq < 0. || utsq > UTSQ_TOO_BIG) { retval = 2; return(retval) ; } gammasq = 1. + utsq ; gamma = sqrt(gammasq); // Always calculate rho from D and gamma so that using D in EOS remains consistent // i.e. you don't get positive values for dP/d(vsq) . rho0 = D / gamma ; u = prim[UU] ; p = pressure_rho0_u(rho0,u) ; w = rho0 + u + p ; W_last = w*gammasq ; // Make sure that W is large enough so that v^2 < 1 : i_increase = 0; while( (( W_last*W_last*W_last * ( W_last + 2.*Bsq ) - QdotBsq*(2.*W_last + Bsq) ) <= W_last*W_last*(Qtsq-Bsq*Bsq)) && (i_increase < 10) ) { W_last *= 10.; i_increase++; } // METHOD specific: Wc = W_last; x_1d[0] = 1. - 1. / gammasq ; // Find vsq : retval = general_newton_raphson( x_1d, 1, func_1d_dbl ) ; // Find W from this vsq: vsq = x_1d[0] ; W = Wc; /* Problem with solver, so return denoting error before doing anything further */ if( (retval != 0) || (W == FAIL_VAL) ) { retval = retval*100+1; return(retval); } else{ if(W <= 0. || W > W_TOO_BIG) { retval = 3; return(retval) ; } } // Calculate utsq // calculated from above: if( vsq >= 1. ) { retval = 4; return(retval) ; } // Recover the primitive variables from the scalars and conserved variables: gtmp = sqrt(1. - vsq); gamma = 1./gtmp ; rho0 = D * gtmp; w = W * (1. - vsq) ; p = pressure_rho0_w(rho0,w) ; u = w - (rho0 + p) ; // User may want to handle this case differently, e.g. do NOT return upon // a negative rho/u, calculate v^i so that rho/u can be floored by other routine: if( (rho0 <= 0.) || (u <= 0.) ) { retval = 5; return(retval) ; } prim[RHO] = rho0 ; prim[UU] = u ; for(i=1;i<4;i++) Qtcon[i] = Qcon[i] + ncon[i] * Qdotn; for(i=1;i<4;i++) prim[UTCON1+i-1] = gamma/(W+Bsq) * ( Qtcon[i] + QdotB*Bcon[i]/W ) ; /* set field components */ for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; /* done! */ return(retval) ; }
static int Utoprim_new_body(FTYPE U[NPR], FTYPE gcov[NDIM][NDIM], FTYPE gcon[NDIM][NDIM], FTYPE gdet, FTYPE prim[NPR]) { FTYPE x_2d[NEWT_DIM]; FTYPE QdotB,Bcon[NDIM],Bcov[NDIM],Qcov[NDIM],Qcon[NDIM],ncov[NDIM],ncon[NDIM],Qsq,Qtcon[NDIM]; FTYPE rho0,u,p,w,gammasq,gamma,gtmp,W_last,W,utsq,vsq,tmpdiff ; int i,j, n, retval, i_increase ; FTYPE local_Bsq,local_QdotBsq,local_Qtsq,local_Qdotn,local_D ; // added by jdsteve2 for OpenMP n = NEWT_DIM ; // Assume ok initially: retval = 0; for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; // Calculate various scalars (Q.B, Q^2, etc) from the conserved variables: Bcon[0] = 0. ; for(i=1;i<4;i++) Bcon[i] = U[BCON1+i-1] ; lower_g(Bcon,gcov,Bcov) ; for(i=0;i<4;i++) Qcov[i] = U[QCOV0+i] ; raise_g(Qcov,gcon,Qcon) ; local_Bsq = 0. ; for(i=1;i<4;i++) local_Bsq += Bcon[i]*Bcov[i] ; QdotB = 0. ; for(i=0;i<4;i++) QdotB += Qcov[i]*Bcon[i] ; local_QdotBsq = QdotB*QdotB ; ncov_calc(gcon,ncov) ; raise_g(ncov,gcon,ncon); local_Qdotn = Qcon[0]*ncov[0] ; Qsq = 0. ; for(i=0;i<4;i++) Qsq += Qcov[i]*Qcon[i] ; local_Qtsq = Qsq + local_Qdotn*local_Qdotn ; local_D = U[RHO] ; /* calculate W from last timestep and use for guess */ utsq = 0. ; for(i=1;i<4;i++) for(j=1;j<4;j++) utsq += gcov[i][j]*prim[UTCON1+i-1]*prim[UTCON1+j-1] ; if( (utsq < 0.) && (fabs(utsq) < 1.0e-13) ) { utsq = fabs(utsq); } if(utsq < 0. || utsq > UTSQ_TOO_BIG) { retval = 2; return(retval) ; } gammasq = 1. + utsq ; gamma = sqrt(gammasq); // Always calculate rho from D and gamma so that using D in EOS remains consistent // i.e. you don't get positive values for dP/d(vsq) . rho0 = local_D / gamma ; u = prim[UU] ; p = pressure_rho0_u(rho0,u) ; w = rho0 + u + p ; W_last = w*gammasq ; // Make sure that W is large enough so that v^2 < 1 : i_increase = 0; while( (( W_last*W_last*W_last * ( W_last + 2.*local_Bsq ) - local_QdotBsq*(2.*W_last + local_Bsq) ) <= W_last*W_last*(local_Qtsq-local_Bsq*local_Bsq)) && (i_increase < 10) ) { W_last *= 10.; i_increase++; } // Calculate W and vsq: x_2d[0] = fabs( W_last ); x_2d[1] = x1_of_x0_omp( W_last, local_Bsq, local_QdotBsq, local_Qtsq ) ; // modified by jdsteve2 retval = general_newton_raphson_omp( x_2d, n, func_vsq_omp, local_Bsq, local_QdotBsq, local_Qtsq, local_Qdotn, local_D) ; W = x_2d[0]; vsq = x_2d[1]; /* Problem with solver, so return denoting error before doing anything further */ if( (retval != 0) || (W == FAIL_VAL) ) { retval = retval*100+1; return(retval); } else{ if(W <= 0. || W > W_TOO_BIG) { retval = 3; return(retval) ; } } // Calculate v^2: if( vsq >= 1. ) { retval = 4; return(retval) ; } // Recover the primitive variables from the scalars and conserved variables: gtmp = sqrt(1. - vsq); gamma = 1./gtmp ; rho0 = local_D * gtmp; w = W * (1. - vsq) ; p = pressure_rho0_w(rho0,w) ; u = w - (rho0 + p) ; // User may want to handle this case differently, e.g. do NOT return upon // a negative rho/u, calculate v^i so that rho/u can be floored by other routine: if( (rho0 <= 0.) || (u <= 0.) ) { retval = 5; return(retval) ; } prim[RHO] = rho0 ; prim[UU] = u ; for(i=1;i<4;i++) Qtcon[i] = Qcon[i] + ncon[i] * local_Qdotn; for(i=1;i<4;i++) prim[UTCON1+i-1] = gamma/(W+local_Bsq) * ( Qtcon[i] + QdotB*Bcon[i]/W ) ; /* set field components */ for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; /* done! */ return(retval) ; }
static int Utoprim_new_body(FTYPE U[NPR], struct of_geom *ptrgeom, FTYPE prim[NPR]) { FTYPE Wtest; FTYPE x_1d[1]; FTYPE QdotB,Bcon[4],Bcov[4],Qcov[4],Qcon[4],ncov[4],ncon[4],Qsq,Qtcon[4]; FTYPE rho0,u,p,w,gammasq,gamma,gtmp,W_last,W,utsq,vsq,tmpdiff ; int i,j, retval, retval2, i_increase ; static void raise_g(FTYPE vcov[], FTYPE gcon[][4], FTYPE vcon[]); static void lower_g(FTYPE vcon[], FTYPE gcov[][4], FTYPE vcov[]); static void ncov_calc(FTYPE gcon[][4],FTYPE ncov[]) ; static FTYPE pressure_rho0_u(FTYPE rho0, FTYPE u); static FTYPE pressure_rho0_w(FTYPE rho0, FTYPE w); static int find_root_2D_gen(FTYPE x0, FTYPE *xnew) ; const int ltrace = 0; const int ltrace2 = 0; /* TEMPORARY */ /* primtoU_g(prim,gcov,gcon,U) ; */ #if(!OPTIMIZED) if( ltrace ) { for(i=0;i<8;i++) dualfprintf(fail_file,"%d %21.15g %21.15g\n",i,prim[i],U[i]) ; } #endif // Assume ok initially: pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMNOFAIL; for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; Bcon[0] = 0. ; for(i=1;i<4;i++) Bcon[i] = U[BCON1+i-1] ; lower_g(Bcon,ptrgeom->gcov,Bcov) ; for(i=0;i<4;i++) Qcov[i] = U[QCOV0+i] ; raise_g(Qcov,ptrgeom->gcon,Qcon) ; Bsq = 0. ; for(i=1;i<4;i++) Bsq += Bcon[i]*Bcov[i] ; QdotB = 0. ; for(i=0;i<4;i++) QdotB += Qcov[i]*Bcon[i] ; QdotBsq = QdotB*QdotB ; ncov_calc(ptrgeom->gcon,ncov) ; raise_g(ncov,ptrgeom->gcon,ncon); Qdotn = Qcon[0]*ncov[0] ; Qsq = 0. ; for(i=0;i<4;i++) Qsq += Qcov[i]*Qcon[i] ; Qtsq = Qsq + Qdotn*Qdotn ; D = U[RHO] ; /* calculate W from last timestep and use for guess */ utsq = 0. ; for(i=1;i<4;i++) for(j=1;j<4;j++) utsq += ptrgeom->gcov[i][j]*prim[UTCON1+i-1]*prim[UTCON1+j-1] ; if( (utsq < 0.) && (fabs(utsq) < MAXNEGUTSQ) ) { utsq = 0.0; } if(utsq < 0. || utsq > UTSQ_TOO_BIG) { if( debugfail>=2 ) dualfprintf(fail_file,"Utoprim_new(): utsq < 0 in utoprim_1d attempt, utsq = %21.15g \n", utsq) ; pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILCONVUTSQ; return(1) ; } gammasq = 1. + utsq ; gamma = sqrt(gammasq); // Always calculate rho from D and gamma so that using D in EOS remains consistent // i.e. you don't get positive values for dP/d(vsq) . rho0 = D / gamma ; u = prim[UU] ; p = pressure_rho0_u(rho0,u) ; w = rho0 + u + p ; W_last = w*gammasq ; // Make sure that W is large enough so that v^2 < 1 : i_increase = 0; while( (( W_last*W_last*W_last * ( W_last + 2.*Bsq ) - QdotBsq*(2.*W_last + Bsq) ) <= W_last*W_last*(Qtsq-Bsq*Bsq)) && (i_increase < 10) ) { W_last *= 10.; i_increase++; #if(!OPTIMIZED) dualfprintf(fail_file,"badval : W = %21.15g, i_increase = %d \n", W_last, i_increase); #endif } #if(!OPTIMIZED) if( i_increase >= 10 ) { dualfprintf(fail_file,"i_increase is too large, i_increase = %d , W = %21.15g \n", i_increase, W_last); } #endif #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file,"u = %21.15g, p = %21.15g, Bsq = %21.15g, Qsq = %21.15g \n",u,p,Bsq,Qsq); dualfprintf(fail_file,"Bcon[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Bcon[0],Bcon[1],Bcon[2],Bcon[3]); dualfprintf(fail_file,"Bcov[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Bcov[0],Bcov[1],Bcov[2],Bcov[3]); dualfprintf(fail_file,"Qcon[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Qcon[0],Qcon[1],Qcon[2],Qcon[3]); dualfprintf(fail_file,"Qcov[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Qcov[0],Qcov[1],Qcov[2],Qcov[3]); dualfprintf(fail_file,"call find_root\n") ; } #endif // METHOD specific: wglobal=w; // used to validate normalized version of W retval = find_root_2D_gen(W_last, &W) ; /* Problem with solver, so return denoting error before doing anything further */ if( (retval != 0) || (W == FAIL_VAL) ) { if( debugfail>=2 ) { dualfprintf(fail_file, "Failed to find a prim. var. solution!! %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g \n",W_last,Bsq,QdotBsq,Qdotn,D,Qtsq); dualfprintf(fail_file, "Utoprim_new_body(): bad newt failure, t,i,j, p[0-7], U[0-7] = %21.15g %d %d ", t, ptrgeom->i, ptrgeom->j ); for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", prim[i]); } for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", U[i]); } dualfprintf(fail_file, "\n"); } pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= retval*100+1;// related to UTOPRIMFAILCONVRET return(retval); } else{ Wtest=W/wglobal; // normalize to old densities if(Wtest <= 0. || Wtest > GAMMASQ_TOO_BIG) { //if(Wtest <= 0.) { if( debugfail>=2 ) { dualfprintf(fail_file,"Wtest failure %21.15g \n",Wtest) ; dualfprintf(fail_file, "Utoprim_new_body(): Wtest<0 or Wtest=toobig failure, t,i,j, p[0-7], U[0-7] = %21.15g %d %d ", t, ptrgeom->i, ptrgeom->j ); for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", prim[i]); } for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", U[i]); } dualfprintf(fail_file, "\n"); } pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILCONVW; return(retval) ; } } #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file,"(W,W_last,Bsq,Qtsq,QdotB,gammasq,Qdotn) %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g\n", W,W_last, Bsq,Qtsq,QdotB,gammasq,Qdotn) ; dualfprintf(fail_file,"done find_root\n") ; } if( ltrace2 ) { dualfprintf(fail_file, "\n <--------- %21.15g %21.15g %21.15g %21.15g %21.15g \n", Bsq,QdotBsq,Qdotn,D,Qtsq); } #endif /* if( nstep == 3 ) { if( ((ptrgeom->i==89) && (ptrgeom->j==88||ptrgeom->j==111)) || (ptrgeom->i==92&&(ptrgeom->j==86||ptrgeom->j==113)) || (ptrgeom->i==92&&(ptrgeom->j==86||ptrgeom->j==113) ) || (ptrgeom->i==94&&(ptrgeom->j==84||ptrgeom->j==115) ) || (ptrgeom->i==105&&(ptrgeom->j==84||ptrgeom->j==115) ) || (ptrgeom->i==107&&(ptrgeom->j==86||ptrgeom->j==113) ) || (ptrgeom->i==110&&(ptrgeom->j==88||ptrgeom->j==111) ) ) { dualfprintf(fail_file, "\n <--------- %21.15g %21.15g %21.15g %21.15g %21.15g \n", Bsq,QdotBsq,Qdotn,D,Qtsq); } } */ // Calculate vsq vsq = vsq_calc(W) ; if( (vsq < 0.) && (fabs(vsq) < MAXNEGVSQ) ) { vsq = 0.0; } // no check for vsq>1 since looking for failure to fix that's not just simple like above //else if(vsq>=1.0){ // if(vsq<1.0+MAXNEGVSQ) vsq=VSQ_TOO_BIG; // } if( (vsq > VSQ_TOO_BIG)||(vsq<0.0) ) { if( debugfail>=2 ) { dualfprintf(fail_file,"vsq failure: vsq = %21.15g , W = %21.15g \n",vsq, W) ; dualfprintf(fail_file, "Utoprim_new_body(): utsq==bad failure, t,i,j, p[0-7], U[0-7] = %21.15g %d %d ", t, ptrgeom->i, ptrgeom->j ); for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", prim[i]); } for( i = 0 ; i < NPR; i++ ) { dualfprintf(fail_file, "%21.15g ", U[i]); } dualfprintf(fail_file, "\n"); } pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILCONVUTSQ2; return(retval) ; } gtmp = sqrt(1. - vsq); gamma = 1./gtmp ; rho0 = D * gtmp; w = W * (1. - vsq) ; p = pressure_rho0_w(rho0,w) ; u = w - (rho0 + p) ; if( (rho0 <= 0.) || (u < 0.) ) { if( debugfail>=2 ) { tmpdiff = w - rho0; dualfprintf(fail_file, "rho or uu < 0 failure: rho,w,(w-rho),p,u = %21.15g %21.15g %21.15g %21.15g %21.15g \n", rho0,w,tmpdiff,p,u) ; dualfprintf(fail_file, "rho or uu < 0 failure: gamma,utsq = %21.15g %21.15g \n", gamma, utsq) ; } if((rho0<=0.)&&(u>=0.)) pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILRHONEG; if((rho0>0.)&&(u<0.)) pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILUNEG; if((rho0<=0.)&&(u<0.)) pflag[ptrgeom->i][ptrgeom->j][FLAGUTOPRIMFAIL]= UTOPRIMFAILRHOUNEG; if(UTOPRIMFAILRETURNTYPE==UTOPRIMRETURNNOTADJUSTED) return(retval) ; // else let assign -- used to check how bad failure is. } prim[RHO] = rho0 ; prim[UU] = u ; for(i=1;i<4;i++) Qtcon[i] = Qcon[i] + ncon[i] * Qdotn; for(i=1;i<4;i++) prim[UTCON1+i-1] = gamma/(W+Bsq) * ( Qtcon[i] + QdotB*Bcon[i]/W ) ; /* set field components */ for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file," rho final = %21.15g , u final = %21.15g \n", rho0, u); } #endif /* done! */ return(retval) ; }