/* ********************************************************************* */ void Init (double *v, double x1, double x2, double x3) /*! * The Init() function can be used to assign initial conditions as * as a function of spatial position. * * \param [out] v a pointer to a vector of primitive variables * \param [in] x1 coordinate point in the 1st dimension * \param [in] x2 coordinate point in the 2nd dimension * \param [in] x3 coordinate point in the 3rd dimension * * The meaning of x1, x2 and x3 depends on the geometry: * \f[ \begin{array}{cccl} * x_1 & x_2 & x_3 & \mathrm{Geometry} \\ \noalign{\medskip} * \hline * x & y & z & \mathrm{Cartesian} \\ \noalign{\medskip} * R & z & - & \mathrm{cylindrical} \\ \noalign{\medskip} * R & \phi & z & \mathrm{polar} \\ \noalign{\medskip} * r & \theta & \phi & \mathrm{spherical} * \end{array} * \f] * * Variable names are accessed by means of an index v[nv], where * nv = RHO is density, nv = PRS is pressure, nv = (VX1, VX2, VX3) are * the three components of velocity, and so forth. * *********************************************************************** */ { /* Density normalization */ real mu = MeanMolecularWeight(v); g_unitDensity = CONST_amu*mu; /* Upstream Mach number and temperature This determines velocity normalization which is the value of the upstream velocity */ double mach = g_inputParam[PAR_MACH]; double temp1_cgs = g_inputParam[PAR_TEMP]; double csound_cgs = sqrt(g_gamma*CONST_kB*temp1_cgs/(CONST_amu*mu)); g_unitVelocity = csound_cgs*mach; /* Upstream vector */ double v1[NVAR]; v1[RHO] = g_inputParam[PAR_RHO1]; EXPAND(v1[VX1] = 1.0;,
/* ***************************************************************** */ void PowerLawCooling (Data_Arr VV, real dt, Time_Step *Dts, Grid *grid) /* * * PURPOSE: * * Take a source step to account for radiative cooling with * a power-law cooling function. * * We directly integrate the following ODE: * * dp_cgs/dt_cgs = -(gamma - 1) Lambda(rho_cgs, T_cgs) * * where: Lambda = lambda0 rho_cgs^2/(mu*m_amu,cgs)^2 (T_cgs/T_crit,cgs)^alpha * * if the cooling function was a single power law. * * * ******************************************************************* */ { int i, j, k; real cost, dE; real rho, p, T, p_f, T_f; real oma, unit_time; /* Read cooling parameters file */ /* Power law cooling mainly valid in regions 10^5 The values for alpha and lamdbda0 just come from a linear fit to the cooltable.dat data between T = 3*10^4 and 1*10^8 K. See cool_fit_pow.py */ double alpha = -0.37988772; double lambda0 = 1.044886865e-22; /* Mean molecular mass */ double vdummy[NVAR]; real mu = MeanMolecularWeight(vdummy); /* A constant that is part of the solution. */ cost = (g_gamma-1.0)*lambda0/CONST_kB*pow(g_minCoolingTemp, -alpha); /* Unit time code to cgs conversion */ unit_time = g_unitLength/g_unitVelocity; /* ------------------------------------------------------------- Integrate analytically ------------------------------------------------------------- */ //dE = 1.e-18; DOM_LOOP(k,j,i){ /* ---- Find initial temperature in Kelvin ---- */ rho = VV[RHO][k][j][i]; p = VV[PRS][k][j][i]; T = mu*p/rho*KELVIN; if (T < g_minCoolingTemp) continue; /* ---- Find final temperature ---- */ /* rho is in code units because the factor in the equation reads * (rho/mu amu), but all other quantities are in cgs */ oma = 1.-alpha; T_f = pow(-cost*oma*rho*dt*unit_time + pow(T, oma), 1./oma); if (T_f <= g_minCoolingTemp){ T_f = T - g_maxCoolingRate*(T - g_minCoolingTemp); } else{ T_f = T - g_maxCoolingRate*(T - T_f); } //T_f = MAX(T_f, g_minCoolingTemp); /* ---- Update Energy ---- */ p_f = T_f*rho/(mu*KELVIN); VV[PRS][k][j][i] = p_f; //dE = fabs(1.0 - p_f/p) + 1.e-18; //Dts->dt_cool = MIN(Dts->dt_cool, dt*g_maxCoolingRate/dE); }
}} } Radiat (v, rhs); L = CoolCoeffs.Lrate; La = CoolCoeffs.La; Lb = CoolCoeffs.Lb; Lc = CoolCoeffs.Lc; C = CoolCoeffs.Crate; Ca = CoolCoeffs.Ca; Cb = CoolCoeffs.Cb; Cc = CoolCoeffs.Cc; R = CoolCoeffs.Rrate; Ra = CoolCoeffs.Ra; Rb = CoolCoeffs.Rb; Rc = CoolCoeffs.Rc; de = CoolCoeffs.de; X = v + NFLX; dnel_dX = CoolCoeffs.dnel_dX; N = v[RHO]*find_N_rho(); /* -- Total number density -- */ mu = MeanMolecularWeight(v); T = v[PRS]/v[RHO]*KELVIN*mu; /* -- compute the vector grad_X (mu) -- */ scrh = 1.0/CoolCoeffs.muD; for (k = 0; k < n - 1; k++){ dmu_dX[k] = (CoolCoeffs.dmuN_dX[k] - CoolCoeffs.dmuD_dX[k]*mu)*scrh; } /* ------------------------------------------------- Compute dX'/dX, dp'/dX with k = 0....n - 2 l = 0....n - 2
/* ********************************************************************* */ void Radiat (double *v, double *rhs) /*! * Cooling for neutral or singly ionized gas: good up to about 35,000 K * in equilibrium or shocks in neutral gas up to about 80 km/s. * Assumed abundances in ab * Uses t : Kelvin * dene : electron density cm*-3 * fneut : hydrogen neutral fraction (adimensionale) * ci,cr : H ionization and recombination rate coefficients * * * em(1) = TOTAL EMISSIVITY : (ergs cm**3 s**-1) * em(2) = Ly alpha + two photon continuum: Aggarwal MNRAS 202, * 10**4.3 K * em(3) = H alpha: Aggarwal, Case B * em(4) = He I 584 + two photon + 623 (all n=2 excitations): Berrington * &Kingston,JPB 20 * em(5) = C I 9850 + 9823: Mendoza, IAU 103, 5000 K * em(6) = C II, 156 micron: Mendoza, 10,000 K * em(7) = C II] 2325 A: Mendoza, 15,000 K * em(8) = N I 5200 A: Mendoza, 7500 K * em(9) = N II 6584 + 6548 A: Mendoza * em(10) = O I 63 micron: Mendoza,2500 K * em(11) = O I 6300 A + 6363 A: Mendoza, 7500 K * em(12) = O II 3727: Mendoza * em(13) = Mg II 2800: Mendoza * em(14) = Si II 35 micron: Dufton&Kingston, MNRAS 248 * em(15) = S II 6717+6727: Mendoza * em(16) = Fe II 25 micron: Nussbaumer&Storey * em(17) = Fe II 1.6 micron * em(18) = thermal energy lost by ionization * em(19) = thermal energy lost by recombination (2/3 kT per * recombination. * The ionization energy lost is not included here. * *********************************************************************** */ { int ii, k, status; double T, mu, st, rho, prs, fn; double N_H, n_el, cr, ci, rlosst, em[20], src_pr; static double t00[18] = {0.0 , 0.0 , 1.18e5, 1.40e5, 2.46e5, 1.46e4, 92.1 , 6.18e4, 2.76e4, 2.19e4, 228.0 , 2.28e4, 3.86e4, 5.13e4, 410.0 , 2.13e4, 575.0 , 8980.0}; static double ep[18] = {0.0 , 0.0 , 10.2 , 1.89, 21.2 , 1.26, 0.0079, 5.33, 2.38 , 1.89, 0.0197, 1.96, 3.33 , 4.43, 0.0354, 1.85, 0.0495, 0.775}; static double critn[18] = {0.0 , 0.0 , 1.e10, 1.e10, 1.e10, 312.0, 0.849, 1.93e7, 124.0, 865.0, 1090.0, 3950.0, 177.0, 1.e10 , 16.8, 96.0, 580.0, 1130.0}; static double om[18] = {0.0 , 0.0 , 0.90, 0.35, 0.15 , 0.067, 0.63, 0.52, 0.90, 0.30, 0.0055, 0.19, 0.33, 8.0 , 2.85, 1.75, 0.3 ,0.39}; static double ab[18] = {0.0 , 0.0 , 1.0 , 1.0 , 0.1 , 0.0003, 0.0003, 0.0003 , 0.0001 , 0.0001 , 0.0006 , 0.0006, 0.0006, 0.00002, 0.00004, 0.00004, 0.00004, 0.00004}; static double fn1[20] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0}; static double fn2[20] = {0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0,-1.0, 1.0, 1.0,-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,-1.0}; static int first_call = 1; static double E_cost, Unit_Time, N_H_rho; if (first_call) { E_cost = UNIT_LENGTH/UNIT_DENSITY/pow(UNIT_VELOCITY, 3.0); Unit_Time = UNIT_LENGTH/UNIT_VELOCITY; /* ------------------------------------------------------ conversion factor from total density to hydrogen number density, i.e. nH = N_H_rho * rho ------------------------------------------------------ */ N_H_rho = UNIT_DENSITY/CONST_amu/(CONST_AH + frac_He*CONST_AHe + frac_Z*CONST_AZ); first_call = 0; } /* ----------------------------------- Force fneut to stay between [0,1] ----------------------------------- */ v[X_HI] = MAX(v[X_HI], 0.0); v[X_HI] = MIN(v[X_HI], 1.0); /* --------------------------------------------------- Compute temperature from rho, rhoe and fractions --------------------------------------------------- */ rho = v[RHO]; mu = MeanMolecularWeight(v); #if EOS == IDEAL if (v[RHOE] < 0.0) v[RHOE] = g_smallPressure/(g_gamma-1.0); prs = v[RHOE]*(g_gamma-1.0); T = prs/rho*KELVIN*mu; #else status = GetEV_Temperature(v[RHOE], v, &T); if (status != 0) { T = T_CUT_RHOE; v[RHOE] = InternalEnergy(v, T); } #endif fn = v[X_HI]; /* -------------------------------------------------------- Set source terms equal to zero when the temperature falls below g_minCoolingTemp -------------------------------------------------------- */ /* if (T < g_minCoolingTemp){ a = b = src_pr = 0.0; continue; } */ if (mu < 0.0){ printf ("Negative mu in radiat \n"); exit(1); } st = sqrt(T); N_H = N_H_rho*rho; /* -- number density of hydrogen N_H = N(HI) + N(HII) -- */ /* ---- coeff di ionizz. e ricomb. della particella fluida i,j ---- */ cr = 2.6e-11/st; ci = 1.08e-8*st*exp(-157890.0/T)/(13.6*13.6); n_el = N_H*(1.0 - fn + frac_Z); /* -- electron number density, in cm^{-3} -- */ rhs[X_HI] = Unit_Time*n_el*(-(ci + cr)*fn + cr); em[1] = 0.0; for (k = 2; k <= 17; k++){ em[k] = 1.6e-12*8.63e-6*om[k]*ep[k]*exp(-t00[k]/T)/st; em[k] = em[k]*critn[k]*st/(n_el + critn[k]*st); em[k] = em[k]*ab[k]*(fn1[k] + fn*fn2[k]); em[1] = em[1] + em[k]; } em[18] = ci*13.6*1.6e-12*fn; em[19] = cr*0.67*1.6e-12*(1.0 - fn)*T/11590.0; em[1] = em[1] + em[18] + em[19]; /* --------------------------------------------------- rlosst is the energy loss in units of erg/cm^3/s; it must be multiplied by cost_E in order to match non-dimensional units. Source term for the neutral fraction scales with UNIT_TIME --------------------------------------------------- */ rlosst = em[1]*n_el*N_H; /* rhs[PRS] = -E_cost*rlosst*(g_gamma - 1.0); rhs[PRS] *= 1.0/(1.0 + exp( -(T - g_minCoolingTemp)/100.0)); */ rhs[RHOE] = -E_cost*rlosst; rhs[RHOE] *= 1.0/(1.0 + exp( -(T - g_minCoolingTemp)/100.0)); /* -- cutoff -- */ }