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) ;

}
Beispiel #2
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 ;
  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) ;

}