static void func_1d_gnr(FTYPE x[], FTYPE dx[], FTYPE resid[], FTYPE jac[][NEWT_DIM], FTYPE *f, FTYPE *df, int n) { FTYPE vsq,W,W0,dpdW,Wsq,W3,p_tmp,dWdvsq , dpdvsq, fact_tmp ; int retval, iters; static void func_1d_gnr2(FTYPE x[], FTYPE dx[], FTYPE resid[], FTYPE jac[][NEWT_DIM], FTYPE *f, FTYPE *df, int n); static int gnr2( FTYPE x[], int n, void (*funcd) (FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *, FTYPE *, int) ); static FTYPE dpdvsq_calc(FTYPE W, FTYPE vsq); vsq = x[0]; // Calculate best value for W given current guess for vsq: vsq_for_gnr2 = vsq; W0 = W_for_gnr; retval = 1 ; iters = 0; while ( (retval != 0) && (++iters < 6) ) { x[0] = W0; retval = gnr2( x, 1, func_1d_gnr2 ) ; W0 *= 10.; } W = W_for_gnr = x[0]; Wsq = W*W; W3 = W*Wsq; x[0] = vsq; dpdW = dpdW_calc_vsq( W, vsq ); dpdvsq = dpdvsq_calc( W, vsq ); dWdvsq = ( dpdvsq - 0.5*Bsq ) / ( 1. - dpdW + QdotBsq/W3 ) ; fact_tmp = (Bsq + W) ; resid[0] = Qtsq - vsq * fact_tmp * fact_tmp + QdotBsq * ( Bsq + 2.*W ) / Wsq ; jac[0][0] = -fact_tmp * ( fact_tmp + 2. * dWdvsq * ( vsq + QdotBsq/W3 ) ) ; dx[0] = -resid[0]/jac[0][0]; *f = 0.5*resid[0]*resid[0]; *df = -2. * (*f); }
//isentropic version: eq. (27) static void func_1d_orig1(FTYPE x[], FTYPE dx[], FTYPE resid[], FTYPE jac[][NEWT_DIM], FTYPE *f, FTYPE *df, int n) { int retval, ntries; FTYPE Dc, t1, t10, t2 , t21, t23, t26, t29, t3 , t30; FTYPE t32, t33, t34, t38, t5 , t51, t67, t8, W, x_rho[1], rho, rho_g ; W = x[0]; W_for_gnr2_old = W_for_gnr2; W_for_gnr2 = W; // get rho from NR: rho_g = x_rho[0] = rho_for_gnr2; ntries = 0; while ( (retval = gnr2( x_rho, 1, func_gnr2_rho)) && ( ntries++ < 10 ) ) { rho_g *= 10.; x_rho[0] = rho_g; } #if(LTRACE) if( x_rho[0] <= 0. ) { fprintf(stderr,"gnr2 neg rho = %d ,rho_n,rho,rho_o,W,W_o = %26.20e %26.20e %26.20e %26.20e %26.20e \n", retval, x_rho[0], rho_for_gnr2, rho_for_gnr2_old, x[0], W_for_gnr2_old); fflush(stderr); } if( retval ) { fprintf(stderr,"gnr2 retval = %d ,rho_n,rho,rho_o,W,W_o = %26.20e %26.20e %26.20e %26.20e %26.20e \n", retval, x_rho[0], rho_for_gnr2, rho_for_gnr2_old, x[0], W_for_gnr2_old); fflush(stderr); } #endif rho_for_gnr2_old = rho_for_gnr2; rho = rho_for_gnr2 = x_rho[0]; Dc = D; t1 = Dc*Dc; t2 = QdotBsq*t1; t3 = t2*Bsq; t5 = Bsq*Bsq; t8 = t1*Bsq; t10 = t1*W; t21 = W*W; t23 = rho*rho; t26 = 1/t1; resid[0] = (t3+(2.0*t2+((Qtsq-t5)*t1 +(-2.0*t8-t10)*W)*W)*W+(t5+(2.0*Bsq+W)*W)*t21*t23)*t26/t21; t29 = t1*t1; t30 = QdotBsq*t29; t32 = GAMMA*K_atm; t33 = pow(rho,1.0*GAMMA); t34 = t32*t33; t38 = t23 * t33; t51 = GAMMA*t1*K_atm*t33; t67 = t21*W; jac[0][0] = -2.0*(t30*Bsq*t34+(t30*t34 +((-t38*Bsq*t32+Bsq*GAMMA*t1*K_atm*t33)*t1 +(-t38*GAMMA*K_atm+t51)*t1*W)*t21)*W +((-t3+(-t2+(-t8-t10)*t21)*W)*W+(-t5-Bsq*W)*t67*t23)*t23)*t26/(t51-W*t23)/t67; dx[0] = -resid[0]/jac[0][0]; *f = 0.5*resid[0]*resid[0]; *df = -2. * (*f); return; }
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_gnr(FTYPE x[], FTYPE dx[], FTYPE resid[], FTYPE jac[][NEWT_DIM], FTYPE *f, FTYPE *df, int n); static void func_1d_gnr2(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) ); static int gnr2( 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, 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 ; // 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++; } // Initialize independent variables for Newton-Raphson: W_for_gnr = W_last; x_1d[0] = vsq_for_gnr2 = 1. - 1. / gammasq ; // Find vsq via Newton-Raphson: retval = general_newton_raphson( x_1d, 1, func_1d_gnr) ; // Find W from this vsq: vsq_for_gnr2 = x_1d[0] ; x_1d[0] = W_for_gnr; retval2 = gnr2( x_1d, 1, func_1d_gnr2 ) ; W = x_1d[0]; retval += retval2 ; /* 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 : vsq = vsq_calc(W) ; 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) ; }