static int find_root_2D_gen(FTYPE *x0) { FTYPE x[2], x_orig[2]; int ntries = 0; int n = 2; int ret; const int ltrace = 0; // extern void func_gamma( FTYPE x[2], FTYPE dx[2], FTYPE *f, FTYPE *df, int n); // extern void func_vsq( FTYPE x[2], FTYPE dx[2], FTYPE *f, FTYPE *df, int n); // extern void func_utsq( FTYPE x[2], FTYPE dx[2], FTYPE *f, FTYPE *df, int n); /* Set presets: */ x_orig[0] = x[0] = fabs(*x0) ; x_orig[1] = x[1] = x1_of_x0( *x0, 3 ) ; if( ltrace ) { fprintf(stdout, "find_root_2D_gen(): x[0] = %21.15g , x[1] = %21.15g \n", x[0], x[1]); fflush(stdout); } ret = general_newton_raphson( x, n, func_vsq ); while( (ret != 0) && (ntries < MAX_NEWT_RETRIES ) ) { x[0] = x_orig[0] * (1. + 0.2*(1.*rand())/(1.*RAND_MAX) ); x[1] = x1_of_x0( x[0], 3 ) ; ntries++; } if( (ntries >= MAX_NEWT_RETRIES) && (MAX_NEWT_RETRIES > 0) ) { fprintf(stderr, "find_root_2D_gen(): Bad exit value from general_newton_raphson() !! \n"); fprintf(stderr, "find_root_2D_gen(): ntries = %d , x[0] = %21.15g , x[1] = %21.15g \n", ntries, x[0], x[1]); fflush(stderr); } if( ret != 0 ) { *x0 = FAIL_VAL; return( ret ); } *x0 = x[0]; return(0); }
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) ; }
/************************************************************ general_newton_raphson(): -- performs Newton-Rapshon method on an arbitrary system. -- inspired in part by Num. Rec.'s routine newt(); *****************************************************************/ static int general_newton_raphson( FTYPE x[], int n, int do_line_search, void (*funcd) (FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *, FTYPE *, int), FTYPE (*res_func) (FTYPE []) ) { FTYPE f, f_old, df, df_old, dx[NEWT_DIM], dx_old[NEWT_DIM], x_old[NEWT_DIM], resid[NEWT_DIM], jac[NEWT_DIM][NEWT_DIM]; FTYPE errx, errx_old, errx_oldest, x_orig[NEWT_DIM]; int n_iter, id, jd, i_extra, doing_extra; FTYPE randtmp, tmp; FTYPE dW,dvsq,vsq_old,vsq,W,W_old; FTYPE resid_norm, resid_check, grad_check; FTYPE res_func_val, res_func_old, res_func_new; FTYPE dn[NEWT_DIM], del_f[NEWT_DIM]; static void my_lnsrch(int, FTYPE [], FTYPE, FTYPE [], FTYPE [], FTYPE [], FTYPE *, FTYPE, FTYPE, int *, FTYPE (*res_func) (FTYPE [])); static void bin_newt_data( FTYPE errx, int niters, int conv_type, int print_now ) ; int keep_iterating, i_increase, retval2,retval = 0; const int ltrace = 0; const int ltrace2 = 1; retval = 0; errx = 1. ; errx_old = 2.; df = df_old = f = f_old = 1.; i_extra = doing_extra = 0; for( id = 0; id < n ; id++) x_old[id] = x_orig[id] = x[id] ; vsq_old = vsq = W = W_old = 0.; n_iter = 0; /* Start the Newton-Raphson iterations : */ keep_iterating = 1; while( keep_iterating ) { nstroke++; lntries++; (*funcd) (x, dx, resid, jac, &f, &df, n); /* returns with new dx, f, df */ #if(!OPTIMIZED) /* Check for bad untrapped divergences : */ if( (finite(f)==0) || (finite(df)==0) ) { if( debugfail >= 2 ) { dualfprintf(fail_file,"general_newton_raphson(): nan encountered in f or df!! \n"); dualfprintf(fail_file,"gnr nan(): f, df, x0, dx0 = %21.15g %21.15g %21.15g %21.15g \n", f,df,x[0],dx[0]); } return(1); } #endif #if(!OPTIMIZED) /* Randomly rescale Newton step to break out of iteration cycles: */ if( ((n_iter+1) % CYCLE_BREAK_PERIOD) == 0 ) { randtmp = ( (1.*rand())/(1.*RAND_MAX) ); for( id = 0; id < n ; id++) dx[id] *= randtmp; // for( id = 0; id < n ; id++) dx[id] *= ( (1.*rand())/(1.*RAND_MAX) ); } #endif /* Save old values before calculating the new: */ errx_oldest = errx_old; errx_old = errx; lerrx=errx; errx = 0.; f_old = f; for( id = 0; id < n ; id++) { x_old[id] = x[id] ; } /* Make the newton step: */ if( do_line_search == 1 ) { /* Compare the residual to its initial value */ if( n_iter == 0 ) { resid_norm = 0.0e0; for( id = 0; id < n ; id++) { resid_norm += fabs(resid[id]); } resid_norm /= 1.0*n ; if( resid_norm == 0.0 ) resid_norm = 1.0; } for( id = 0; id < n ; id++) { tmp = 0.; for( jd = 0; jd < n ; jd++) { tmp += jac[jd][id] * resid[jd]; } del_f[id] = tmp; } for( id = 0; id < n ; id++) { dn[id] = dx[id]; } my_lnsrch(n, x_old-1, f_old, del_f-1, dn-1, x-1, &f, TOL_LINE_STEP, SCALEMAX, &retval, res_func); /* dx is needed for errx calculation below: */ for( id = 0; id < n ; id++) { dx[id] = x[id] - x_old[id]; } #if(!OPTIMIZED) if( ltrace ) { res_func_val = res_func(x); res_func_old = res_func(x_old); dualfprintf(fail_file,"gnr(): f_old, f, res_func_old, res_func_val = %21.15g %21.15g %21.15g %21.15g \n", f_old, f, res_func_old, res_func_val ); dualfprintf(fail_file,"gnr(): x_old = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",x_old[id]); } dualfprintf(fail_file,"\n "); dualfprintf(fail_file,"gnr(): x = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",x[id]); } dualfprintf(fail_file,"\n "); dualfprintf(fail_file,"gnr(): dn = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",dn[id]); } dualfprintf(fail_file,"\n "); dualfprintf(fail_file,"gnr(): del_f = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",del_f[id]); } dualfprintf(fail_file,"\n "); } #endif /* Check to see if line search problem is because the residual vector is already small enough */ if( retval == 1 ) { resid_check = 0.0e0; for( id = 0; id < n ; id++) { resid_check += fabs(resid[id]); } resid_check /= 1.0*n; if( resid_check <= resid_norm * NEWT_FUNC_TOL ) { retval = 0; } if( ltrace && retval ) { dualfprintf(fail_file,"general_newton_raphson(): retval, resid_check = %4i %21.15g \n",retval, resid_check); } } /* If initial Newton step is bad, then try again without line searching: */ if( (retval == 2) && (USE_LINE_SEARCH == do_line_search) ) { #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file,"gnr(): bad first step: retval, f_old, f = %4i %21.15g %21.15g \n",retval,f_old,f); dualfprintf(fail_file,"gnr: doing recursive call, retval, errx = %4i %21.15g \n", retval, errx ); } #endif retval = general_newton_raphson( x_orig, n, ((do_line_search+1)%2), funcd, res_func ); for( id = 0; id < n ; id++) x[id] = x_orig[id] ; return( retval ); } /* Check to see if it is trapped in a local minimum, i.e. gradient is too small */ if( retval == 1 ) { grad_check = 0.0e0; for( id = 0; id < n ; id++) { resid_check = (x[id] == 0.) ? 1.0 : fabs(x[id]) ; grad_check += del_f[id] * resid_check ; } resid_check = (f == 0.) ? 1.0 : fabs(f) ; grad_check /= resid_check; /* Then we've most likely found a solution: */ if( grad_check > GRADMIN ) { retval = -1; } else if( ltrace ) { dualfprintf(fail_file,"general_newton_raphson(): retval, grad_check = %4i %21.15g \n",retval, grad_check); } } } else { /* don't use line search : */ for( id = 0; id < n ; id++) { x[id] += dx[id] ; } } /* End of "to do line search or not to do line search..." */ /****************************************/ /* Calculate the convergence criterion */ /****************************************/ /* For the new criterion, always look at error in "W" : */ // METHOD specific: #if( NEWCONVERGE == 1 ) errx = (x[0]==0.) ? fabs(dx[0]) : fabs(dx[0]/x[0]); /* For the old criterion, look at errors in each indep. variable(s) (except for 5D) : */ #else for( id = 0; id < n ; id++) { errx += (x[id]==0.) ? fabs(dx[id]) : fabs(dx[id]/x[id]); } errx /= 1.*n; #endif /****************************************/ /* Make sure that the new x[] is physical : */ /****************************************/ // METHOD specific: validate_x( x, x_old ) ; /****************************************/ /* Check to see if we're in a infinite loop with error function: */ /****************************************/ #if( CHECK_FOR_STALL ) if( ( (errx_old == errx) || (errx_oldest == errx) ) && (errx <= MIN_NEWT_TOL) ) errx = -errx; #endif /****************************************/ /* If there's a problem with line search, then stop iterating: */ /****************************************/ if( (retval == 1) || (retval == -1) ) errx = -errx; #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file," general_newton_raphson(): niter,f_old,f,errx_old,errx = %4i %21.15g %21.15g %21.15g %21.15g\n", n_iter,f_old,f,errx_old,errx ); dualfprintf(fail_file,"gnr(): x_old = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",x_old[id]); } dualfprintf(fail_file,"\n "); dualfprintf(fail_file,"gnr(): x = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",x[id]); } dualfprintf(fail_file,"\n "); dualfprintf(fail_file,"gnr(): dx = "); for( id = 0; id < n ; id++) { dualfprintf(fail_file," %21.15g ",dx[id]); } dualfprintf(fail_file,"\n "); } #endif /****************************************/ /* Prepare for the next iteration, set the "old" variables: */ /****************************************/ for( id = 0; id < n ; id++) dx_old[id] = dx[id] ; f_old = f; df_old = df; /****************************************/ /* If we've reached the tolerance level, then just do a few extra iterations before stopping */ /****************************************/ if( (fabs(errx) <= NEWT_TOL) && (doing_extra == 0) && (EXTRA_NEWT_ITER > 0) ) { doing_extra = 1; } if( doing_extra == 1 ) i_extra++ ; if( ((fabs(errx) <= NEWT_TOL)&&(doing_extra == 0)) || (i_extra > EXTRA_NEWT_ITER) || (n_iter >= (MAX_NEWT_ITER-1)) ) { keep_iterating = 0; } n_iter++; #if(CRAZYDEBUG) if(icurr==0 && jcurr==31 && nstep==9 && steppart==2){ dualfprintf(fail_file,"n_iter=%d errx=%21.15g %21.15g\n",n_iter,errx,MIN_NEWT_TOL); } #endif } // END of while(keep_iterating) /* Check for bad untrapped divergences : */ if( (finite(f)==0) || (finite(df)==0) || (finite(x[0])==0) || (finite(x[1])==0)) { #if(!OPTIMIZED) if( debugfail >= 2 ) { dualfprintf(fail_file,"general_newton_raphson(): nan encountered in f or df!! \n"); dualfprintf(fail_file,"gnr nan(): f, df, x0, dx0 = %21.15g %21.15g %21.15g %21.15g \n", f,df,x[0],dx[0]); } #endif return(1); } if( fabs(errx) > MIN_NEWT_TOL){ if( (do_line_search != USE_LINE_SEARCH) || (USE_LINE_SEARCH < 0) ) { #if(DOHISTOGRAM) bin_newt_data( errx, n_iter, 0, 0 ); #endif #if(!OPTIMIZED) if(ltrace2) { dualfprintf(fail_file," totalcount = %d 0 %d %d %d %21.15g \n",n_iter,retval,do_line_search,i_extra,errx); } if(ltrace) { dualfprintf(fail_file,"general_newton_raphson(): did not find solution \n"); if( retval == -1 ) { dualfprintf(fail_file,"general_newton_raphson(): lnsrch converged: x = "); for( id = 0; id < n ; id++) dualfprintf(fail_file," %21.15g ",x[id]); dualfprintf(fail_file,"\n"); dualfprintf(fail_file,"general_newton_raphson(): lnsrch converged: x_old = "); for( id = 0; id < n ; id++) dualfprintf(fail_file," %21.15g ",x_old[id]); dualfprintf(fail_file,"\n"); } } // dualfprintf(fail_file,"gnr retval2 = %4i \n", 1); #endif return(1); } else { /* If bad return and we tried line searching, try it without before giving up: */ // dualfprintf(fail_file,"gnr: doing recursive call, do_line_search, retval, errx = %4i %4i %21.15g \n", do_line_search, retval, errx ); // retval2 = general_newton_raphson( x_orig, n, ((do_line_search+1)%2), funcd, res_func ); for( id = 0; id < n ; id++) x[id] = x_orig[id] ; // dualfprintf(fail_file,"gnr retval3 = %4i \n", retval2); return( retval2 ); } } if( (fabs(errx) <= MIN_NEWT_TOL) && (fabs(errx) > NEWT_TOL) ){ #if(DOHISTOGRAM) bin_newt_data( errx, n_iter, 1, 0 ); #endif #if(!OPTIMIZED) if(ltrace2) { dualfprintf(fail_file," totalcount = %d 1 %d %d %d %21.15g \n",n_iter,retval,do_line_search,i_extra,errx); } if(ltrace) { dualfprintf(fail_file,"general_newton_raphson(): found minimal solution \n"); } // dualfprintf(fail_file,"gnr retval4 = %4i \n", 0); #endif return(0); } if( fabs(errx) <= NEWT_TOL ){ #if(DOHISTOGRAM) bin_newt_data( errx, n_iter, 2, 0 ); #endif #if(!OPTIMIZED) if(ltrace2) { dualfprintf(fail_file," totalcount = %d 2 %d %d %d %21.15g \n",n_iter,retval,do_line_search,i_extra, errx); } // dualfprintf(fail_file,"gnr retval5 = %4i \n", 0); #endif return(0); } #if(!OPTIMIZED) dualfprintf(fail_file,"gnr retval6 = %4i \n", 0); #endif return(0); }
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 ; FTYPE alpha, ucovt, utsqp1, aco, bco, cco, pevar, agame, the; int i,j, n, retval, i_increase ; double dummy; 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) ; 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) ; // fprintf(stderr,"failure, utsq_too_big at %d %d\n", i,j); } 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++; } // Calculate W and vsq: x_2d[0] = fabs( W_last ); x_2d[1] = x1_of_x0( W_last ) ; retval = general_newton_raphson( x_2d, n, func_vsq ) ; 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) ) { // fprintf(stderr,"failure, in solver at %d %d\n", i,j); retval = retval*100+1; return(retval); } else{ if(W <= 0. || W > W_TOO_BIG) { // fprintf(stderr,"failure, W_too_big at %d %d\n", i,j); 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 = 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]) { 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 find_root_2D_gen(FTYPE x0, FTYPE *xnew) { FTYPE x[2], x_orig[2]; int ntries = 0; int retval, n = 2; int it; static void func_vsq( FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *f, FTYPE *df, int n); static void func_vsq2( FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *f, FTYPE *df, int n); static FTYPE res_sq_vsq( FTYPE [] ); static FTYPE res_sq_vsq2( FTYPE [] ); static FTYPE x1_of_x0(FTYPE x0 ) ; static int general_newton_raphson( FTYPE x[], int n, int do_line_search, void (*funcd) (FTYPE [], FTYPE [], FTYPE [], FTYPE [][NEWT_DIM], FTYPE *, FTYPE *, int), FTYPE (*res_func) (FTYPE []) ); const int ltrace = 0; /* Set presets: */ x_orig[0] = x[0] = fabs(x0) ; x_orig[1] = x[1] = x1_of_x0( x0 ) ; #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file, "find_root_2D_gen(): x[0] = %21.15g , x[1] = %21.15g \n", x[0], x[1]); } #endif retval = general_newton_raphson( x, n, USE_LINE_SEARCH, func_vsq2, res_sq_vsq2 ) ; ntries++; while( (retval==1) && (ntries <= MAX_NEWT_RETRIES ) ) { // x[0] = x_orig[0] * (1. + ( (1.*rand())/(1.*RAND_MAX) - 0.5 ) ); x[0] = x_orig[0]; for( it=0; it<ntries; it++) x[0] *= 10.0; x[1] = x1_of_x0( x[0] ) ; // retval = general_newton_raphson( x, n, USE_LINE_SEARCH, func_vsq, res_sq_vsq ) ; retval = general_newton_raphson( x, n, USE_LINE_SEARCH, func_vsq2, res_sq_vsq2 ) ; #if(!OPTIMIZED) if( ltrace ) { dualfprintf(fail_file, "find_root_2D_gen(): ntries, x[0,1] = %4i %21.15g %21.15g \n", ntries, x[0], x[1]); } #endif ntries++; } #if( MAX_NEWT_RETRIES > 0 ) if( (ntries > MAX_NEWT_RETRIES) && (retval==1) ) { if( debugfail >= 2 ) { dualfprintf(fail_file, "find_root_2D_gen(): Bad exit value from general_newton_raphson() !! \n"); dualfprintf(fail_file, "find_root_2D_gen(): ntries = %d , x[0] = %21.15g , x[1] = %21.15g \n", ntries, x[0], x[1]); } } #endif *xnew = x[0]; return(retval); }