예제 #1
0
int wvsq_solv_ldz(FTYPE *vsq, FTYPE *W)
{
  FTYPE tol, x1, x2;
  FTYPE rtsafe(void (*funcd) (), FTYPE x1, FTYPE x2, FTYPE xacc);
  extern void func(FTYPE *x, FTYPE *f, FTYPE *df);
  extern void funcorig(FTYPE *x, FTYPE *f, FTYPE *df);
  int nrunsafe(void (*funcd) (FTYPE*,FTYPE*,FTYPE*), FTYPE *guess);
  int nrunsafeorig(void (*funcd) (FTYPE*,FTYPE*,FTYPE*), FTYPE *guess);

  x1 = 0. - SMALL;
  x2 = 1. - 1.e-6;

  // x1 = 0.5*(*vsq) ;
  // x2 = 0.5 + 0.5*(*vsq) ;

#if(JONCORRECTIONS)
    if(nrunsafe(func, vsq)>=1){
      if(debugfail>=1) dualfprintf(fail_file,"t=%g : nrsafe failed\n",t);
      return(1);
    }
  // sometimes, however unlikely, it can (and has) happen that vsq is identically 1.0 to machine precision.  This result can, sometimes, have good enough error to pass nrunsafe.  We however cannot allow this, so fail on this case.
  //  if(*vsq>=1.0){
  // don't fail this since not so bad as a real failure unless actually >=1.0, we only want to rescale velocities, not screw up solution
  //  if(*vsq>=1.0-1.0/(GAMMAMAX*GAMMAMAX)){
  if( (*vsq>=1.0-1.0/(GAMMAFAIL*GAMMAFAIL))||(*vsq<0.0)){
    if(fabs(*vsq)<1E-10) *vsq=1E-10; // machine precision thing
    else{    
      if(debugfail>=1) dualfprintf(fail_file,"t=%g : nrunsafe passed vsq>~1.0  : vsq=%21.15g passed\n",t,*vsq);
      return(1); // i.e. failure, even if passed tolerance requirements
    }
  }


  // tol = 1.e-4 ;
  // *vsq = rtsafe(func,x1,x2,tol) ;
#else
    nrunsafeorig(funcorig, vsq);
#endif

  *W = Wc;

  return(0);

}
예제 #2
0
파일: exact.c 프로젝트: Ingwar/amuse
void fluxes(const Cons1DS Ul, const Cons1DS Ur,
            const Prim1DS Wl, const Prim1DS Wr,
            const Real Bxi, Cons1DS *pF)
{
  Real zl, zr, zm, dm, Vxm, Mxm, tmp, dmin, dmax;
  Real sl, sr;    /* Left and right going shock velocity */
  Real hdl, hdr;  /* Left and right going rarefaction head velocity */
  Real tll, tlr;  /* Left and right going rarefaction tail velocity */
  char soln;      /* two bits: 0=shock, 1=raref */

  if(!(Ul.d > 0.0)||!(Ur.d > 0.0))
    ath_error("[exact flux]: Non-positive densities: dl = %e  dr = %e\n",
	      Ul.d, Ur.d);

/*--- Step 1. ------------------------------------------------------------------
 * Compute the density and momentum of the intermediate state
 */

  zl = sqrt((double)Wl.d);
  zr = sqrt((double)Wr.d);

  /* --- 1-shock and 2-shock --- */
  soln = 0;

  /* Start by finding density if shocks on both left and right.
   * This will only be the case if dm > Wl.d and dm > Wr.d */
  tmp = zl*zr*(Wl.Vx - Wr.Vx)/(2.0*Iso_csound*(zl + zr));
  zm = tmp + sqrt((double)(tmp*tmp + zl*zr));
  dm = zm*zm;

  /* Get velocity from 1-shock formula */
  Vxm = Wl.Vx - Iso_csound*(dm-Wl.d)/(zm*zl);

  /* If left or right density is greater than intermediate density,
   * then at least one side has rarefaction instead of shock */
  dmin = MIN(Wl.d, Wr.d);
  dmax = MAX(Wl.d, Wr.d);
  if (dm < dmax) {
    /* --- 1-rarefaction and 2-rarefaction --- */
    soln = 3;

    /* Try rarefactions on both left and right, since it's a quicker
     * calculation than 1-shock+2-raref or 1-raref+2-shock */
    dm = zl*zr*exp((Wl.Vx-Wr.Vx)/(2.0*Iso_csound));

    /* Get velocity from 1-rarefaction formula */
    Vxm = Wl.Vx - Iso_csound*log(dm/Wl.d);

    /* If left or right density is smaller than intermediate density,
     * then we must instead have a combination of shock and rarefaction */
    if (dm > dmin) {
      /* --- EITHER 1-rarefaction and 2-shock ---
       * --- OR     1-shock and 2-rarefaction --- */

      /* Solve iteratively equation for shock and rarefaction
       * If Wl.d > Wr.d ==> 1-rarefaction and 2-shock
       * If Wr.d > Wl.d ==> 1-shock and 2-rarefaction */
      if (Wl.d > Wr.d) soln = 2; else soln = 1;

      dm = rtsafe(&srder,dmin,dmax, 2.0*DBL_EPSILON, Wl.Vx, Wr.Vx, dmin, dmax);

      /* Don't be foolish enough to take ln of zero */
      if ((dm > dmin) && (dm <= dmax)) {
        if (Wl.d > Wr.d) {
          /* Get velocity from 1-rarefaction formula */
          Vxm = Wl.Vx - Iso_csound*log(dm/Wl.d);
        } else {
          /* Get velocity from 2-rarefaction formula */
          Vxm = Wr.Vx + Iso_csound*log(dm/Wr.d);
        }
      } else {
        /* --- DEFAULT 1-rarefaction and 2-rarefaction --- */
        soln = 3;

        /* In the event that the intermediate density fails to fall between
         * the left and right densities (should only happen when left and
         * right densities differ only slightly and intermediate density
         * calculated in any step has significant truncation and/or roundoff
         * errors), default to rarefactions on both left and right */
        dm = zl*zr*exp((Wl.Vx-Wr.Vx)/(2.0*Iso_csound));

        /* Get velocity from 1-rarefaction formula */
        Vxm = Wl.Vx - Iso_csound*log(dm/Wl.d);
      }
    }
  }

  if (dm < 0.0)
    ath_error("[exact flux]: Solver finds negative density %5.4e\n", dm);

/*--- Step 2. ------------------------------------------------------------------
 * Calculate the Interface Flux if the wave speeds are such that we aren't
 * actually in the intermediate state
 */

  if (soln & 2) { /* left rarefaction */
    /* The L-going rarefaction head/tail velocity */
    hdl = Wl.Vx - Iso_csound;
    tll = Vxm - Iso_csound;

    if (hdl >= 0.0) {
      /* To left of rarefaction */
      pF->d  = Ul.Mx;
      pF->Mx = Ul.Mx*(Wl.Vx) + Wl.d*Iso_csound2;
      pF->My = Ul.My*(Wl.Vx);
      pF->Mz = Ul.Mz*(Wl.Vx);
      return;
    } else if (tll >= 0.0) {
      /* Inside rarefaction fan */
      dm = Ul.d*exp(hdl/Iso_csound);
      Mxm = Ul.d*Iso_csound*exp(hdl/Iso_csound);
      Vxm = (dm == 0.0 ? 0.0 : Mxm / dm);

      pF->d  = Mxm;
      pF->Mx = Mxm*Vxm + dm*Iso_csound2;
      pF->My = Mxm*Wl.Vy;
      pF->Mz = Mxm*Wl.Vz;
      return;
    }
  } else { /* left shock */
    /* The L-going shock velocity */
    sl = Wl.Vx - Iso_csound*sqrt(dm)/zl;

    if(sl >= 0.0) {
      /* To left of shock */
      pF->d  = Ul.Mx;
      pF->Mx = Ul.Mx*(Wl.Vx) + Wl.d*Iso_csound2;
      pF->My = Ul.My*(Wl.Vx);
      pF->Mz = Ul.Mz*(Wl.Vx);
      return;
    }
  }

  if (soln & 1) { /* right rarefaction */
    /* The R-going rarefaction head/tail velocity */
    hdr = Wr.Vx + Iso_csound;
    tlr = Vxm + Iso_csound;

    if (hdr <= 0.0) {
      /* To right of rarefaction */
      pF->d  = Ur.Mx;
      pF->Mx = Ur.Mx*(Wr.Vx) + Wr.d*Iso_csound2;
      pF->My = Ur.My*(Wr.Vx);
      pF->Mz = Ur.Mz*(Wr.Vx);
      return;
    } else if (tlr <= 0.0) {
      /* Inside rarefaction fan */
      tmp = dm;
      dm = tmp*exp(-tlr/Iso_csound);
      Mxm = -tmp*Iso_csound*exp(-tlr/Iso_csound);
      Vxm = (dm == 0.0 ? 0.0 : Mxm / dm);

      pF->d  = Mxm;
      pF->Mx = Mxm*Vxm + dm*Iso_csound2;
      pF->My = Mxm*Wr.Vy;
      pF->Mz = Mxm*Wr.Vz;
      return;
    }
  } else { /* right shock */
    /* The R-going shock velocity */
    sr = Wr.Vx + Iso_csound*sqrt(dm)/zr;

    if(sr <= 0.0) {
      /* To right of shock */
      pF->d  = Ur.Mx;
      pF->Mx = Ur.Mx*(Wr.Vx) + Wr.d*Iso_csound2;
      pF->My = Ur.My*(Wr.Vx);
      pF->Mz = Ur.Mz*(Wr.Vx);
      return;
    }
  }

/* If we make it this far, then we're in the intermediate state */

/*--- Step 3. ------------------------------------------------------------------
 * Calculate the Interface Flux */

  if(Vxm >= 0.0){
    pF->d  = dm*Vxm;
    pF->Mx = dm*Vxm*Vxm + dm*Iso_csound2;
    pF->My = dm*Vxm*Wl.Vy;
    pF->Mz = dm*Vxm*Wl.Vz;
  }
  else{
    pF->d  = dm*Vxm;
    pF->Mx = dm*Vxm*Vxm + dm*Iso_csound2;
    pF->My = dm*Vxm*Wr.Vy;
    pF->Mz = dm*Vxm*Wr.Vz;
  }

  return;
}