// shouldn't use this function since not optimized to avoid catastrophic cancellations static void primtoU_g(struct of_geom *ptrgeom, FTYPE *prim,FTYPE gcov[SYMMATRIXNDIM],FTYPE gcon[SYMMATRIXNDIM],FTYPE *U) { int i,j ; FTYPE rho0 ; FTYPE ucon[NDIM],ucov[NDIM],bcon[NDIM],bcov[NDIM],ncov[NDIM] ; FTYPE gamma,n_dot_b,bsq,u,p,w ; /* preliminaries */ ucon_calc_g(prim,gcov,gcon,ucon) ; lower_g(ucon,gcov,ucov) ; ncov_calc(gcon,ncov) ; gamma = -ncov[0]*ucon[0] ; bcon_calc_g(prim,ucon,ucov,ncov,bcon) ; lower_g(bcon,gcov,bcov) ; n_dot_b = 0. ; for(i=0;i<NDIM;i++) n_dot_b += ncov[i]*bcon[i] ; bsq = 0. ; for(i=0;i<NDIM;i++) bsq += bcov[i]*bcon[i] ; rho0 = prim[RHO] ; u = prim[UU] ; p = pressure_rho0_u_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,rho0,u) ; w = rho0 + u + p ; U[RHO] = gamma*rho0 ; for(i=0;i<NDIM;i++) U[QCOV0+i] = gamma*(w + bsq)*ucov[i] - (p + bsq/2.)*ncov[i] + n_dot_b*bcov[i] ; U[BCON1] = prim[BCON1] ; U[BCON2] = prim[BCON2] ; U[BCON3] = prim[BCON3] ; return ; }
static int Utoprim_new_body(FTYPE U[NPR], FTYPE gcov[NDIM][NDIM], FTYPE gcon[NDIM][NDIM], FTYPE gdet, FTYPE prim[NPR]) { 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,aco, bco, cco, pevar, agame, the; FTYPE alpha, ucovt, utsqp1; FTYPE dummy; int i,j, retval, retval2, 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 = 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 = D / gamma ; u = prim[UU] ; p = pressure_rho0_u(rho0,u) ; w = rho0 + u + p ; W_last = w*gammasq ; // Initialize independent variables for Newton-Raphson: x_1d[0] = 1. - 1. / gammasq ; // Find vsq via Newton-Raphson: retval = general_newton_raphson( x_1d, 1, func_1d_gnr) ; /* Problem with solver, so return denoting error before doing anything further */ if( retval != 0 ) { retval = retval*100+1; return(retval); } // Calculate v^2 : vsq = x_1d[0]; if( (vsq >= 1.) || (vsq < 0.) ) { retval = 4; return(retval) ; } // Find W from this vsq: W = W_of_vsq(vsq, &p, &rho0, &u); // Recover the primitive variables from the scalars and conserved variables: gtmp = sqrt(1. - vsq); gamma = 1./gtmp ; w = W * (1. - vsq) ; // 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 *pressure) { FTYPE Wtest; // extern void func_1d_orig(FTYPE x[1], FTYPE dx[1], FTYPE *f, FTYPE *df, int n); // extern FTYPE Bsq,QdotBsq,Qtsq,Qdotn,D ; FTYPE x_1d[1]; FTYPE gcov[SYMMATRIXNDIM], gcon[SYMMATRIXNDIM]; FTYPE QdotB,Bcon[4],Bcov[4],Qcov[4],Qcon[4],ncov[4],ncon[4],Qsq,Qtcon[4]; FTYPE rho0,u,p,w,gammasq,gamma,W_last,W,utsq ; int i,j, ret, errval ; FTYPE Ui[8],primi[8]; const int ltrace = 0; const int ltrace2 = 0; if( ltrace ) { for(i=0;i<8;i++) fprintf(stdout,"%d %21.15g %21.15g\n",i,prim[i],U[i]) ; fflush(stdout); } // Assume ok initially: *glpflag= UTOPRIMNOFAIL; for(i = 0; i < NDIM; i++ ) { for(j = 0; j < NDIM; j++ ) { gcov[GIND(i,j)] = ptrgeom->gcov[GIND(i,j)]; gcon[GIND(i,j)] = ptrgeom->gcon[GIND(i,j)]; } } /* save guess and prims */ for(i=0;i<8;i++) Ui[i] = U[i] ; for(i=0;i<8;i++) primi[i] = prim[i] ; /* set field components */ for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; /* Set parameters based upoon the conservative 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 = U[RHO] ; utsq = 0. ; for(i=1;i<4;i++) for(j=1;j<4;j++) utsq += gcov[GIND(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 ) { if( debugfail>=2 ) dualfprintf(fail_file,"Utoprim_new1(): utsq < 0 in utoprim_1d attempt, utsq = %21.15g \n", utsq) ; *glpflag= UTOPRIMFAILCONVGUESSUTSQ; return(0) ; } rho0 = prim[RHO] ; u = prim[UU] ; p = pressure_rho0_u_2d(rho0,u) ; *pressure=p; w = rho0 + u + p ; gammasq = 1. + utsq ; W_last = w*gammasq ; if( ltrace ) { fprintf(stdout,"u = %21.15g, p = %21.15g, Bsq = %21.15g, Qsq = %21.15g \n",prim[RHO],prim[UU],Bsq,Qsq); fprintf(stdout,"Bcon[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Bcon[0],Bcon[1],Bcon[2],Bcon[3]); fprintf(stdout,"Bcov[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Bcov[0],Bcov[1],Bcov[2],Bcov[3]); fprintf(stdout,"Qcon[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Qcon[0],Qcon[1],Qcon[2],Qcon[3]); fprintf(stdout,"Qcov[0-3] = %21.15g %21.15g %21.15g %21.15g \n", Qcov[0],Qcov[1],Qcov[2],Qcov[3]); fprintf(stdout,"call find_root\n") ; fflush(stdout); fflush(stdout); } W = W_last; wglobal=w; ret = find_root_2D_gen( &W ) ; if( ltrace ) { fprintf(stderr,"(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) ; } if( ltrace2 ) { fprintf(stdout, "\n <--------- %21.15g %21.15g %21.15g %21.15g %21.15g \n", Bsq,QdotBsq,Qdotn,D,Qtsq); fflush(stdout); } /* Problem with solver, so return denoting error before doing anything further */ if( (ret != 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); *glpflag= ret+UTOPRIMFAILCONVRET+1; // related to UTOPRIMFAILCONVRET return(0); } else{ Wtest=W/wglobal; if(Wtest <= 0. || Wtest > W_TOO_BIG) { //if(Wtest <= 0.) { if( debugfail>=2 ) dualfprintf(fail_file,"Wtest failure %21.15g \n",Wtest) ; *glpflag= UTOPRIMFAILCONVW; return(0) ; } // below test for UTSQ_TOO_BIG is good normalized version of the above unnormalized W test. utsq = utsq_calc(W) ; if( (utsq < 0.) && (fabs(utsq) < 1.0e-13) ) { utsq = fabs(utsq); } if(utsq < 0. || utsq > UTSQ_TOO_BIG) { if( debugfail>=2 ) dualfprintf(fail_file,"utsq failure: utsq = %21.15g , W = %21.15g \n",utsq, W) ; *glpflag= UTOPRIMFAILCONVUTSQ; return(0) ; } } if( ltrace ) { fprintf(stdout,"done find_root\n") ; fflush(stdout); } /* Past all checks, so now use good result to find final values of all primitive variables */ gamma = sqrt(1. + utsq) ; rho0 = D/gamma ; w = W/(gamma*gamma) ; p = pressure_rho0_w_2d(rho0,w) ; u = w - (rho0 + p) ; if( (rho0 <= 0.) || (u <= 0.) ) { if( debugfail>=2 ) dualfprintf(fail_file,"utsq failure: utsq = %21.15g , W = %21.15g \n",utsq, W) ; if((rho0<=0.)&&(u>=0.)) *glpflag= UTOPRIMFAILRHONEG; if((rho0>=0.)&&(u<=0.)) *glpflag= UTOPRIMFAILUNEG; if((rho0<=0.)&&(u<=0.)) *glpflag= UTOPRIMFAILRHOUNEG; if(UTOPRIMFAILRETURNTYPE==UTOPRIMRETURNNOTADJUSTED) return(0) ; // 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*Qtcon[i]/(W + Bsq) - gamma*QdotB*Bcon[i]/(W*(W + Bsq)) ; for(i = BCON1; i <= BCON3; i++) prim[i] = U[i] ; if( ltrace ) { fprintf(stdout," rho final = %21.15g , u final = %21.15g \n", rho0, u); } /* done! */ return(0) ; }
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_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 ; FTYPE alpha, ucovt, utsqp1, aco, bco, cco, pevar, agame, the, utt; int i,j, retval, i_increase ; double dummy; // 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 = 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 = D / gamma ; p = pressure_of_rho( rho0 ); u = u_of_p(p); w = rho0 + u + p ; #if(LTRACE) if( rho0 <= 0. ) { fprintf(stderr,"beg neg rho fix1, rho,D,gamma = %26.20e %26.20e %26.20e \n", rho0, D, gamma); fflush(stderr); rho0 = fabs(rho0); } #endif 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++; } W_for_gnr2 = W_for_gnr2_old = W_last; rho_for_gnr2 = rho_for_gnr2_old = rho0; // Calculate W: x_1d[0] = W_last; #if( USE_ISENTROPIC ) retval = general_newton_raphson( x_1d, 1, func_1d_orig1); #else retval = general_newton_raphson( x_1d, 1, func_1d_orig2); #endif W = x_1d[0]; /* Problem with solver, so return denoting error before doing anything further */ if( (retval != 0) || (W == FAIL_VAL) ) { retval = retval*100+1; #if(LTRACE) fprintf(stderr,"fix1: retval, W, rho = %d %26.20e %26.20e \n", retval,W, rho_for_gnr2);fflush(stderr); #endif return(retval); } else{ if(W <= 0. || W > W_TOO_BIG) { retval = 3; #if(LTRACE) fprintf(stderr,"fix1: retval, W, rho = %d %26.20e %26.20e \n", retval,W, rho_for_gnr2);fflush(stderr); #endif return(retval) ; } } // Calculate v^2 : vsq = vsq_calc(W) ; if( vsq >= 1. ) { retval = 4; #if(LTRACE) fprintf(stderr,"fix1: retval, W, rho,vsq = %d %26.20e %26.20e %26.20e \n", retval,W, rho_for_gnr2,vsq);fflush(stderr); #endif 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_of_rho( rho0 ); u = u_of_p(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; #if(LTRACE) fprintf(stderr,"fix1: retval, W, rho,vsq,u = %d %26.20e %26.20e %26.20e %26.20e \n", retval,W, rho0,vsq,u);fflush(stderr); #endif 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], 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) ; }