Exemplo n.º 1
0
def radPress(numDeps, temp):

    pRad = [[0.0 for i in range(numDeps)] for j in range(2)]

    logC = Useful.logC()
    logSigma = Useful.logSigma()
    radFac = math.log(4.0) + logSigma - math.log(3.0) - logC
    for i in range(numDeps):
        pRad[1][i] = radFac + 4.0 * temp[1][i]
        pRad[0][i] = math.exp(pRad[1][i])

    return pRad
Exemplo n.º 2
0
def hydroFormalSoln(numDeps, grav, tauRos, kappa, temp, guessPGas):
    """This approach is based on integrating the formal solution of the hydrostaitc equilibrium equation
// on the otical depth (Tau) scale.  Advantage is that it makes better use of the itial guess at
// pgas 
//
//  Takes in *Gas* pressure, converts tot *total pressure*, then returns *Gas* pressure
//
"""

    press = [[0.0 for i in range(numDeps)] for j in range(2)]
    logC = Useful.logC()
    logSigma = Useful.logSigma()

    radFac = math.log(4.0) + logSigma - math.log(3.0) - logC

    logEg = math.log(grav)  #//Natural log g!!
    #// no needed if integrating in natural log?? //double logLogE = Math.log(Math.log10(Math.E));
    log1p5 = math.log(1.5)
    logE = math.log10(math.e)

    #//Compute radiation pressure for this temperature structure and add it to Pgas
    #//
    #double pT, pRad;
    logPRad = [0.0 for i in range(numDeps)]
    logPTot = [0.0 for i in range(numDeps)]
    #//  System.out.println("hydroFormalSoln: ");
    for i in range(numDeps):
        logPRad[i] = radFac + 4.0 * temp[1][i]
        pRad = math.exp(logPRad[i])
        #//System.out.println("i " + i + " pRad " + pRad);
        pT = guessPGas[0][i] + pRad
        #//       System.out.println("i " + i + " guessPGas[1] " + logE*guessPGas[1][i]);
        logPTot[i] = math.log(pT)

    #double help, logHelp, logPress;
    #double term, logSum, integ, logInteg, lastInteg;
    #double deltaLogT;

    sum = [0.0 for i in range(numDeps)]

    #//Upper boundary - inherit from intiial guess:
    #//Carefull here - P at upper boundary can be an underestimate, but it must not be greater than value at next depth in!
    #//  press[1][0] = logPTot[0];
    #//  press[1][0] = guessPGas[1][0];
    #//   press[1][0] = Math.log(1.0e-4); //try same upper boundary as Phoenix
    #//
    #//   press[0][0] = Math.exp(press[1][0]);
    press[0][0] = 0.1 * guessPGas[0][0]
    press[1][0] = math.log(press[0][0])
    #//Corresponding value of basic integrated quantity at top of atmosphere:
    logSum = 1.5 * press[1][0] + math.log(0.666667) - logEg
    sum[0] = math.exp(logSum)

    #// Integrate inward on logTau scale

    #// CAUTION; This is not an integral for Delta P, but for P once integral at each tau is exponentiated by 2/3!
    #// Accumulate basic integral to be exponentiated, then construct pressure values later:

    #//Jump start integration with an Euler step:
    deltaLogT = tauRos[1][1] - tauRos[1][0]
    #// log of integrand
    logInteg = tauRos[1][1] + 0.5 * logPTot[1] - kappa[1][1]
    lastInteg = math.exp(logInteg)
    sum[1] = sum[0] + lastInteg * deltaLogT

    #// Continue with extended trapezoid rule:

    for i in range(2, numDeps):

        deltaLogT = tauRos[1][i] - tauRos[1][i - 1]
        logInteg = tauRos[1][i] + 0.5 * logPTot[i] - kappa[1][i]
        integ = math.exp(logInteg)
        term = 0.5 * (integ + lastInteg) * deltaLogT
        sum[i] = sum[i - 1] + term  #//accumulate basic integrated quantity
        lastInteg = integ

    #//System.out.println("hydroFormalSoln: ");
    for i in range(1, numDeps):
        #//Evaluate total pressures from basic integrated quantity at edach depth
        #// our integration variable is the natural log, so I don't think we need the 1/log(e) factor
        logPress = 0.666667 * (log1p5 + logEg + math.log(sum[i]))
        #//Subtract radiation pressure:
        logHelp = logPRad[i] - logPress
        help = math.exp(logHelp)
        # For hot and low g stars: limit Prad to 50% Ptot so we doen't get netaive Pgas and rho values:
        if (help > 0.5):
            help = 0.5

        press[1][i] = logPress + math.log(1.0 - help)
        #//System.out.println("i " + i + " guessPGas[1] " + logE*guessPGas[1][i] + " press[1] " + logE*press[1][i]);
        press[0][i] = math.exp(press[1][i])

    return press  #//*Gas* pressure
Exemplo n.º 3
0
def convec(numDeps, tauRos, depths, temp, press, rho, kappa, kappaSun, zScale,
           teff, logg, mmw):

    logE = math.log10(math.E)  #// for debug output
    ln10 = math.log(10.0)  #//needed to convert logg from base 10 to base e

    convTemp = [[0.0 for i in range(numDeps)] for j in range(2)]

    #//Schwarzschild criterion for convective instability:
    gamma = 5.0 / 3.0  #//adiabatic gamma for ideal monatomic gas - the photon gas is negligible in stars w convection
    gammaFac = gamma / (
        gamma - 1.0
    )  #// yeah, yeah - I know it's 2.5, but let's show where it comes from for the record...
    invGamFac = 1.0 / gammaFac
    #//CHEAT: Set gammaThing to value that makes convection just disappear at bottom of mid-F star (7000 K)
    #//double gammaThing = 1.60;
    #//double invGamThing = 1.0 / gammaThing;
    #double invGamThing;
    #//System.out.println("gammaThing " + gammaThing);

    #double deltaP, deltaT; //, dlnPdlnT;
    #double dlnTdlnP, dlnMudlnP, deltaMu;

    #double Hp, logHp;

    #//double HpSun = 1.2535465715411615E7;  //cm, as computed by GrayStar at depth index=36
    HpSun = 2.0e7  #//cm, approximately as computed by GrayStar at depth index=36
    logHpSun = math.log(HpSun)

    #//Compute the presure scale height as a reality check:
    HpRefDep = 36  #//index of reference depth for computing pressure scale height
    logHp = press[1][HpRefDep] - rho[1][HpRefDep] - ln10 * logg
    Hp = math.exp(logHp)

    #//Try scaling gamma to "fix" the convective boundary
    #//invGamThing = invGamFac * HpSun/Hp;

    #//System.out.println("Hp/HpSun " + Hp/HpSun);

    #//double[] mmw = State.mmwFn(numDeps, temp, zScale);

    #//Search outward for top of convection zone
    isStable = False
    iBound = numDeps - 1  #//initialize index of depth where convection begins to bottom of atmosphere
    for i in range(numDeps - 2, 0, -1):

        #//System.out.println("Hp " + Hp);
        #//1st order finite difference - erratic?
        #//double deltaP = press[1][i] - press[1][i-1];
        #//double deltaT = temp[1][i] - temp[1][i-1];
        #//Try "2nd order" finite difference - non-uniform spacing in deltaT
        deltaP = press[1][i + 1] - press[1][i - 1]
        deltaT = temp[1][i + 1] - temp[1][i - 1]
        deltaMu = (mmw[i + 1] - mmw[i]) * Useful.amu
        #//dlnPdlnT = deltaP / deltaT;
        dlnTdlnP = deltaT / deltaP
        dlnMudlnP = deltaMu / deltaP
        #//System.out.format("%12.8f   %12.8f%n", logE * tauRos[1][i], dlnPlndT);
        #// This can be finicky - let's say we have not found the radiative zone unless two consecutive layers meet the criterion
        #//if (dlnPdlnT > gammaThing) {
        if (dlnTdlnP < invGamFac + dlnMudlnP):

            #//Convectively stable
            if (isStable == False):
                #//The previous convectively unstable layer was an isolated anomoly - we're have NOT found the zone!  Reset:
                isStable = true
                iBound = i
                #//System.out.println("First stable layer was found, tauRos " + logE * tauRos[1][i] + " NOW: isStable " + isStable);

            #}
        #}
    #}
    #//System.out.println("Convec: iBound " + iBound);

    #//Radiative zone - leave temperatures alone:
    for i in range(iBound):
        convTemp[0][i] = temp[0][i]
        convTemp[1][i] = temp[1][i]

    baseTemp = temp[0][iBound]
    baseLogTemp = temp[1][iBound]
    baseTau = tauRos[0][iBound]
    baseLogTau = tauRos[1][iBound]
    #//double baseDepth = depths[iBound]

    logSigma = Useful.logSigma()
    logK = Useful.logK()
    logAmu = Useful.logAmu()

    mixLSun = 1.0  #// convective mixing length in pressure scale heights (H_P)

    betaSun = 0.5  #// factor for square of  convective bubble velocity (range: 0.0 - 1.0)

    #double Cp, logCp;  //Specific heat capacity at constant pressure
    mixL = mixLSun  #//initialization
    beta = betaSun  #//initialization
    teffSun = 5778.0
    loggSun = 4.44

    #//Shameless fix:
    #//It seems mixL and beta need to be temp and press dependent:
    if (teff < teffSun):
        mixL = mixLSun * math.pow(
            teff / teffSun,
            4.0)  #//lower teff -> smaller mixL -> steeper SAdGrad
        beta = betaSun * math.pow(
            teff / teffSun,
            4.0)  #//lower teff -> smaller beta -> steeper SAdGrad

    mixL = mixL * math.pow(
        loggSun / logg, 2.0)  #// lower logg -> larger mixL -> smaller sAdGrad
    beta = beta * math.pow(
        loggSun / logg, 2.0)  #// lower logg -> larger beta -> smaller sAdGrad
    """/*
        //Shameless fix:
        beta = betaSun;  // no fix?
        mixL = mixLSun * Math.pow(Hp / HpSun, 4.0);  //lower teff -> smaller Hp -> smaller mixL -> steeper SAdGrad
        //mixL = mixL * Math.pow(logg / loggSun, 4.0); // lower logg -> smaller mixL -> larger sAdGrad
    */"""
    logMixL = math.log(mixL)
    logBeta = math.log(beta)

    logFluxSurfBol = logSigma + 4.0 * math.log(teff)

    #// This will get hairy when we take it super-adiabatic so let's take it *really* easy and make every factor and term clear:
    logInvGamFac = math.log(invGamFac)

    #//Get the mean molecular weight in amu from State - Row 0 is "mu" in amu:
    #double mu, logMu, logFctr1, logFctr2, logFctr3;
    #double nextTemp, lastTemp, nextTemp2;

    #//Adiabatic dT/dx gradients in various coordinates
    #//tau, logTau space
    #double logAdGradTauMag, logAdGradLogTauMag, adGradLogTau;
    #//SuperAdiabatic dT/dx gradients in various coordinates
    #double deltaTau, logDeltaTau, deltaLogTau, logDeltaLogTau;
    #double sAdGradLogTau, logSadGradR, logSadGradTau, logSadGradLogTau;
    #double lastLogTau;

    #//r space:
    #double logAdGradRMag, adGradR;

    #//SuperAdiabatic dT/dx gradients in various coordinates
    #double deltaR, logDeltaR;
    #/*
    #     double sAdGradR;
    #     double lastDepth;
    #     */

    lastTemp = baseTemp
    lastLogTau = baseLogTau
    #//lastDepth = baseDepth;

    #//System.out.println(
    #//        "tauRos[1][i]   (tauRos[1][i]-lastLogTau)   adGradLogTau   rho[1][i]   kappa[1][i]   lastTemp   nextTemp");
    for i in range(iBound, numDeps):

        mu = mmw[i]
        logMu = math.log(mu)
        logFctr1 = logMu + logAmu - logK
        #//System.out.println("logFactr1 " + logE*logFctr1 + " logInvGamFac " + logE*logInvGamFac + " logg " + logg);
        logCp = math.log(
            5.0 / 2.0
        ) - logFctr1  #//ideal monatomic gas - underestimate that neglects partial ionization

        #// ** Caution: These are log_e of the *magnitude* of the temperature gradients!
        #//The adiabatic dT/dTau in r space
        logAdGradRMag = logInvGamFac + logFctr1 + ln10 * logg  #//logg is in base 10

        #//This is baaad stuff - remember our tuaRos scale has *nothing* to do with our kappa values!
        #//The adiabatic dT/dTau in tau space - divide dT/dr by rho and kappa and make it +ve becasue we're in tau-space:
        #//Bad fake to fix artificially small dT/dr at low Teff - use kappaSun instead of kappa
        logAdGradTauMag = logAdGradRMag - rho[1][i] - kappa[1][i]
        #//The adiabatic dT/dLnTau in log_e(tau) space
        logAdGradLogTauMag = tauRos[1][i] + logAdGradTauMag

        #//Build the T(tau) in the convection zone:
        #// Work in logTau space - numerically safer??
        adGradLogTau = math.exp(
            logAdGradLogTauMag)  #//No minus sign - logTau increases inward...
        nextTemp = lastTemp + adGradLogTau * (tauRos[1][i] - lastLogTau)

        #//System.out.format("%12.8f   %12.8f   %12.8f   %12.8f   %12.8f   %7.1f   %7.1f%n", logE * tauRos[1][i], logE * (tauRos[1][i] - lastLogTau), adGradLogTau, logE * rho[1][i], logE * kappa[1][i], lastTemp, nextTemp);
        """/*
             // Do in geometric depth space
             adGradR = Math.exp(logAdGradRMag); // no minus sign - our depths *increase* inwards (they're NOT heights!)
             nextTemp = lastTemp + adGradR * (depths[i] - lastDepth);  
            
             //System.out.format("%12.8f   %12.8f   %12.8f   %7.1f   %7.1f%n", logE*tauRos[1][i], (depths[i] - lastDepth), adGradR, lastTemp, nextTemp);
             */"""
        #//Okay - now the difference between the superadiabatic and adiabatic dT/dr:
        logFctr2 = rho[1][i] + logCp + 2.0 * logMixL

        #// ** NOTE ** Should temp in the following line be the *convective* temp of the last depth???
        #// logg is in base 10 - convert to base e
        logFctr3 = 3.0 * (ln10 * logg - math.log(lastTemp)) / 2.0

        #//Difference between SuperAdibatic dT/dr and Adiabtic dT/dr in r-space - Carroll & Ostlie 2nd Ed. p. 328
        #//System.out.println("logFluxSurfBol " + logE * logFluxSurfBol + " logFctr2 " + logE * logFctr2 + " logFctr1 " + logE * logFctr1 + " logFctr3 " + logE * logFctr3 + " logBeta " + logE * logBeta);
        logDeltaR = logFluxSurfBol - logFctr2 + 2.0 * logFctr1 + logFctr3 - 0.5 * logBeta
        logDeltaR = 2.0 * logDeltaR / 3.0  #//DeltaR is above formula to the 2/3 power

        #//This is baaad stuff - remember our tuaRos scale has *nothing* to do with our kappa values!
        #//Bad fake to fix artificially small dT/dr at low Teff - use kappaSun instead of kappa
        logDeltaTau = logDeltaR - rho[1][i] - kappa[1][i]
        logDeltaLogTau = tauRos[1][i] + logDeltaTau
        sAdGradLogTau = adGradLogTau + math.exp(logDeltaLogTau)
        #//System.out.format("%12.8f   %12.8f   %12.8f   %12.8f%n", logE*tauRos[1][i], logE*logDeltaR, logE*logDeltaTau, logE*logDeltaLogTau);
        nextTemp2 = lastTemp + sAdGradLogTau * (tauRos[1][i] - lastLogTau)
        """/*
        // Do in geometric depth space
        sAdGradR = adGradR + Math.exp(logDeltaR);
        nextTemp2 = lastTemp + sAdGradR * (depths[i] - lastDepth);
        */"""
        #// set everything to nextTemp2 for superadibatic dT/dr, and to nexTemp for adiabatic dT/dr
        convTemp[0][i] = nextTemp2
        convTemp[1][i] = math.log(nextTemp2)
        lastTemp = nextTemp2
        lastLogTau = tauRos[1][i]
        #//lastDepth = depths[i]
    #}

    return convTemp