Пример #1
0
def dBdT(temp, lambda2):
    
    """// Computes the first partial derivative of B(T) wrt T, dB/dT:"""

    #double logdBdTlam; 

    #//double c = Useful.c; //linear
    logC = Useful.logC()  #//log
    #//double k = Useful.k  #//linear
    logK = Useful.logK()  #//log
    #//double h = Useful.h  #//linear
    logH = Useful.logH()  #//log

    logPreFac = math.log(2.0) + logH + 2.0 * logC  #//log
    logExpFac = logH + logC - logK      #//log

    #//Declare scratch variables:
    #double logLam, logTemp, logPreLamFac, logExpLamFac, expon, logExpon, eTerm, denom, logDenom;  //log

    #//lambda = lambda * 1.0E-7;  // convert nm to cm
    logLam = math.log(lambda2) #// Do the call to log for lambda once //log
    logTemp = math.log(temp)

    logPreLamFac = logPreFac + logExpFac - 6.0 * logLam - 2.0 * logTemp  #//log
        
    logExpLamFac = logExpFac - logLam    #//log
        
    #//This is very subtle and dangerous!
    logExpon = logExpLamFac - logTemp  #// log of hc/kTlambda
    expon = math.exp(logExpon)  #// hc/kTlambda
       
    eTerm = math.exp(expon) #// e^hc/ktlambda
    denom = eTerm - 1.0 #// e^hc/ktlambda - 1
    logDenom = math.log(denom) #// log(e^hc/ktlambda - 1)
        
    logdBdTlam = logPreLamFac + expon - 2.0 * logDenom  #//log
        
    return logdBdTlam;
    #} //end method dBdT
Пример #2
0
def masterMetal(numDeps, numLams, temp, lambdaScale, stagePops):
    """/* Metal b-f opacity routines taken from Moog (moogjul2014/, MOOGJUL2014.tar)
Chris Sneden (Universtiy of Texas at Austin)  and collaborators
http://www.as.utexas.edu/~chris/moog.html
//From Moog source file Opacitymetals.f
*/"""

    #//System.out.println("masterMetal called...");

    #//From Moog source file Opacitymetals.f
    #// From how values such as aC1[] are used in Moog file Opacit.f to compute the total opacity
    #// and then the optical depth scale, I infer that they are extinction coefficients
    #// in cm^-1
    #// There does not seem to be any correction for stimulated emission

    logE = math.log10(math.e)

    masterBF = [[0.0 for i in range(numDeps)] for j in range(numLams)]

    logUC1 = [0.0 for i in range(5)]
    logUMg1 = [0.0 for i in range(5)]
    logUMg2 = [0.0 for i in range(5)]
    logUAl1 = [0.0 for i in range(5)]
    logUSi1 = [0.0 for i in range(5)]
    logUSi2 = [0.0 for i in range(5)]
    logUFe1 = [0.0 for i in range(5)]

    logStatWC1 = 0.0
    logStatWMg1 = 0.0
    logStatWMg2 = 0.0
    logStatWAl1 = 0.0
    logStatWSi1 = 0.0
    logStatWSi2 = 0.0
    logStatWFe1 = 0.0

    theta = 1.0
    species = ""
    logGroundPopsC1 = [0.0 for i in range(numDeps)]
    logGroundPopsMg1 = [0.0 for i in range(numDeps)]
    logGroundPopsMg2 = [0.0 for i in range(numDeps)]
    logGroundPopsAl1 = [0.0 for i in range(numDeps)]
    logGroundPopsSi1 = [0.0 for i in range(numDeps)]
    logGroundPopsSi2 = [0.0 for i in range(numDeps)]
    logGroundPopsFe1 = [0.0 for i in range(numDeps)]

    #//
    #// C I: Z=6 --> iZ=5:
    aC1 = [0.0 for i in range(numDeps)]
    #// Mg I: Z=12 --> iZ=11:
    aMg1 = [0.0 for i in range(numDeps)]
    #// Mg II: Z=12 --> iZ=11:
    aMg2 = [0.0 for i in range(numDeps)]
    #// Al I: Z=13 --> iZ=12:
    aAl1 = [0.0 for i in range(numDeps)]
    #// Si I: Z=14 --> iZ=13:
    aSi1 = [0.0 for i in range(numDeps)]
    #// Si II: Z=14 --> iZ =13:
    aSi2 = [0.0 for i in range(numDeps)]
    #// Fe I: Z=26 --> iZ=25
    aFe1 = [0.0 for i in range(numDeps)]

    species = "CI"
    logUC1 = PartitionFn.getPartFn2(species)
    species = "MgI"
    logUMg1 = PartitionFn.getPartFn2(species)
    species = "MgII"
    logUMg2 = PartitionFn.getPartFn2(species)
    species = "AlI"
    logUAl1 = PartitionFn.getPartFn2(species)
    species = "SiI"
    logUSi1 = PartitionFn.getPartFn2(species)
    species = "SiII"
    logUSi2 = PartitionFn.getPartFn2(species)
    species = "FeI"
    logUFe1 = PartitionFn.getPartFn2(species)

    #//System.out.println("iD     PpC1     PpMg1      PpMg2     PpAl1     PpSi1     PpSi2     PpFe1");
    for iD in range(numDeps):
        #//neutral stage
        #//Assumes ground state stat weight, g_1, is 1.0
        #theta = 5040.0 / temp[0][iD]
        #// U[0]: theta = 1.0, U[1]: theta = 0.5
        """
        if (theta <= 0.5):
            logStatWC1 = logUC1[1]
            logStatWMg1 = logUMg1[1]
            logStatWMg2 = logUMg2[1]
            logStatWAl1 = logUAl1[1]
            logStatWSi1 = logUSi1[1]
            logStatWSi2 = logUSi2[1]
            logStatWFe1 = logUFe1[1]
        elif ( (theta < 1.0) and (theta > 0.5) ):
            logStatWC1 = ( (theta-0.5) * logUC1[0] ) + ( (1.0-theta) * logUC1[1] )
            #//divide by common factor of interpolation interval of 0.5 = (1.0 - 0.5):
            logStatWC1 = 2.0 * logStatWC1 
            logStatWMg1 = ( (theta-0.5) * logUMg1[0] ) + ( (1.0-theta) * logUMg1[1] );
            logStatWMg1 = 2.0 * logStatWMg1; 
            logStatWMg2 = ( (theta-0.5) * logUMg2[0] ) + ( (1.0-theta) * logUMg2[1] );
            logStatWMg2 = 2.0 * logStatWMg2; 
            logStatWAl1 = ( (theta-0.5) * logUAl1[0] ) + ( (1.0-theta) * logUAl1[1] );
            logStatWAl1 = 2.0 * logStatWAl1; 
            logStatWSi1 = ( (theta-0.5) * logUSi1[0] ) + ( (1.0-theta) * logUSi1[1] );
            logStatWSi1 = 2.0 * logStatWSi1; 
            logStatWSi2 = ( (theta-0.5) * logUSi2[0] ) + ( (1.0-theta) * logUSi2[1] );
            logStatWSi2 = 2.0 * logStatWSi2; 
            logStatWFe1 = ( (theta-0.5) * logUFe1[0] ) + ( (1.0-theta) * logUFe1[1] );
            logStatWFe1 = 2.0 * logStatWFe1; 
        else:
            logStatWC1 = logUC1[0]
            logStatWMg1 = logUMg1[0]
            logStatWMg2 = logUMg2[0]
            logStatWAl1 = logUAl1[0]
            logStatWSi1 = logUSi1[0]
            logStatWSi2 = logUSi2[0]
            logStatWFe1 = logUFe1[0]
        """

        #// NEW Interpolation involving temperature for new partition function: lburns
        thisTemp = temp[0][iD]
        if (thisTemp <= 130):
            logStatWC1 = logUC1[0]
            logStatWMg1 = logUMg1[0]
            logStatWMg2 = logUMg2[0]
            logStatWAl1 = logUAl1[0]
            logStatWSi1 = logUSi1[0]
            logStatWSi2 = logUSi2[0]
            logStatWFe1 = logUFe1[0]
        elif (thisTemp > 130 and thisTemp <= 500):
            #// Add in interpolation here lburns
            logStatWC1 = logUC1[1] * (thisTemp - 130)/(500 - 130) \
                + logUC1[0] * (500 - thisTemp)/(500 - 130)
            logStatWMg1 = logUMg1[1] * (thisTemp - 130)/(500 - 130) \
                + logUMg1[0] * (500 - thisTemp)/(500 - 130)
            logStatWMg2 = logUMg2[1] * (thisTemp - 130)/(500 - 130) \
                + logUMg2[0] * (500 - thisTemp)/(500 - 130)
            logStatWAl1 = logUAl1[1] * (thisTemp - 130)/(500 - 130) \
                + logUAl1[0] * (500 - thisTemp)/(500 - 130)
            logStatWSi1 = logUSi1[1] * (thisTemp - 130)/(500 - 130) \
                + logUSi1[0] * (500 - thisTemp)/(500 - 130)
            logStatWSi2 = logUSi2[1] * (thisTemp - 130)/(500 - 130) \
                + logUSi2[0] * (500 - thisTemp)/(500 - 130)
            logStatWFe1 = logUFe1[1] * (thisTemp - 130)/(500 - 130) \
                + logUFe1[0] * (500 - thisTemp)/(500 - 130)
        elif (thisTemp > 500 and thisTemp <= 3000):
            logStatWC1 = logUC1[2] * (thisTemp - 500)/(3000 - 500) \
                + logUC1[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWMg1 = logUMg1[2] * (thisTemp - 500)/(3000 - 500) \
                + logUMg1[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWMg2 = logUMg2[2] * (thisTemp - 500)/(3000 - 500) \
                + logUMg2[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWAl1 = logUAl1[2] * (thisTemp - 500)/(3000 - 500) \
                + logUAl1[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWSi1 = logUSi1[2] * (thisTemp - 500)/(3000 - 500) \
                + logUSi1[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWSi2 = logUSi2[2] * (thisTemp - 500)/(3000 - 500) \
                + logUSi2[1] * (3000 - thisTemp)/(3000 - 500)
            logStatWFe1 = logUFe1[2] * (thisTemp - 500)/(3000 - 500) \
                + logUFe1[1] * (3000 - thisTemp)/(3000 - 500)
        elif (thisTemp > 3000 and thisTemp <= 8000):
            logStatWC1 = logUC1[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUC1[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWMg1 = logUMg1[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUMg1[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWMg2 = logUMg2[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUMg2[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWAl1 = logUAl1[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUAl1[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWSi1 = logUSi1[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUSi1[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWSi2 = logUSi2[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUSi2[2] * (8000 - thisTemp)/(8000 - 3000)
            logStatWFe1 = logUFe1[3] * (thisTemp - 3000)/(8000 - 3000) \
                + logUFe1[2] * (8000 - thisTemp)/(8000 - 3000)
        elif (thisTemp > 8000 and thisTemp < 10000):
            logStatWC1 = logUC1[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUC1[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWMg1 = logUMg1[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUMg1[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWMg2 = logUMg2[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUMg2[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWAl1 = logUAl1[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUAl1[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWSi1 = logUSi1[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUSi1[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWSi2 = logUSi2[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUSi2[3] * (10000 - thisTemp)/(10000 - 8000)
            logStatWFe1 = logUFe1[4] * (thisTemp - 8000)/(10000 - 8000) \
                + logUFe1[3] * (10000 - thisTemp)/(10000 - 8000)
        else:
            #// for temperatures greater than or equal to 10000
            logStatWC1 = logUC1[4]
            logStatWMg1 = logUMg1[4]
            logStatWMg2 = logUMg2[4]
            logStatWAl1 = logUAl1[4]
            logStatWSi1 = logUSi1[4]
            logStatWSi2 = logUSi2[4]
            logStatWFe1 = logUFe1[4]

        logGroundPopsC1[iD] = stagePops[5][0][iD] - logStatWC1
        logGroundPopsMg1[iD] = stagePops[11][0][iD] - logStatWMg1
        logGroundPopsMg2[iD] = stagePops[11][1][iD] - logStatWMg2
        logGroundPopsAl1[iD] = stagePops[12][0][iD] - logStatWAl1
        logGroundPopsSi1[iD] = stagePops[13][0][iD] - logStatWSi1
        logGroundPopsSi2[iD] = stagePops[13][1][iD] - logStatWSi2
        logGroundPopsFe1[iD] = stagePops[25][0][iD] - logStatWFe1

        #// if (iD%5 == 1){
        #//     System.out.format("%03d, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f %n",
        #//          iD, logE*(logGroundPopsC1[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsMg1[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsMg2[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsAl1[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsSi1[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsSi2[iD]+temp[1][iD]+Useful.logK()),
        #//              logE*(logGroundPopsFe1[iD]+temp[1][iD]+Useful.logK()));
    #id loop// }

    #double waveno;  //cm??
    #double freq, logFreq, kapBF;
    #double stimEmExp, stimEmLogExp, stimEmLogExpHelp, stimEm;

    #//System.out.println("iD    iL    lambda    stimEm    aC1     aMg1     aMg2     aAl1    aSi1    aSi2    aFe1 ");
    for iL in range(numLams):
        #print("iL ", iL)
        #//
        #//initialization:
        for i in range(numDeps):
            aC1[i] = 0.0
            aMg1[i] = 0.0
            aMg2[i] = 0.0
            aAl1[i] = 0.0
            aSi1[i] = 0.0
            aSi2[i] = 0.0
            aFe1[i] = 0.0

        waveno = 1.0 / lambdaScale[iL]  #//cm^-1??
        logFreq = Useful.logC() - math.log(lambdaScale[iL])
        freq = math.exp(logFreq)
        #if (iL%20 == 1):
        #    print("freq ", freq)

        stimEmLogExpHelp = Useful.logH() + logFreq - Useful.logK()

        #//System.out.println("Calling opacC1 from masterMetal...");
        if (freq >= 2.0761e15):
            aC1 = opacC1(numDeps, temp, lambdaScale[iL], logGroundPopsC1)
        if (freq >= 2.997925e+14):
            #print("opacMg1 called")
            aMg1 = opacMg1(numDeps, temp, lambdaScale[iL], logGroundPopsMg1)
        if (freq >= 2.564306e15):
            aMg2 = opacMg2(numDeps, temp, lambdaScale[iL], logGroundPopsMg2)
        if (freq >= 1.443e15):
            aAl1 = opacAl1(numDeps, temp, lambdaScale[iL], logGroundPopsAl1)
        if (freq >= 2.997925e+14):
            #print("opacSi1 called")
            aSi1 = opacSi1(numDeps, temp, lambdaScale[iL], logGroundPopsSi1)
        if (freq >= 7.6869872e14):
            aSi2 = opacSi2(numDeps, temp, lambdaScale[iL], logGroundPopsSi2)
        if (waveno >= 21000.0):
            aFe1 = opacFe1(numDeps, temp, lambdaScale[iL], logGroundPopsFe1)

        for iD in range(numDeps):

            kapBF = 1.0e-99  #minimum safe value
            stimEmLogExp = stimEmLogExpHelp - temp[1][iD]
            stimEmExp = -1.0 * math.exp(stimEmLogExp)
            stimEm = (1.0 - math.exp(stimEmExp)
                      )  #//LTE correction for stimulated emission

            kapBF = kapBF + aC1[iD] + aMg1[iD] + aMg2[iD] + aAl1[iD] + aSi1[
                iD] + aSi2[iD] + aFe1[iD]
            #kapBF = aC1[iD] + aMg2[iD] + aAl1[iD] + aSi2[iD] + aFe1[iD]
            #if ( (iL%20 == 1) and (iD%10 == 1) ):
            #print("iL ", iL, " iD ", iD, " stimEm ", stimEm, " kapBF ", kapBF)
            #    print("aMg1 ", aMg1[iD], " aSi1 ", aSi1[iD])
            masterBF[iL][iD] = math.log(kapBF) + math.log(stimEm)
            #//  if ( (iD%10 == 0) && (iL%10 == 0) ) {
            #//    System.out.format("%03d, %03d, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %21.15f, %n",
            #//       iD, iL, lambdaScale[iL], Math.log10(stimEm), Math.log10(aC1[iD]), Math.log10(aMg1[iD]), Math.log10(aMg2[iD]), Math.log10(aAl1[iD]), Math.log10(aSi1[iD]), Math.log10(aSi2[iD]), Math.log10(aFe1[iD]));
            #//  }

        #} //iD

    #} //iL

    return masterBF
Пример #3
0
def planck(temp, lambda2):
    
    """ /**
 * Inputs: lambda: a single scalar wavelength in cm temp: a single scalar
 * temperature in K Returns log of Plank function in logBBlam - B_lambda
 * distribution in pure cgs units: ergs/s/cm^2/ster/cm
 */"""

    #//int numLams = (int) (( lamSetup[1] - lamSetup[0] ) / lamSetup[2]) + 1; 
    #double logBBlam; //, BBlam;

    #//double c = Useful.c; //linear
    logC = Useful.logC() # //log
    #//double k = Useful.k;  //linear
    logK = Useful.logK()  #//log
    #//double h = Useful.h;  //linear
    logH = Useful.logH()  #//log

    logPreFac = math.log(2.0) + logH + 2.0 * logC  #//log
    logExpFac = logH + logC - logK      #//log
    #//double preFac = 2.0 * h * ( c * c );  //linear
    #//double expFac = ( h / k ) * c;      //linear

    #//System.out.println("logC " + logC + " logK " + logK + " logH " + logH);
    #//System.out.println("logPreFac " + logPreFac + " logExpFac " + logExpFac);
    #//Declare scratch variables:
    #double logLam, logPreLamFac, logExpLamFac, expon, logExpon, eTerm, denom, logDenom;  //log
    #//double preLamFac, expLamFac, expon, denom; //linear

    #//for (int il = 0; il < numLams; il++){
    #//lambda = lambda[il] * 1.0E-7;  // convert nm to cm
    #//lambda = lambda * 1.0E-7;  // convert nm to cm
    logLam = math.log(lambda2) #// Do the call to log for lambda once //log
    #//System.out.println("lambda " + lambda + " logLam " + logLam);

    logPreLamFac = logPreFac - 5.0 * logLam  #//log
    logExpLamFac = logExpFac - logLam    #//log
    #//System.out.println("logPreLamFac " + logPreLamFac + " logExpLamFac " + logExpLamFac);
    #// Be VERY careful about how we divide by lambda^5:
    #//preLamFac = preFac / ( lambda * lambda ); //linear
    #//preLamFac = preLamFac / ( lambda * lambda );  //linear
    #//preLamFac = preLamFac / lambda;   //linear
    #//expLamFac = expFac / lambda;

    #//for (int id = 0; id < numDeps; id++){
    #//logExpon = logExpLamFac - temp[1][id];
        
    #//This is very subtle and dangerous!
    logExpon = logExpLamFac - math.log(temp)  #// log of hc/kTlambda
    #//System.out.println("temp " + temp + " logTemp " + Math.log(temp));
    expon = math.exp(logExpon)  #// hc/kTlambda
    #//System.out.println("logExpon " + logExpon + " expon " + expon + " denom " + denom);
    #// expon = expLamFac / temp;  //linear
    eTerm = math.exp(expon) #// e^hc/ktlambda
    denom = eTerm - 1.0 #// e^hc/ktlambda - 1
    logDenom = math.log(denom) #// log(e^hc/ktlambda - 1)

    #//BBlam[1][id][il] = logPreLamFac - logDenom;
    #//BBlam[0][id][il] = Math.exp(BBlam[1][id][il]);
    logBBlam = logPreLamFac - logDenom  #//log
    #// Not needed? BBlam = math.exp(logBBlam)  #//log
    #//BBlam = preLamFac / denom;  //linear

    #// } //id loop - depths
    #// } //il loop - lambdas
    return logBBlam;
Пример #4
0
def jolaProfilePR(omega0, logf, vibConst, jolaPoints, alphP, alphR, numDeps,
                  temp):
    """//
//JOLA profile for P (Delta J = 1) and R (Delta J = -1) branches
//Equation 19 from Zeidler & Koestler"""

    nm2cm = 1.0e-7
    log10E = math.log10(math.e)

    numPoints = len(jolaPoints)
    #// derivative of rotational-line oscillator strength with respect to frequency
    dfBydw = [[0.0 for i in range(numDeps)] for j in range(numPoints)]
    fvv = math.exp(logf)

    logHcBbyK = Useful.logH() + Useful.logC() + math.log(vibConst[0]) \
                                - Useful.logK()

    #//System.out.println("omega0 " + omega0 + " logf " + log10E*logf + " vibConst " + vibConst[0] + " " + vibConst[1] + " alphP " + alphP + " alphR " + alphR);

    Bsum = vibConst[1] + vibConst[0]
    Bdiff = vibConst[1] - vibConst[0]

    #//value of J-related "m" at band-head:
    mH = -1.0 * Bsum / (2.0 * Bdiff)  #//Eq. 14
    #//Frequency (or wavenumber??) at band head:
    wH = (-1.0 * Bdiff * mH * mH) + omega0  #//Eq. 15
    #//System.out.println("1.0/wH " + 1.0/wH + " 1.0/omega0 " + 1.0/omega0);

    mTheta1 = 1.0  #//R branch?
    mTheta2 = 1.0  #//P branch?

    #double m1, m2; // related to J, for R & P branches, respectively
    alpha1 = 1.0
    alpha2 = 1.0

    #//value of m is closely related to rotational quantum number J,
    #//Near band origin, frequency, w, range should correspond to -1 <= m <= 1 - ???:
    #//double wMin = Useful.c / (1.0e-7*jolaPoints[numPoints-1]); //first frequency omega
    #//double wMax = Useful.c / (1.0e-7*jolaPoints[0]); //last frequency omega
    #//double deltaW = 0.02;
    #double w, logW, m1Fctr, m2Fctr, mHelp, wMinuswHOverBDiff;
    #double denom1, denom2, m1Term, m2Term;
    #double help1, logHcBbyKt, hcBbyKt;

    #//Outer loop over frequency omega
    #// for (int iW = -1; iW <= 1; iW++){
    #for (int iW = numPoints-1; iW >= 0; iW--){
    for iW in range(numPoints - 1, 0, -1):
        #//dW = (double) iW;
        #//w = wMin + (dW*deltaW);
        #//logW = Useful.logC() - Math.log(1.0e-7*jolaPoints[iW]); //if w is freq in Hz
        logW = 0.0 - math.log(
            nm2cm * jolaPoints[iW])  #//if w is waveno in cm^-1
        w = math.exp(logW)
        #//System.out.println("logW " + log10E*logW);
        #//I have no idea if this is right...
        wMinuswHOverBDiff = (w - wH) / Bdiff
        mHelp = math.sqrt(abs(wMinuswHOverBDiff))  #//Eq. 17
        m1 = mH + mHelp
        m2 = mH - mHelp  #//Eq. 18
        #//System.out.println("mH " + mH + " m1 " + m1 + " m2 " + m2);
        m1Fctr = (m1 * m1 - m1)
        m2Fctr = (m2 * m2 - m2)
        #//The following association between the sign of m1 or m2 and whether
        #//it's the P or the R branch might be backwards:
        if (m1 < 0):
            alpha1 = alphP

        if (m1 >= 0):
            alpha1 = alphR

        if (m2 < 0):
            alpha2 = alphP

        if (m2 >= 0):
            alpha2 = alphR

        denom1 = abs(Bsum + 2.0 * m1 * Bdiff)
        denom2 = abs(Bsum + 2.0 * m2 * Bdiff)

        for iD in range(numDeps):

            if (wMinuswHOverBDiff > 0):

                logHcBbyKt = logHcBbyK - temp[1][iD]
                hcBbyKt = math.exp(logHcBbyKt)

                help1 = -1.0 * hcBbyKt * m1Fctr
                m1Term = alpha1 * mTheta1 * math.exp(help1) / denom1

                help1 = -1.0 * hcBbyKt * m2Fctr
                m2Term = alpha2 * mTheta2 * math.exp(help1) / denom2

                #//Can this be used like a differential cross-section (once converted to sigma)?
                #// System.out.println("fvv " + fvv + " hcBbyKt " + hcBbyKt + " m1Term " + m1Term + " m2Term " + m2Term);
                dfBydw[iW][iD] = fvv * hcBbyKt * (m1Term + m2Term)  #// Eq. 19

            else:

                dfBydw[iW][iD] = 0.0

            #}
            #// if (iD%10 == 1){
            #//   System.out.println("PR iD " + iD + " iW " + iW + " dfBydw " + dfBydw[iW][iD]);
            #// }

        #} //iD - depth loop

    #} //iW - frequency loop

    return dfBydw
Пример #5
0
def kappas2(numDeps, pe, zScale, temp, rho, numLams, lambdas, logAHe, \
            logNH1, logNH2, logNHe1, logNHe2, Ne, teff, logKapFudge):

    
    """/* Compute opacities properly from scratch with real physical cross-sections
 */ //  *** CAUTION:
//
//  This return's "kappa" as defined by Gray 3rd Ed. - cm^2 per *relelvant particle* where the "releveant particle"
//  depends on *which* kappa """
#//
#//  *** CAUTION:
#//
#//  This return's "kappa" as defined by Gray 3rd Ed. - cm^2 per *relelvant particle* where the "releveant particle"
#//  depends on *which* kappa

    log10E = math.log10(math.e) #//needed for g_ff
    logLog10E = math.log(log10E)
    logE10 = math.log(10.0)
    logNH = [0.0 for i in range(numDeps)] #//Total H particle number density cm^-3
    #double logPH1, logPH2, logPHe1, logPHe2;
    for i in range(numDeps):
        logNH[i] = math.exp(logNH1[i]) + math.exp(logNH2[i])
        logNH[i] = math.log(logNH[i])

        #//System.out.println("i " + i + " logNH1 " + log10E*logNH1[i] + " logNH2 " + log10E*logNH2[i] 
    #//+ " logNHe1 " + log10E*logNHe1[i] + " logNHe2 " + log10E*logNHe2[i] + " logPe " + log10E*pe[1][i]);
     #//   logPH1 = logNH1[i] + temp[1][i] + Useful.logK();
      #//  logPH2 = logNH2[i] + temp[1][i] + Useful.logK();
       #// logPHe1 = logNHe1[i] + temp[1][i] + Useful.logK();
       #// logPHe2 = logNHe2[i] + temp[1][i] + Useful.logK();
        #//System.out.println("i " + i + " logPH1 " + log10E*logPH1 + " logPH2 " + log10E*logPH2 
    #//+ " logPHe1 " + log10E*logPHe1 + " logPHe2 " + log10E*logPHe2 + " logPe " + log10E*pe[1][i]);
     

    #double[][] logKappa = new double[numLams][numDeps];
    logKappa = [ [0.0 for i in range(numDeps)] for j in range(numLams) ]
    #double kappa; //helper
    #double stimEm; //temperature- and wavelength-dependent stimulated emission correction  
    #double stimHelp, logStimEm;
 
    #double ii; //useful for converting integer loop counter, i, to float
#//
#//
#//Input data and variable declarations:
#//
#//
#// H I b-f & f-f
    chiIH = 13.598433  #//eV
    Rydberg = 1.0968e-2  #// "R" in nm^-1
    #//Generate threshold wavelengths and b-f Gaunt (g_bf) helper factors up to n=10:
    #double n; //principle quantum number of Bohr atom E-level
    numHlevs = 10
     #double logChiHlev;
    invThresh = [0.0 for i in range(numHlevs)] #//also serves as g_bf helper factor
    threshLambs = [0.0 for i in range(numHlevs)]
    chiHlev = [0.0 for i in range(numHlevs)]
    for i in range(numHlevs):
        n = 1.0 + float(i)
        invThresh[i] = Rydberg / n / n #//nm^-1; also serves as g_bf helper factor 
        threshLambs[i] = 1.0 / invThresh[i] #//nm
        logChiHlev = Useful.logH() + Useful.logC() + math.log(invThresh[i]) + 7.0*logE10 #// ergs
        chiHlev[i] = math.exp(logChiHlev - Useful.logEv()) #//eV
        chiHlev[i] = chiIH - chiHlev[i]
#// System.out.println("i " + i + " n " + n + " invThresh " + invThresh[i] + " threshLambs[i] " + threshLambs[i] + " chiHlev " + chiHlev[i]);

    logGauntPrefac = math.log(0.3456) - 0.333333*math.log(Rydberg)

    #// ****  Caution: this will require lamba in A!:
    a0 = 1.0449e-26  #//if lambda in A 
    logA0 = math.log(a0)
#// Boltzmann const "k" in eV/K - needed for "theta"
    logKeV = Useful.logK() - Useful.logEv() 

    #//g_bf Gaunt factor - depends on lower E-level, n:
    loggbf = [0.0 for i in range(numHlevs)]
    #//initialize quantities that depend on lowest E-level contributing to opacity at current wavelength:
    for iThresh in range(numHlevs):
        loggbf[iThresh] = 0.0
     
     #double logGauntHelp, gauntHelp; 
     #double gbf, gbfHelp, loggbfHelp;
     #double gff, gffHelp, loggffHelp, logffHelp, loggff;
     #double help, logHelp3;
     #double chiLambda, logChiLambda;
     #double bfTerm, logbfTerm, bfSum, logKapH1bf, logKapH1ff;
 
#//initial defaults:
    gbf = 1.0
    gff = 1.0
    loggff = 0.0
 
    logChiFac = math.log(1.2398e3) #// eV per lambda, for lambda in nm

#// Needed for kappa_ff: 
    #double ffBracket; 
    logffHelp = logLog10E - math.log(chiIH) - math.log(2.0)
    #//logHelp = logffHelp - math.log(2.0)

#//
#//Hminus:
#//
#// H^- b-f
#//This is for the sixth order polynomial fit to the cross-section's wavelength dependence
    numHmTerms = 7
    logAHm = [0.0 for i in range(numHmTerms)]
    signAHm = [0.0 for i in range(numHmTerms)]     
 
    aHmbf = 4.158e-10
    #//double logAHmbf = Math.log(aHmbf);
    #//Is the factor of 10^-18cm^2 from the polynomial fit to alpha_Hmbf missing in Eq. 8.12 on p. 156 of Gray 3rd Ed??
    logAHmbf = math.log(aHmbf) - 18.0*logE10
    #double alphaHmbf, logAlphaHmbf, logTermHmbf, logKapHmbf; 

    #//Computing each polynomial term logarithmically
    logAHm[0] = math.log(1.99654)
    signAHm[0] = 1.0
    logAHm[1] = math.log(1.18267e-5)
    signAHm[1] = -1.0
    logAHm[2] = math.log(2.64243e-6)
    signAHm[2] = 1.0
    logAHm[3] = math.log(4.40524e-10)
    signAHm[3] = -1.0
    logAHm[4] = math.log(3.23992e-14)
    signAHm[4] = 1.0
    logAHm[5] = math.log(1.39568e-18)
    signAHm[5] = -1.0
    logAHm[6] = math.log(2.78701e-23)
    signAHm[6] = 1.0
    alphaHmbf = math.exp(logAHm[0]) #//initialize accumulator

#// H^- f-f:

    logAHmff = -26.0*logE10
    numHmffTerms = 5
    #double fPoly, logKapHmff, logLambdaAFac; 
    fHmTerms = [ [ 0.0 for i in range(numHmffTerms) ] for j in range(3) ]
    fHm = [0.0 for i in range(3)]
    fHmTerms[0][0] = -2.2763
    fHmTerms[0][1] = -1.6850
    fHmTerms[0][2] = 0.76661
    fHmTerms[0][3] = -0.053346
    fHmTerms[0][4] = 0.0
    fHmTerms[1][0] = 15.2827
    fHmTerms[1][1] = -9.2846
    fHmTerms[1][2] = 1.99381
    fHmTerms[1][3] = -0.142631
    fHmTerms[1][4] = 0.0
    fHmTerms[2][0] = -197.789
    fHmTerms[2][1] = 190.266
    fHmTerms[2][2] = -67.9775
    fHmTerms[2][3] = 10.6913
    fHmTerms[2][4] = -0.625151

#//
#//H_2^+ molecular opacity - cool stars
#// scasles with proton density (H^+)
#//This is for the third order polynomial fit to the "sigma_l(lambda)" and "U_l(lambda)"
#//terms in the cross-section
    numH2pTerms = 4
    sigmaH2pTerm = [0.0 for i in range(numH2pTerms)]
    UH2pTerm = [0.0 for i in range(numH2pTerms)]
    #double logSigmaH2p, sigmaH2p, UH2p, logKapH2p;  
    aH2p = 2.51e-42
    logAH2p = math.log(aH2p)
    sigmaH2pTerm[0] = -1040.54
    sigmaH2pTerm[1] = 1345.71
    sigmaH2pTerm[2] = -547.628
    sigmaH2pTerm[3] = 71.9684
    #//UH2pTerm[0] = 54.0532
    #//UH2pTerm[1] = -32.713
    #//UH2pTerm[2] = 6.6699
    #//UH2pTerm[3] = -0.4574
    #//Reverse signs on U_1 polynomial expansion co-efficients - Dave Gray private communcation 
    #//based on Bates (1952)
    UH2pTerm[0] = -54.0532
    UH2pTerm[1] = 32.713
    UH2pTerm[2] = -6.6699
    UH2pTerm[3] = 0.4574
 

#// He I b-f & ff: 
    #double totalH1Kap, logTotalH1Kap, helpHe, logKapHe;

#//
#//He^- f-f
  
    AHe = math.exp(logAHe) 
    #double logKapHemff, nHe, logNHe, thisTerm, thisLogTerm, alphaHemff, log10AlphaHemff;

#// Gray does not have this pre-factor, but PHOENIX seems to and without it
#// the He opacity is about 10^26 too high!:
    logAHemff = -26.0*logE10

    numHemffTerms = 5
    logC0HemffTerm = [0.0 for i in range(numHemffTerms)]
    logC1HemffTerm = [0.0 for i in range(numHemffTerms)]
    logC2HemffTerm = [0.0 for i in range(numHemffTerms)]
    logC3HemffTerm = [0.0 for i in range(numHemffTerms)]
    signC0HemffTerm = [0.0 for i in range(numHemffTerms)]
    signC1HemffTerm = [0.0 for i in range(numHemffTerms)]
    signC2HemffTerm = [0.0 for i in range(numHemffTerms)]
    signC3HemffTerm = [0.0 for i in range(numHemffTerms)]

#//we'll be evaluating the polynominal in theta logarithmically by adding logarithmic terms - 
    logC0HemffTerm[0] = math.log(9.66736) 
    signC0HemffTerm[0] = 1.0
    logC0HemffTerm[1] = math.log(71.76242) 
    signC0HemffTerm[1] = -1.0
    logC0HemffTerm[2] = math.log(105.29576) 
    signC0HemffTerm[2] = 1.0
    logC0HemffTerm[3] = math.log(56.49259) 
    signC0HemffTerm[3] = -1.0
    logC0HemffTerm[4] = math.log(10.69206) 
    signC0HemffTerm[4] = 1.0
    logC1HemffTerm[0] = math.log(10.50614) 
    signC1HemffTerm[0] = -1.0
    logC1HemffTerm[1] = math.log(48.28802) 
    signC1HemffTerm[1] = 1.0
    logC1HemffTerm[2] = math.log(70.43363) 
    signC1HemffTerm[2] = -1.0
    logC1HemffTerm[3] = math.log(37.80099) 
    signC1HemffTerm[3] = 1.0
    logC1HemffTerm[4] = math.log(7.15445)
    signC1HemffTerm[4] = -1.0
    logC2HemffTerm[0] = math.log(2.74020)
    signC2HemffTerm[0] = 1.0
    logC2HemffTerm[1] = math.log(10.62144) 
    signC2HemffTerm[1] = -1.0
    logC2HemffTerm[2] = math.log(15.50518) 
    signC2HemffTerm[2] = 1.0
    logC2HemffTerm[3] = math.log(8.33845)
    signC2HemffTerm[3] = -1.0
    logC2HemffTerm[4] = math.log(1.57960)
    signC2HemffTerm[4] = 1.0
    logC3HemffTerm[0] = math.log(0.19923)
    signC3HemffTerm[0] = -1.0
    logC3HemffTerm[1] = math.log(0.77485)
    signC3HemffTerm[1] = 1.0
    logC3HemffTerm[2] = math.log(1.13200)
    signC3HemffTerm[2] = -1.0
    logC3HemffTerm[3] = math.log(0.60994)
    signC3HemffTerm[3] = 1.0
    logC3HemffTerm[4] = math.log(0.11564)
    signC3HemffTerm[4] = -1.0
#    //initialize accumulators:
    cHemff = [0.0 for i in range(4)]
    cHemff[0] = signC0HemffTerm[0] * math.exp(logC0HemffTerm[0]);   
    cHemff[1] = signC1HemffTerm[0] * math.exp(logC1HemffTerm[0]);   
    cHemff[2] = signC2HemffTerm[0] * math.exp(logC2HemffTerm[0]);   
    cHemff[3] = signC3HemffTerm[0] * math.exp(logC3HemffTerm[0]);   
#//
#//Should the polynomial expansion for the Cs by in 10g10Theta??  No! Doesn't help:
    #//double[] C0HemffTerm = new double[numHemffTerms];
    #//double[] C1HemffTerm = new double[numHemffTerms];
    #//double[] C2HemffTerm = new double[numHemffTerms];
    #//double[] C3HemffTerm = new double[numHemffTerms];
#//
    #//C0HemffTerm[0] = 9.66736; 
    #//C0HemffTerm[1] = -71.76242; 
    #//C0HemffTerm[2] = 105.29576; 
    #//C0HemffTerm[3] = -56.49259; 
    #//C0HemffTerm[4] = 10.69206; 
    #//C1HemffTerm[0] = -10.50614; 
    #//C1HemffTerm[1] = 48.28802; 
    #//C1HemffTerm[2] = -70.43363; 
    #//C1HemffTerm[3] = 37.80099; 
    #//C1HemffTerm[4] = -7.15445;
    #//C2HemffTerm[0] = 2.74020; 
    #//C2HemffTerm[1] = -10.62144; 
    #//C2HemffTerm[2] = 15.50518; 
    #//C2HemffTerm[3] = -8.33845; 
    #//C2HemffTerm[4] = 1.57960;
    #//C3HemffTerm[0] = -0.19923; 
    #//C3HemffTerm[1] = 0.77485; 
    #//C3HemffTerm[2] = -1.13200; 
    #//C3HemffTerm[3] = 0.60994; 
    #//C3HemffTerm[4] = -0.11564;
    #//initialize accumulators:
    #// double[] cHemff = new double[4];
    #// cHemff[0] = C0HemffTerm[0];   
    #// cHemff[1] = C1HemffTerm[0];   
    #// cHemff[2] = C2HemffTerm[0];   
    #// cHemff[3] = C3HemffTerm[0];   

#//
#// electron (e^-1) scattering (Thomson scattering)

    #double kapE, logKapE;
    alphaE = 0.6648e-24 #//cm^2/e^-1
    logAlphaE = math.log(0.6648e-24)
  

#//Universal:
#//
#     double theta, logTheta, log10Theta, log10ThetaFac;
#     double logLambda, lambdaA, logLambdaA, log10LambdaA, lambdanm, logLambdanm;
#//Okay - here we go:
#//Make the wavelength loop the outer loop - lots of depth-independnet lambda-dependent quantities:
#//
#//
#   //System.out.println("Kappas called...");
#//
#//  **** START WAVELENGTH LOOP iLam
#//
#//
#//
    for iLam in range(numLams):
 #//
 #//Re-initialize all accumulators to be on safe side:
        kappa = 0.0
        logKapH1bf = -99.0 
        logKapH1ff = -99.0
        logKapHmbf = -99.0 
        logKapHmff = -99.0
        logKapH2p = -99.0
        logKapHe = -99.0
        logKapHemff = -99.0
        logKapE = -99.0
#//
#//*** CAUTION: lambda MUST be in nm here for consistency with Rydbeg 
        logLambda = math.log(lambdas[iLam])  #//log cm
        lambdanm = 1.0e7 * lambdas[iLam]
        logLambdanm = math.log(lambdanm)
        lambdaA = 1.0e8 * lambdas[iLam] #//Angstroms
        logLambdaA = math.log(lambdaA)
        log10LambdaA = log10E * logLambdaA

        logChiLambda = logChiFac - logLambdanm
        chiLambda = math.exp(logChiLambda)   #//eV

#// Needed for both g_bf AND g_ff: 
        logGauntHelp = logGauntPrefac - 0.333333*logLambdanm #//lambda in nm here
        gauntHelp = math.exp(logGauntHelp)

  #//            if (iLam == 142){
   #// System.out.println("lambdaA " + lambdaA);
   #//         }

#//HI b-f depth independent factors:
#//Start at largest threshold wavelength and break out of loop when next threshold lambda is less than current lambda:
        #for (iThresh = numHlevs-1; iThresh >= 0; iThresh--){
        for iThresh in range(0, numHlevs-1, -1):
            if (threshLambs[iThresh] < lambdanm):
                break
           
            if (lambdanm <= threshLambs[iThresh]):
           #//this E-level contributes
                loggbfHelp = logLambdanm + math.log(invThresh[iThresh]) # //lambda in nm here; invThresh here as R/n^2
                gbfHelp = math.exp(loggbfHelp)
                gbf = 1.0 - (gauntHelp * (gbfHelp - 0.5))
#//              if (iLam == 1){}
#//    System.out.println("iThresh " + iThresh + " threshLambs " + threshLambs[iThresh] +  " gbf " + gbf);
#//              }
                loggbf[iThresh] = math.log(gbf)
           
        #//end iThresh loop 

#//HI f-f depth independent factors:
#        //logChi = logLog10E + logLambdanm - logChiFac; //lambda in nm here
#        //chi = Math.exp(logChi);
        loggffHelp = logLog10E - logChiLambda

#//
#//
#//
#//  ******  Start depth loop iTau ******
#//
#//
#//
#//
        for iTau in range(numDeps):
#//
# //Re-initialize all accumulators to be on safe side:
            kappa = 0.0
            logKapH1bf = -99.0 
            logKapH1ff = -99.0
            logKapHmbf = -99.0 
            logKapHmff = -99.0
            logKapH2p = -99.0
            logKapHe = -99.0
            logKapHemff = -99.0
            logKapE = -99.0
#//
#//
#//if (iTau == 36 && iLam == 142){
#//    System.out.println("lambdanm[142] " + lambdanm + " temp[0][iTau=36] " + temp[0][iTau=36]);
#// }
#//This is "theta" ~ 5040/T:
            logTheta = logLog10E - logKeV - temp[1][iTau]
            log10Theta = log10E * logTheta
            theta = math.exp(logTheta)
            #//System.out.println("theta " + theta + " logTheta " + logTheta);

#// temperature- and wavelength-dependent stimulated emission coefficient:
            stimHelp = -1.0 * theta * chiLambda * logE10
            stimEm = 1.0 - math.exp(stimHelp)
            logStimEm = math.log(stimEm)
# //          if (iTau == 36 && iLam == 142){
# //   System.out.println("stimEm " + stimEm);
# //}


            ffBracket = math.exp(loggffHelp - logTheta) + 0.5 
            gff = 1.0 + (gauntHelp*ffBracket)


#//if (iTau == 36 && iLam == 1){
#//    System.out.println("gff " + gff);
#// }
            loggff = math.log(gff)

#//H I b-f:
#//Start at largest threshold wavelength and break out of loop when next threshold lambda is less than current lambda:
            bfSum = 0.0 #//initialize accumulator
            logHelp3 = logA0 + 3.0*logLambdaA #//lambda in A here
            #for (int iThresh = numHlevs-1; iThresh >= 0; iThresh--){
            for iThresh in range(0, numHlevs-1, -1):
                if (threshLambs[iThresh] < lambdanm):
                    break
              
            n = 1.0 + float(iThresh)
            if (lambdanm <= threshLambs[iThresh]):
                #//this E-level contributes
                logbfTerm = loggbf[iThresh] - 3.0*math.log(n) 
                logbfTerm = logbfTerm - (theta*chiHlev[iThresh])*logE10 
                bfSum = bfSum + math.exp(logbfTerm)
#//if (iTau == 36 && iLam == 142){
#  //System.out.println("lambdanm " + lambdanm + " iThresh " + iThresh + " threshLambs[iThresh] " + threshLambs[iThresh]);
#  //System.out.println("loggbf " + loggbf[iThresh] + " theta " + theta + " chiHlev " + chiHlev[iThresh]);
#  //System.out.println("bfSum " + bfSum + " logbfTerm " + logbfTerm);
#//  }
              
            #//end iThresh loop 

#// cm^2 per *neutral* H atom
            logKapH1bf = logHelp3 + math.log(bfSum) 

#//Stimulated emission correction
            logKapH1bf = logKapH1bf + logStimEm
#//System.out.println("lambda " + lambdas[iLam] + "iTau " + iTau + " sigma " + Math.exp(logKapH1bf)); 

#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
            logKapH1bf = logKapH1bf + logNH1[iTau]
#//System.out.println(" aH1 " + Math.exp(logKapH1bf)); 
#////Nasty fix to make Balmer lines show up in A0 stars!
#//     if (teff > 8000){
#//          logKapH1bf = logKapH1bf - logE10*1.5;
#//     
            kappa = math.exp(logKapH1bf) 
#//System.out.println("HIbf " + log10E*logKapH1bf);
#//if (iTau == 36 && iLam == 142){
#//           System.out.println("lambdaA " + lambdaA + " logKapH1bf " + log10E*(logKapH1bf)); //-rho[1][iTau]));
#//}
#//H I f-f:
#// cm^2 per *neutral* H atom
            logKapH1ff = logHelp3 + loggff + logffHelp - logTheta - (theta*chiIH)*logE10

#//Stimulated emission correction
            logKapH1ff = logKapH1ff + logStimEm
#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
            logKapH1ff = logKapH1ff + logNH1[iTau]
#////Nasty fix to make Balmer lines show up in A0 stars!
#//     if (teff > 8000){
#//          logKapH1ff = logKapH1ff - logE10*1.5;
#//     
            kappa = kappa + math.exp(logKapH1ff); 
#//System.out.println("HIff " + log10E*logKapH1ff);

#//if (iTau == 36 && iLam == 142){
#//           System.out.println("logKapH1ff " + log10E*(logKapH1ff)); //-rho[1][iTau]));
#//}

#//
#//Hminus:
#//
#// H^- b-f:
#//if (iTau == 36 && iLam == 142){
# // System.out.println("temp " + temp[0][iTau] + " lambdanm " + lambdanm);
# // }
            logKapHmbf =  -99.0 #//initialize default
            #//if ( (temp[0][iTau] > 2500.0) && (temp[0][iTau] < 10000.0) ){
            #//if ( (temp[0][iTau] > 2500.0) && (temp[0][iTau] < 8000.0) ){
            #//Try lowering lower Teff limit to avoid oapcity collapse in outer layers of late-type stars
            if ( (temp[0][iTau] > 1000.0) and (temp[0][iTau] < 10000.0) ):
                if ((lambdanm > 225.0) and (lambdanm < 1500.0) ):  # //nm 
#//if (iTau == 36 && iLam == 142){
# //              System.out.println("In KapHmbf condition...");
#//}
                    ii = 0.0
                    alphaHmbf = signAHm[0]*math.exp(logAHm[0]) #//initialize accumulator
                    #for (int i = 1; i < numHmTerms; i++){
                    for i in range(1, numHmTerms):
                        ii = float(i)
#//if (iTau == 36 && iLam == 142){
#//                   System.out.println("ii " + ii);
#//}
                        logTermHmbf = logAHm[i] + ii*logLambdaA 
                        alphaHmbf = alphaHmbf + signAHm[i]*math.exp(logTermHmbf)  
#//if (iTau == 36 && iLam == 142){
#//                  System.out.println("logTermHmbf " + log10E*logTermHmbf + " i " + i + " logAHm " + log10E*logAHm[i]); 
#//}
                
                    logAlphaHmbf = math.log(alphaHmbf)
#// cm^2 per neutral H atom
                    logKapHmbf = logAHmbf + logAlphaHmbf + pe[1][iTau] + 2.5*logTheta + (0.754*theta)*logE10 
#//Stimulated emission correction
                    logKapHmbf = logKapHmbf + logStimEm
#//if (iTau == 36 && iLam == 142){
#//  System.out.println("alphaHmbf " + alphaHmbf);
#//  System.out.println("logKapHmbf " + log10E*logKapHmbf + " logAHmbf " + log10E*logAHmbf + " logAlphaHmbf " + log10E*logAlphaHmbf);
#//  }

#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
                    logKapHmbf = logKapHmbf + logNH1[iTau]
                    kappa = kappa + math.exp(logKapHmbf)
#//System.out.println("Hmbf " + log10E*logKapHmbf);
#//if (iTau == 36 && iLam == 142){
#//           System.out.println("logKapHmbf " + log10E*(logKapHmbf)); //-rho[1][iTau]));
#//}
                #//wavelength condition
            #// temperature condition

#// H^- f-f:
            logKapHmff = -99.0 #//initialize default
          #//if ( (temp[0][iTau] > 2500.0) && (temp[0][iTau] < 10000.0) ){
          #//Try lowering lower Teff limit to avoid oapcity collapse in outer layers of late-type stars
          #//if ( (temp[0][iTau] > 2500.0) && (temp[0][iTau] < 8000.0) ){
            if ( (temp[0][iTau] > 1000.0) and (temp[0][iTau] < 10000.0) ):
                if ((lambdanm > 260.0) and (lambdanm < 11390.0) ): #//nm 
                    #//construct "f_n" polynomials in log(lambda)
                    for j in range(3):
                        fHm[j] = fHmTerms[j][0]  #//initialize accumulators                        
                    ii = 0.0  
                    for i in range(1, numHmffTerms):
                        ii = float(i)
                        logLambdaAFac = math.pow(log10LambdaA, ii)
                        for j in range(3):
                            fHm[j] = fHm[j] + (fHmTerms[j][i]*logLambdaAFac)    
                        #} #// i
                    #} #// j
#// 
                    fPoly = fHm[0] + fHm[1]*log10Theta + fHm[2]*log10Theta*log10Theta
#// In cm^2 per neutral H atom:
#// Stimulated emission alreadya ccounted for
                    logKapHmff = logAHmff + pe[1][iTau] + fPoly*logE10

#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
                    logKapHmff = logKapHmff + logNH1[iTau]
                    kappa = kappa + math.exp(logKapHmff)
#//System.out.println("Hmff " + log10E*logKapHmff);
#//if (iTau == 36 && iLam == 142){
#//           System.out.println("logKapHmff " + log10E*(logKapHmff)); //-rho[1][iTau]));
#//}
                #//wavelength condition
            #// temperature condition


#// H^+_2:
#//
            logKapH2p = -99.0 #//initialize default 
            if ( temp[0][iTau] < 4000.0 ):
                if ((lambdanm > 380.0) and (lambdanm < 2500.0) ): # //nm 
                    sigmaH2p = sigmaH2pTerm[0] #//initialize accumulator
                    UH2p = UH2pTerm[0] #//initialize accumulator
                    ii = 0.0#
                    for i in range(1, numH2pTerms):
                        ii = float(i) 
                        logLambdaAFac = math.pow(log10LambdaA, ii)
                        #// kapH2p way too large with lambda in A - try cm:  No! - leads to negative logs
                        #//logLambdaAFac = Math.pow(logLambda, ii);
                        sigmaH2p = sigmaH2p +  sigmaH2pTerm[i] * logLambdaAFac 
                        UH2p = UH2p +  UH2pTerm[i] * logLambdaAFac                    
                    logSigmaH2p = math.log(sigmaH2p)
                    logKapH2p = logAH2p + logSigmaH2p - (UH2p*theta)*logE10 + logNH2[iTau] 
#//Stimulated emission correction
                    logKapH2p = logKapH2p + logStimEm

#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
                    logKapH2p = logKapH2p + logNH1[iTau]
                    kappa = kappa + math.exp(logKapH2p) 
#//System.out.println("H2p " + log10E*logKapH2p);
#//if (iTau == 16 && iLam == 142){
#           //System.out.println("logKapH2p " + log10E*(logKapH2p-rho[1][iTau]) + " logAH2p " + log10E*logAH2p
#// + " logSigmaH2p " + log10E*logSigmaH2p + " (UH2p*theta)*logE10 " + log10E*((UH2p*theta)*logE10) + " logNH2[iTau] " + log10E*logNH2[iTau]);
#//}
                #//wavelength condition
            #// temperature condition


#//He I 
#//
#//  HeI b-f + f-f
#//Scale sum of He b-f and f-f with sum of HI b-f and f-f 

#//wavelength condition comes from requirement that lower E level be greater than n=2 (edge at 22.78 nm)
            logKapHe = -99.0 #//default intialization
            if ( temp[0][iTau] > 10000.0 ):
                if (lambdanm > 22.8): #//nm  
                    totalH1Kap = math.exp(logKapH1bf) + math.exp(logKapH1ff)
                    logTotalH1Kap = math.log(totalH1Kap) 
                    helpHe = Useful.k() * temp[0][iTau]
#// cm^2 per neutral H atom (after all, it's scaled wrt kappHI
#// Stimulated emission already accounted for
#//
#//  *** CAUTION: Is this *really* the right thing to do???
#//    - we're re-scaling the final H I kappa in cm^2/g corrected for stim em, NOT the raw cross section
                    logKapHe = math.log(4.0) - (10.92 / helpHe) + logTotalH1Kap

#//Add it in to total - opacity per neutral HI atom, so multiply by logNH1 
#// This is now linear opacity in cm^-1
                    logKapHe = logKapHe + logNH1[iTau]
                    kappa = kappa + math.exp(logKapHe) 
#//System.out.println("He " + log10E*logKapHe);
#//if (iTau == 36 && iLam == 142){
#//           System.out.println("logKapHe " + log10E*(logKapHe)); //-rho[1][iTau]));
#//}
                #//wavelength condition
            #// temperature condition


#//
#//He^- f-f:
            logKapHemff = -99.0 #//default initialization
            if ( (theta > 0.5) and (theta < 2.0) ):
                if ((lambdanm > 500.0) and (lambdanm < 15000.0) ): 

#// initialize accumulators:
                    cHemff[0] = signC0HemffTerm[0]*math.exp(logC0HemffTerm[0]);   
                    #//System.out.println("C0HemffTerm " + signC0HemffTerm[0]*Math.exp(logC0HemffTerm[0]));
                    cHemff[1] = signC1HemffTerm[0]*math.exp(logC1HemffTerm[0]);   
                    #//System.out.println("C1HemffTerm " + signC1HemffTerm[0]*Math.exp(logC1HemffTerm[0]));
                    cHemff[2] = signC2HemffTerm[0]*math.exp(logC2HemffTerm[0]);   
                    #//System.out.println("C2HemffTerm " + signC2HemffTerm[0]*Math.exp(logC2HemffTerm[0]));
                    cHemff[3] = signC3HemffTerm[0]*math.exp(logC3HemffTerm[0]);   
                    #//System.out.println("C3HemffTerm " + signC3HemffTerm[0]*Math.exp(logC3HemffTerm[0]));
#//build the theta polynomial coefficients
                    ii = 0.0
                    for i in range(1, numHemffTerms):
                        ii = float(i)
                        thisLogTerm = ii*logTheta + logC0HemffTerm[i] 
                        cHemff[0] = cHemff[0] + signC0HemffTerm[i]*math.exp(thisLogTerm) 
                        #//System.out.println("i " + i + " ii " + ii + " C0HemffTerm " + signC0HemffTerm[i]*Math.exp(logC0HemffTerm[i]));
                        thisLogTerm = ii*logTheta + logC1HemffTerm[i] 
                        cHemff[1] = cHemff[1] + signC1HemffTerm[i]*math.exp(thisLogTerm) 
                        #//System.out.println("i " + i + " ii " + ii + " C1HemffTerm " + signC1HemffTerm[i]*Math.exp(logC1HemffTerm[i]));
                        thisLogTerm = ii*logTheta + logC2HemffTerm[i]
                        cHemff[2] = cHemff[2] + signC2HemffTerm[i]*math.exp(thisLogTerm) 
                        #//System.out.println("i " + i + " ii " + ii + " C2HemffTerm " + signC2HemffTerm[i]*Math.exp(logC2HemffTerm[i]));
                        thisLogTerm = ii*logTheta + logC3HemffTerm[i] 
                        cHemff[3] = cHemff[3] + signC3HemffTerm[i]*math.exp(thisLogTerm) 
                        #//System.out.println("i " + i + " ii " + ii + " C3HemffTerm " + signC3HemffTerm[i]*Math.exp(logC3HemffTerm[i]));
     
    #//// Should polynomial expansion for Cs be in log10Theta??: - No! Doesn't help
    #// initialize accumulators:
    #// cHemff[0] = C0HemffTerm[0];   
    #// cHemff[1] = C1HemffTerm[0];   
    #// cHemff[2] = C2HemffTerm[0];   
    #// cHemff[3] = C3HemffTerm[0];   
    #// ii = 0.0;
    #// for (int i = 1; i < numHemffTerms; i++){
    #//    ii = (double) i;
    #//    log10ThetaFac = Math.pow(log10Theta, ii);
    #//    thisTerm = log10ThetaFac * C0HemffTerm[i]; 
    #//    cHemff[0] = cHemff[0] + thisTerm; 
    #//    thisTerm = log10ThetaFac * C1HemffTerm[i]; 
    #//    cHemff[1] = cHemff[1] + thisTerm; 
    #//    thisTerm = log10ThetaFac * C2HemffTerm[i]; 
    #//    cHemff[2] = cHemff[2] + thisTerm; 
    #//    thisTerm = log10ThetaFac * C3HemffTerm[i]; 
    #//    cHemff[3] = cHemff[3] + thisTerm; 
    #// }
     
#//Build polynomial in logLambda for alpha(He^1_ff):
                    log10AlphaHemff = cHemff[0] #//initialize accumulation
                    #//System.out.println("cHemff[0] " + cHemff[0]);
                    ii = 0.0
                    for i in range(1, 3+1):
                        #//System.out.println("i " + i + " cHemff[i] " + cHemff[i]);
                        ii = float(i)
                        thisTerm = cHemff[i] * math.pow(log10LambdaA, ii)
                        log10AlphaHemff = log10AlphaHemff + thisTerm 
        
                    #//System.out.println("log10AlphaHemff " + log10AlphaHemff);
                    alphaHemff = math.pow(10.0, log10AlphaHemff) #//gives infinite alphas!
                    #// alphaHemff = log10AlphaHemff; // ?????!!!!!
                    #//System.out.println("alphaHemff " + alphaHemff);

#// Note: this is the extinction coefficient per *Hydrogen* particle (NOT He- particle!)
#       //nHe = Math.exp(logNHe1[iTau]) + Math.exp(logNHe2[iTau]);
#       //logNHe = Math.log(nHe);
#       //logKapHemff = Math.log(alphaHemff) + Math.log(AHe) + pe[1][iTau] + logNHe1[iTau] - logNHe;
                    logKapHemff = logAHemff + math.log(alphaHemff) + pe[1][iTau] + logNHe1[iTau] - logNH[iTau]

#//Stimulated emission already accounted for
#//Add it in to total - opacity per H particle, so multiply by logNH 
#// This is now linear opacity in cm^-1
                    logKapHemff = logKapHemff + logNH[iTau]
                    kappa = kappa + math.exp(logKapHemff) 
#//System.out.println("Hemff " + log10E*logKapHemff);
#//if (iTau == 36 && iLam == 155){
#//if (iLam == 155){
#//           System.out.println("logKapHemff " + log10E*(logKapHemff)); //-rho[1][iTau]));
#//}
 
                #//wavelength condition
            #// temperature condition

#//
#// electron (e^-1) scattering (Thomson scattering)

#//coefficient per *"hydrogen atom"* (NOT per e^-!!) (neutral or total H??):
            logKapE = logAlphaE + Ne[1][iTau] - logNH[iTau]

#//Stimulated emission not relevent 
#//Add it in to total - opacity per H particle, so multiply by logNH 
#// This is now linear opacity in cm^-1
#//I know, we're adding logNH right back in after subtracting it off, but this is for dlarity and consistency for now... :
            logKapE = logKapE + logNH[iTau]   
            kappa = kappa + math.exp(logKapE) 
#//System.out.println("E " + log10E*logKapE);
#//if (iTau == 36 && iLam == 142){
#//           System.out.println("logKapE " + log10E*(logKapE)); //-rho[1][iTau]));
#//}

#//Metal b-f
#//Fig. 8.6 Gray 3rd Ed.
#//

#//
#// This is now linear opacity in cm^-1
#// Divide by mass density
#// This is now mass extinction in cm^2/g
#//
            logKappa[iLam][iTau] = math.log(kappa) - rho[1][iTau]
#// Fudge is in cm^2/g:  Converto to natural log:
            logEKapFudge = logE10 * logKapFudge
            logKappa[iLam][iTau] = logKappa[iLam][iTau] + logEKapFudge
#//if (iTau == 36 && iLam == 142){
#//System.out.println(" " + log10E*(logKappa[iLam][iTau]+rho[1][iTau]));
#//}


        #// close iTau depth loop
#//
    #//close iLam wavelength loop 

    return logKappa
Пример #6
0
def jolaProfileQ(omega0, logf, vibConst, jolaPoints, alphQ, numDeps, temp):
    """//JOLA profile for Q (Delta J = 0) branch
//Equation 24 from Zeidler & Koestler"""

    nm2cm = 1.0e-7
    numPoints = len(jolaPoints)
    #// derivative of rotational-line oscillator strength with respect to frequency

    dfBydw = [[0.0 for i in range(numDeps)] for j in range(numPoints)]
    fvv = math.exp(logf)
    logHcBbyK = Useful.logH() + Useful.logC() + math.log(vibConst[0]) \
                                - Useful.logK()

    Bsum = vibConst[1] + vibConst[0]
    Bdiff = vibConst[1] - vibConst[0]

    #double mQ; #// related to J, for R & P branches, respectively

    #//value of m is closely related to rotational quantum number J,
    #//Near band origin, frequency, w, range should correspond to -1 <= m <= 1 - ???:
    #//      double wMin = Useful.c / (1.0e-7*lambda[1]); //first frequency omega
    #//     double wMax = Useful.c / (1.0e-7*lambda[0]); //last frequency omega
    #//    double deltaW = 0.02;
    #double w, logW, mQFctr, mHelp;
    #double denom, mQTerm, wMinusw0OverBDiff;
    #double help1, logHcBbyKt, hcBbyKt;

    #//Outer loop over frequency omega
    #//for (int iW = -1; iW <= 1; iW++){
    #for (int iW = numPoints-1; iW >= 0; iW--){
    for iW in range(numPoints - 1, 0, -1):
        #//dW = (double) iW;
        #//w = wMin + (dW*deltaW);
        #//logW = Useful.logC() - Math.log(1.0e-7*jolaPoints[iW]); //if w is freq in Hz
        logW = 0.0 - math.log(
            nm2cm * jolaPoints[iW])  #//if w is waveno in cm^-1
        w = math.exp(logW)

        #//I have no idea if this is right...
        wMinusw0OverBDiff = (w - omega0) / Bdiff
        mHelp = 0.25 + math.abs(wMinusw0OverBDiff)
        mHelp = math.sqrt(mHelp)  #//Eq. 17
        mQ = -0.5 + mHelp
        mQFctr = (mQ * mQ - mQ)
        denom = math.abs(Bdiff)

        for iD in range(numDeps):

            if (wMinusw0OverBDiff > 0):

                logHcBbyKt = logHcBbyK - temp[1][iD]
                hcBbyKt = math.exp(logHcBbyKt)

                help1 = -1.0 * hcBbyKt * mQFctr
                mQTerm = math.exp(help1) / denom

                #//Can this be used like a differential cross-section (once converted to sigma)?
                #//System.out.println("alphQ " + alphQ + " fvv " + " logHcBbyKt " + logHcBbyKt + " mQTerm " + mQTerm);
                dfBydw[iW][iD] = alphQ * fvv * hcBbyKt * mQTerm  #// Eq. 24

            else:

                dfBydw[iW][iD] = 0.0

            #//if (iD%10 == 1){
            #//System.out.println("Q iD " + iD + " iW " + iW + " dfBydw " + dfBydw[iW][iD]);
            #//}

        #//iD - depth loop

    #} //iW - frequency loop

    return dfBydw
Пример #7
0
def jolaKap(jolaLogNums, dfBydw, jolaPoints, numDeps, temp, rho):

    log10E = math.log10(math.e)
    nm2cm = 1.0e-7

    numPoints = len(jolaPoints)

    logKappaJola = [[0.0 for i in range(numDeps)] for j in range(numPoints)]
    #//Initialize this carefully:

    for iD in range(numDeps):
        for iW in range(numPoints):
            logKappaJola[iW][iD] = -999.0

    #double stimEmExp, stimEmLogExp, stimEmLogExpHelp, stimEm;
    #double freq, lastFreq, w, lastW, deltaW, thisDeltaF;
    logSigma = -999.0
    logFreq = Useful.logC() - math.log(nm2cm * jolaPoints[0])
    logW = 0.0 - math.log(nm2cm * jolaPoints[0])  #//if w is waveno in cm^-1
    #//lastFreq = Math.exp(logFreq)
    lastW = math.exp(logW)

    #//try accumulating oscillator strenth, f, across band - assumes f = 0 at first (largest) lambda- ??
    thisF = 0.0

    #//If f is cumulative in wavenumber, then we have to make the wavenumber loop the inner one even if it
    #//means re-calculating depth-independent quantities each time:
    for iD in range(numDeps):

        thisF = 0.0  #//re-set accumulator

        #//loop in order of *increasing* wavenumber
        #for (int iW = numPoints-1; iW >=1; iW--){
        for iW in range(numPoints - 1, 1, -1):

            #//df/dv is a differential oscillator strength in *frequency* space:
            logFreq = Useful.logC() - math.log(nm2cm * jolaPoints[iW])
            freq = math.exp(logFreq)
            logW = 0.0 - math.log(
                nm2cm * jolaPoints[iW])  #//if w is waveno in cm^-1
            w = math.exp(logW)  #//if w is waveno in cm^-1
            #//System.out.println("w " + w);
            #//deltaW = Math.abs(freq - lastFreq);
            deltaW = abs(w - lastW)

            #//For LTE stimulated emission correction:
            stimEmLogExpHelp = Useful.logH() + logFreq - Useful.logK()

            #//        for (int iD = 0; iD < numDeps; iD++){

            thisDeltaF = deltaW * dfBydw[iW][iD]
            if (thisDeltaF > 0.0):
                #thisF += thisDeltaF #//cumulative version
                thisF = thisDeltaF
                #//non-cumulative version
                logSigma = math.log(thisF) + math.log(
                    math.pi) + 2.0 * Useful.logEe() - Useful.logMe(
                    ) - Useful.logC()
            else:
                logSigma = -999.0

            #// LTE stimulated emission correction:
            stimEmLogExp = stimEmLogExpHelp - temp[1][iD]
            stimEmExp = -1.0 * math.exp(stimEmLogExp)
            stimEm = (1.0 - math.exp(stimEmExp))

            #//extinction coefficient in cm^2 g^-1:
            logKappaJola[iW][iD] = logSigma + jolaLogNums[iD] - rho[1][
                iD] + math.log(stimEm)
            #//logKappaJola[iW][iD] = -999.0;
            #//if (iD%10 == 1){
            #//System.out.println("iD " + iD + " iW " + iW + " logFreq " + log10E*logFreq + " logW " + log10E*logW + " logStimEm " + log10E*Math.log(stimEm));
            #//System.out.println("iD " + iD + " iW " + iW + " thisDeltaF " + thisDeltaF + " logSigma " + log10E*logSigma + " jolaLogNums " + log10E*jolaLogNums[iD] + " rho " + log10E*rho[1][iD] + " logKappaJola " + log10E*logKappaJola[iW][iD]);
            #//}

            #//        } //iD loop - depths

            lastFreq = freq
        #} //iW loop - wavelength

    #} //iD loop - depths

    return logKappaJola
Пример #8
0
def molPops(nmrtrLogNumB, nmrtrDissE, logUwA, nmrtrLogUwB, nmrtrLogQwAB, nmrtrLogMuAB, \
            numMolsB, logNumB, dissEArr, logUwB, logQwABArr, logMuABArr,   \
            logGroundRatio, numDeps, temp):
    # line 1: //species A data - ionization equilibrium of A
    # //data for set of species "B" - molecular equlibrium for set {AB}
    """Diatomic molecular equilibrium routine that accounts for molecule formation:
 // Returns depth distribution of molecular population 

// Input parameters:
// logNum - array with depth-dependent total element number densities (cm^-3) 
// chiI1 - ground state ionization energy of neutral stage 
// chiI2 - ground state ionization energy of singly ionized stage 
// Also needs atsmopheric structure information:
// numDeps
// temp structure 
// rho structure
//
// Atomic element "A" is the one kept on the LHS of the master fraction, whose ionization fractions are included 
//   in the denominator of the master fraction
//  Element "B" refers to array of other sintpecies with which A forms molecules "AB" """

    logE = math.log10(math.e)  #// for debug output
    #//System.out.println("molPops: nmrtrDissE " + nmrtrDissE + " log10UwA " + log10UwA[0] + " " + log10UwA[1] + " nmrtrLog10UwB " +
    #//     nmrtrLog10UwB[0] + " " + nmrtrLog10UwB[1] + " nmrtrLog10QwAB " + logE*nmrtrLogQwAB[2] + " nmrtrLogMuAB " + logE*nmrtrLogMuAB
    #//     + " numMolsB " + numMolsB + " dissEArr " + dissEArr[0] + " log10UwBArr " + log10UwBArr[0][0] + " " + log10UwBArr[0][1] + " log10QwABArr " +
    #//     logE*logQwABArr[0][2] + " logMuABArr " + logE*logMuABArr[0]);
    #//System.out.println("Line: nmrtrLog10UwB[0] " + logE*nmrtrLog10UwB[0] + " nmrtrLog10UwB[1] " + logE*nmrtrLog10UwB[1]);

    ln10 = math.log(10.0)
    log2pi = math.log(2.0 * math.pi)
    log2 = math.log(2.0)

    logE10 = math.log(10.0)
    #// Convert to natural logs:
    #double Ttheta, thisTemp;

    #//Treat at least one molecule - if there are really no molecules for an atomic species,
    #//there will be one phantom molecule in the denominator of the ionization fraction
    #//with an impossibly high dissociation energy
    if (numMolsB == 0):
        numMolsB = 1
        #//This should be inherited, but let's make sure:
        dissEArr[0] = 29.0  #//eV

    #//var molPops = function(logNum, numeratorLogNumB, numeratorDissE, numeratorLog10UwA, numeratorLog10QwAB, numeratorLogMuAB,  //species A data - ionization equilibrium of A
    #//Molecular partition functions - default initialization:
    thisLogUwB = [0.0 for i in range(numMolsB)]

    for iMol in range(numMolsB):
        thisLogUwB[
            iMol] = 0.0  #// variable for temp-dependent computed partn fn of array element B

    thisLogUwA = 0.0  #// element A
    nmrtrThisLogUwB = 0.0  #// element A
    thisLogQwAB = math.log(300.0)
    nmrtrThisLogQwAB = math.log(300.0)

    #//For clarity: neutral stage of atom whose ionization equilibrium is being computed is element A
    #// for molecule formation:
    #logUwA = [0.0 for i in range(5)]

    #nmrtrLogUwB = [0.0 for i in range(5)]

    #for kk in range(len(logUwA)):
    #logUwA[kk] = logE10*log10UwA[kk]
    #nmrtrLogUwB[kk] = logE10*nmrtrLog10UwB[kk]

    #// lburns

    #// Array of elements B for all molecular species AB:
    #double[][] logUwB = new double[numMolsB][2];
    #logUwB = [ [ 0.0 for i in range(5) ] for j in range(numMolsB) ]
    #//if (numMolsB > 0){
    #for iMol in range(numMolsB):
    #    for kk in range(5):
    #        logUwB[iMol][kk] = logE10*log10UwBArr[iMol][kk]
    # // lburns new loop

    #//}
    #// Molecular partition functions:
    #//       double nmrtrLogQwAB = logE10*nmrtrLog10QwAB;
    #//       double[] logQwAB = new double[numMolsB];
    #//      //if (numMolsB > 0){
    #//       for (int iMol = 0; iMol < numMolsB; iMol++){
    #//          logQwAB[iMol] = logE10*log10QwABArr[iMol];
    #//       }
    #      //}
    #//Molecular dissociation Boltzmann factors:
    nmrtrBoltzFacIAB = 0.0
    nmrtrLogMolSahaFac = 0.0
    logDissE = math.log(nmrtrDissE) + Useful.logEv()
    #//System.out.println("logDissE " + logE*logDissE)
    logBoltzFacIAB = logDissE - Useful.logK()
    #//System.out.println("logBoltzFacIAB " + logE*logBoltzFacIAB);
    nmrtrBoltzFacIAB = math.exp(logBoltzFacIAB)
    nmrtrLogMolSahaFac = (3.0 / 2.0) * (log2pi + nmrtrLogMuAB + Useful.logK() -
                                        2.0 * Useful.logH())
    #//System.out.println("nmrtrLogMolSahaFac " + logE*nmrtrLogMolSahaFac);
    #//System.out.println("nmrtrDissE " + nmrtrDissE + " logDissE " + logE*logDissE + " logBoltzFacIAB " + logE*logBoltzFacIAB + " nmrtrBoltzFacIAB " + nmrtrBoltzFacIAB + " nmrtrLogMuAB " + logE*nmrtrLogMuAB + " nmrtrLogMolSahaFac " + logE*nmrtrLogMolSahaFac);

    boltzFacIAB = [0.0 for i in range(numMolsB)]
    logMolSahaFac = [0.0 for i in range(numMolsB)]
    #//if (numMolsB > 0){
    for iMol in range(numMolsB):
        logDissE = math.log(dissEArr[iMol]) + Useful.logEv()
        logBoltzFacIAB = logDissE - Useful.logK()
        boltzFacIAB[iMol] = math.exp(logBoltzFacIAB)
        logMolSahaFac[iMol] = (3.0 / 2.0) * (
            log2pi + logMuABArr[iMol] + Useful.logK() - 2.0 * Useful.logH())
#//System.out.println("logMolSahaFac[iMol] " + logE*logMolSahaFac[iMol]);
#//System.out.println("iMol " + iMol + " dissEArr[iMol] " + dissEArr[iMol] + " logDissE " + logE*logDissE + " logBoltzFacIAB " + logE*logBoltzFacIAB + " boltzFacIAB[iMol] " + boltzFacIAB[iMol] + " logMuABArr " + logE*logMuABArr[iMol] + " logMolSahaFac " + logE*logMolSahaFac[iMol]);

#//double[] logNums = new double[numDeps]

#//}
#//   For molecular species:
#double nmrtrSaha, nmrtrLogSahaMol, nmrtrLogInvSahaMol; //, nmrtrInvSahaMol;
    logMolFrac = [0.0 for i in range(numDeps)]
    logSahaMol = [0.0 for i in range(numMolsB)]
    invSahaMol = [0.0 for i in range(numMolsB)]
    #//
    #//  System.out.println("molPops: id      nmrtrLogNumB      logNumBArr[0]      logGroundRatio");
    for id in range(numDeps):

        #//System.out.format("%03d, %21.15f, %21.15f, %21.15f, %n", id, logE*nmrtrLogNumB[id], logE*logNumB[0][id], logE*logGroundRatio[id]);

        #//// reduce or enhance number density by over-all Rosseland opcity scale parameter

        #//Determine temparature dependent partition functions Uw:
        thisTemp = temp[0][id]
        #Ttheta = 5040.0 / thisTemp
        """
        if (Ttheta >= 1.0):
            thisLogUwA = logUwA[0]
            nmrtrThisLogUwB = nmrtrLogUwB[0]
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][0]
           
       
        if (Ttheta <= 0.5):
            thisLogUwA = logUwA[1]
            nmrtrThisLogUwB = nmrtrLogUwB[1]
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][1]
           
        if (Ttheta > 0.5 and Ttheta < 1.0):
            thisLogUwA = ( logUwA[1] * ((Ttheta - 0.5)/(1.0 - 0.5)) ) \
            + ( logUwA[0] * ((1.0 - Ttheta)/(1.0 - 0.5)) )
            nmrtrThisLogUwB = ( nmrtrLogUwB[1] * ((Ttheta - 0.5)/(1.0 - 0.5)) ) \
            + ( nmrtrLogUwB[0] * ((1.0 - Ttheta)/(1.0 - 0.5)) )
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = ( logUwB[iMol][1] * ((Ttheta - 0.5)/(1.0 - 0.5)) ) \
                + ( logUwB[iMol][0] * ((1.0 - Ttheta)/(1.0 - 0.5)) )
        """

        #// NEW Determine temperature dependent partition functions Uw: lburns
        thisTemp = temp[0][id]
        if (thisTemp <= 130):
            thisLogUwA = logUwA[0]
            nmrtrThisLogUwB = nmrtrLogUwB[0]
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][0]

        if (thisTemp > 130 and thisTemp <= 500):
            thisLogUwA = logUwA[1] * (thisTemp - 130)/(500 - 130) \
                       + logUwA[0] * (500 - thisTemp)/(500 - 130)
            nmrtrThisLogUwB = nmrtrLogUwB[1] * (thisTemp - 130)/(500 - 130) \
                            + nmrtrLogUwB[0] * (500 - thisTemp)/(500 - 130)
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][1] * (thisTemp - 130)/(500 - 130) \
                                 + logUwB[iMol][0] * (500 - thisTemp)/(500 - 130)

        if (thisTemp > 500 and thisTemp <= 3000):
            thisLogUwA = logUwA[2] * (thisTemp - 500)/(3000 - 500) \
                       + logUwA[1] * (3000 - thisTemp)/(3000 - 500)
            nmrtrThisLogUwB = nmrtrLogUwB[2] * (thisTemp - 500)/(3000 - 500) \
                            + nmrtrLogUwB[1] * (3000 - thisTemp)/(3000 - 500)
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][2] * (thisTemp - 500)/(3000 - 500) \
                                 + logUwB[iMol][1] * (3000 - thisTemp)/(3000 - 500)

        if (thisTemp > 3000 and thisTemp <= 8000):
            thisLogUwA = logUwA[3] * (thisTemp - 3000)/(8000 - 3000) \
                       + logUwA[2] * (8000 - thisTemp)/(8000 - 3000)
            nmrtrThisLogUwB = nmrtrLogUwB[3] * (thisTemp - 3000)/(8000 - 3000) \
                            + nmrtrLogUwB[2] * (8000 - thisTemp)/(8000 - 3000)
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][3] * (thisTemp - 3000)/(8000 - 3000) \
                                 + logUwB[iMol][2] * (8000 - thisTemp)/(8000 - 3000)

        if (thisTemp > 8000 and thisTemp < 10000):
            thisLogUwA = logUwA[4] * (thisTemp - 8000)/(10000 - 8000) \
                       + logUwA[3] * (10000 - thisTemp)/(10000 - 8000)
            nmrtrThisLogUwB = nmrtrLogUwB[4] * (thisTemp - 8000)/(10000 - 8000) \
                            + nmrtrLogUwB[3] * (10000 - thisTemp)/(10000 - 8000)
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][4] * (thisTemp - 8000)/(10000 - 8000) \
                                + logUwB[iMol][3] * (10000 - thisTemp)/(10000 - 8000)

        if (thisTemp >= 10000):
            thisLogUwA = logUwA[4]
            nmrtrThisLogUwB = nmrtrLogUwB[4]
            for iMol in range(numMolsB):
                thisLogUwB[iMol] = logUwB[iMol][4]

        for iMol in range(numMolsB):
            if (thisTemp < 3000.0):
                thisLogQwAB = ( logQwABArr[iMol][1] * (3000.0 - thisTemp)/(3000.0 - 500.0) ) \
                + ( logQwABArr[iMol][2] * (thisTemp - 500.0)/(3000.0 - 500.0) )
            if ((thisTemp >= 3000.0) and (thisTemp <= 8000.0)):
                thisLogQwAB = ( logQwABArr[iMol][2] * (8000.0 - thisTemp)/(8000.0 - 3000.0) ) \
                + ( logQwABArr[iMol][3] * (thisTemp - 3000.0)/(8000.0 - 3000.0) )
            if (thisTemp > 8000.0):
                thisLogQwAB = ( logQwABArr[iMol][3] * (10000.0 - thisTemp)/(10000.0 - 8000.0) ) \
                + ( logQwABArr[iMol][4] * (thisTemp - 8000.0)/(10000.0 - 8000.0) )
            if (thisTemp < 3000.0):
                nmrtrThisLogQwAB = ( nmrtrLogQwAB[1] * (3000.0 - thisTemp)/(3000.0 - 500.0) ) \
                + ( nmrtrLogQwAB[2] * (thisTemp - 500.0)/(3000.0 - 500.0) )
            if ((thisTemp >= 3000.0) and (thisTemp <= 8000.0)):
                nmrtrThisLogQwAB = ( nmrtrLogQwAB[2] * (8000.0 - thisTemp)/(8000.0 - 3000.0) ) \
                + ( nmrtrLogQwAB[3] * (thisTemp - 3000.0)/(8000.0 - 3000.0) )
            if (thisTemp > 8000.0):
                nmrtrThisLogQwAB = ( nmrtrLogQwAB[3] * (10000.0 - thisTemp)/(10000.0 - 8000.0) ) \
                + ( nmrtrLogQwAB[4] * (thisTemp - 8000.0)/(10000.0 - 8000.0) )

#//For clarity: neutral stage of atom whose ionization equilibrium is being computed is element A
#// for molecule formation:

#   //Ionization stage Saha factors:
#//System.out.println("id " + id + " nmrtrLogNumB[id] " + logE*nmrtrLogNumB[id]);
#  // if (id == 16){
#  //   System.out.println("id " + id + " nmrtrLogNumB[id] " + logE*nmrtrLogNumB[id] + " pp nmrtB " + (logE*(nmrtrLogNumB[id]+temp[1][id]+Useful.logK())) + " nmrtrThisLogUwB " + logE*nmrtrThisLogUwB + " thisLogUwA " + logE*thisLogUwA + " nmrtrLogQwAB " + logE*nmrtrThisLogQwAB);
#   //System.out.println("nmrtrThisLogUwB " + logE*nmrtrThisLogUwB + " thisLogUwA " + logE*thisLogUwA + " nmrtrThisLogQwAB " + logE*nmrtrThisLogQwAB);
#   // }
        nmrtrLogSahaMol = nmrtrLogMolSahaFac - nmrtrLogNumB[id] - (
            nmrtrBoltzFacIAB / temp[0][id]) + (
                3.0 * temp[1][id] /
                2.0) + nmrtrThisLogUwB + thisLogUwA - nmrtrThisLogQwAB
        nmrtrLogInvSahaMol = -1.0 * nmrtrLogSahaMol
        #//System.out.println("nmrtrLogInvSahaMol " + logE*nmrtrLogInvSahaMol);
        #//nmrtrInvSahaMol = Math.exp(nmrtrLogSahaMol);
        #//   if (id == 16){
        #//       System.out.println("nmrtrLogInvSahaMol " + logE*nmrtrLogInvSahaMol);
        #//   }
        #//   if (id == 16){
        #//        System.out.println("nmrtrBoltzFacIAB " + nmrtrBoltzFacIAB + " nmrtrThisLogUwB " + logE*nmrtrThisLogUwB + " thisLogUwA " + logE*thisLogUwA + " nmrtrThisLogQwAB " + nmrtrThisLogQwAB);
        #//        System.out.println("nmrtrLogSahaMol " + logE*nmrtrLogSahaMol); // + " nmrtrInvSahaMol " + nmrtrInvSahaMol);
        #//   }

        #//Molecular Saha factors:
        for iMol in range(numMolsB):
            #//System.out.println("iMol " + iMol + " id " + id + " logNumB[iMol][id] " + logE*nmrtrLogNumB[id]);
            #//System.out.println("iMol " + iMol + " thisLogUwB[iMol] " + logE*thisLogUwB[iMol] + " thisLogUwA " + logE*thisLogUwA + " thisLogQwAB " + logE*thisLogQwAB);
            logSahaMol[iMol] = logMolSahaFac[iMol] - logNumB[iMol][id] - (
                boltzFacIAB[iMol] / temp[0][id]) + (
                    3.0 * temp[1][id] /
                    2.0) + thisLogUwB[iMol] + thisLogUwA - thisLogQwAB
            #//For denominator of ionization fraction, we need *inverse* molecular Saha factors (N_AB/NI):
            logSahaMol[iMol] = -1.0 * logSahaMol[iMol]
            invSahaMol[iMol] = math.exp(logSahaMol[iMol])
            #//TEST invSahaMol[iMol] = 1.0e-99; //test
    #//     if (id == 16){
    #//         System.out.println("iMol " + iMol + " boltzFacIAB[iMol] " + boltzFacIAB[iMol] + " thisLogUwB[iMol] " + logE*thisLogUwB[iMol] + " logQwAB[iMol] " + logE*thisLogQwAB + " logNumB[iMol][id] " + logE*logNumB[iMol][id] + " logMolSahaFac[iMol] " + logE*logMolSahaFac[iMol]);
    #//         System.out.println("iMol " + iMol + " logSahaMol " + logE*logSahaMol[iMol] + " invSahaMol[iMol] " + invSahaMol[iMol]);
    #//     }

#//Compute log of denominator is ionization fraction, f_stage
#        //default initialization
#        //  - ratio of total atomic particles in all ionization stages to number in ground state:
        denominator = math.exp(
            logGroundRatio[id]
        )  #//default initialization - ratio of total atomic particles in all ionization stages to number in ground state
        #//molecular contribution
        for iMol in range(numMolsB):
            #//  if (id == 16){
            #//   System.out.println("invSahaMol[iMol] " + invSahaMol[iMol] + " denominator " + denominator);
            #//  }
            denominator = denominator + invSahaMol[iMol]

#//
        logDenominator = math.log(denominator)
        #//System.out.println("logGroundRatio[id] " + logE*logGroundRatio[id] + " logDenominator " + logE*logDenominator);
        #//  if (id == 16){
        #// System.out.println("id " + id + " logGroundRatio " + logGroundRatio[id] + " logDenominator " + logDenominator);
        #//  }
        #//if (id == 36){
        #//     System.out.println("logDenominator " + logE*logDenominator);
        #// }
        #//var logDenominator = Math.log( 1.0 + saha21 + (saha32 * saha21) + (saha43 * saha32 * saha21) + (saha54 * saha43 * saha32 * saha21) );

        logMolFrac[id] = nmrtrLogInvSahaMol - logDenominator
        #//  if (id == 16){
        #//       System.out.println("id " + id + " logMolFrac[id] " + logE*logMolFrac[id]);
        #//  }

        #//logNums[id] = logNum[id] + logMolFrac;
    #} //id loop

    return logMolFrac
Пример #9
0
def sahaRHS(chiI, logUwU, logUwL, temp):
    """RHS of partial pressure formulation of Saha equation in standard form (N_U*P_e/N_L on LHS)
 // Returns depth distribution of LHS: Phi(T) === N_U*P_e/N_L (David Gray notation)

// Input parameters:
// chiI - ground state ionization energy of lower stage 
// log10UwUArr, log10UwLArr - array of temperature-dependent partition function for upper and lower ionization stage
// Also needs atsmopheric structure information:
// numDeps
// temp structure 
//
// Atomic element "A" is the one whose ionization fractions are being computed
//  Element "B" refers to array of other species with which A forms molecules "AB" """

    ln10 = math.log(10.0)
    logE = math.log10(math.e)  #// for debug output
    log2pi = math.log(2.0 * math.pi)
    log2 = math.log(2.0)

    #//    var numMols = dissEArr.length;

    #// Parition functions passed in are 2-element vectore with remperature-dependent base 10 log Us
    #// Convert to natural logs:
    #double Ttheta, thisTemp;
    #//Default initializations:
    #//We need one more stage in size of saha factor than number of stages we're actualy populating
    thisLogUwU = 0.0
    thisLogUwL = 0.0

    logE10 = math.log(10.0)
    #//We need one more stage in size of saha factor than number of stages we're actualy populating
    #logUwU = [0.0 for i in range(5)]
    #logUwL = [0.0 for i in range(5)]
    for kk in range(len(logUwL)):
        logUwU[kk] = logUwL[kk]
    #   logUwL[kk] = logE10*log10UwLArr[kk]

    #//System.out.println("chiL before: " + chiL);
    #// If we need to subtract chiI from chiL, do so *before* converting to tiny numbers in ergs!

#//atomic ionization stage Boltzmann factors:
#double logChiI, logBoltzFacI;
#double boltzFacI;
    logChiI = math.log(chiI) + Useful.logEv()
    logBoltzFacI = logChiI - Useful.logK()
    boltzFacI = math.exp(logBoltzFacI)

    #//Extra factor of k to get k^5/2 in the P_e formulation of Saha Eq.
    logSahaFac = log2 + (3.0 / 2.0) * (log2pi + Useful.logMe() + Useful.logK()
                                       - 2.0 * Useful.logH()) + Useful.logK()

    #//double[] logLHS = new double[numDeps];
    #double logLHS;

    #//   For atomic ionization stages:
    #double logSaha, saha, expFac;

    #//  for (int id = 0; id < numDeps; id++) {

    #//
    #//Determine temperature dependent partition functions Uw:
    thisTemp = temp[0]
    #Ttheta = 5040.0 / thisTemp
    """         
    if (Ttheta >= 1.0):
        thisLogUwU = logUwU[0]
        thisLogUwL = logUwL[0]
       
    if (Ttheta <= 0.5):
        thisLogUwU = logUwU[1]
        thisLogUwL = logUwL[1]
       
    if (Ttheta > 0.5 and Ttheta < 1.0):
        thisLogUwU = ( logUwU[1] * (Ttheta - 0.5)/(1.0 - 0.5) )
        + ( logUwU[0] * (1.0 - Ttheta)/(1.0 - 0.5) )
        thisLogUwL = ( logUwL[1] * (Ttheta - 0.5)/(1.0 - 0.5) )
        + ( logUwL[0] * (1.0 - Ttheta)/(1.0 - 0.5) )
    """

    if (thisTemp <= 130):
        thisLogUwU = logUwU[0]
        thisLogUwL = logUwL[0]

    if (thisTemp > 130 and thisTemp <= 500):
        thisLogUwU = logUwU[1] * (thisTemp - 130)/(500 - 130) \
            + logUwU[0] * (500 - thisTemp)/(500 - 130)
        thisLogUwL = logUwL[1] * (thisTemp - 130)/(500 - 130) \
            + logUwL[0] * (500 - thisTemp)/(500 - 130)

    if (thisTemp > 500 and thisTemp <= 3000):
        thisLogUwU = logUwU[2] * (thisTemp - 500)/(3000 - 500) \
            + logUwU[1] * (3000 - thisTemp)/(3000 - 500)
        thisLogUwL = logUwL[2] * (thisTemp - 500)/(3000 - 500) \
            + logUwL[1] * (3000 - thisTemp)/(3000 - 500)

    if (thisTemp > 3000 and thisTemp <= 8000):
        thisLogUwU = logUwU[3] * (thisTemp - 3000)/(8000 - 3000) \
            + logUwU[2] * (8000 - thisTemp)/(8000 - 3000)
        thisLogUwL = logUwL[3] * (thisTemp - 3000)/(8000 - 3000) \
            + logUwL[2] * (8000 - thisTemp)/(8000 - 3000)

    if (thisTemp > 8000 and thisTemp < 10000):
        thisLogUwU = logUwU[4] * (thisTemp - 8000)/(10000 - 8000) \
            + logUwU[3] * (10000 - thisTemp)/(10000 - 8000)
        thisLogUwL = logUwL[4] * (thisTemp - 8000)/(10000 - 8000) \
            + logUwL[3] * (10000 - thisTemp)/(10000 - 8000)

    if (thisTemp >= 10000):
        thisLogUwU = logUwU[4]
        thisLogUwL = logUwL[4]

#//Ionization stage Saha factors:

#//Need T_kin^5/2 in the P_e formulation of Saha Eq.
    logSaha = logSahaFac - (boltzFacI / temp[0]) + (
        5.0 * temp[1] / 2.0) + thisLogUwU - thisLogUwL
    #// saha = Math.exp(logSaha);

    #//logLHS[id] = logSaha;
    logLHS = logSaha
    #//    } //id loop

    return logLHS
Пример #10
0
def stagePops2(logNum, Ne, chiIArr, logUw,  \
               numMols, logNumB, dissEArr, logUwB, logQwABArr, logMuABArr, \
               numDeps, temp):
    #line 1: //species A data - ionization equilibrium of A
    #line 2: //data for set of species "B" - molecular equlibrium for set {AB}
    """Ionization equilibrium routine that accounts for molecule formation:
    // Returns depth distribution of ionization stage populations 

    // Input parameters:
    // logNum - array with depth-dependent total element number densities (cm^-3) 
    // chiI1 - ground state ionization energy of neutral stage 
    // chiI2 - ground state ionization energy of singly ionized stage 
    // Also needs atsmopheric structure information:
    // numDeps
    // temp structure 
    // rho structure
    // Atomic element A is the one whose ionization fractions are being computed
    //  Element B refers to array of other species with which A forms molecules AB """

    ln10 = math.log(10.0)
    logE = math.log10(math.e)  #// for debug output
    log2pi = math.log(2.0 * math.pi)
    log2 = math.log(2.0)

    numStages = len(
        chiIArr
    )  #// + 1; //need one more stage above the highest stage to be populated

    #//    var numMols = dissEArr.length;

    #// Parition functions passed in are 2-element vectore with remperature-dependent base 10 log Us
    #// Convert to natural logs:
    #double Ttheta, thisTemp;
    #//Default initializations:
    #//We need one more stage in size of saha factor than number of stages we're actualy populating
    thisLogUw = [0.0 for i in range(numStages + 1)]
    for i in range(numStages + 1):
        thisLogUw[i] = 0.0

    logE10 = math.log(10.0)
    #//We need one more stage in size of saha factor than number of stages we're actualy populating
    #double[][] logUw = new double[numStages+1][2];
    #logUw = [ [ 0.0 for i in range(5) ] for j in range(numStages+1) ]
    #for i in range(numStages):
    #    for kk in range(5):
    #        logUw[i][kk] = logE10*log10UwAArr[i][kk]
    #// lburns- what variable can we use instead of 5?

    #//Assume ground state statistical weight (or partition fn) of highest stage is 1.0;
    #//var logGw5 = 0.0;

    #for kk in range(5):
    #    logUw[numStages][kk] = 0.0
    #// lburns

    #//System.out.println("chiL before: " + chiL);
    #// If we need to subtract chiI from chiL, do so *before* converting to tiny numbers in ergs!

    #//atomic ionization stage Boltzmann factors:
    #double logChiI, logBoltzFacI;
    boltzFacI = [0.0 for i in range(numStages)]
    #print("numStages ", numStages, " Useful.logEv ", Useful.logEv())
    for i in range(numStages):
        #print("i ", i, " chiIArr ", chiIArr[i])
        logChiI = math.log(chiIArr[i]) + Useful.logEv()
        logBoltzFacI = logChiI - Useful.logK()
        boltzFacI[i] = math.exp(logBoltzFacI)

    logSahaFac = log2 + (3.0 / 2.0) * (log2pi + Useful.logMe() +
                                       Useful.logK() - 2.0 * Useful.logH())

    #// return a 2D 5 x numDeps array of logarithmic number densities
    #// Row 0: neutral stage ground state population
    #// Row 1: singly ionized stage ground state population
    #// Row 2: doubly ionized stage ground state population
    #// Row 3: triply ionized stage ground state population
    #// Row 4: quadruply ionized stage ground state population
    #double[][] logNums = new double[numStages][numDeps];
    logNums = [[0.0 for i in range(numDeps)] for j in range(numStages)]

    #//We need one more stage in size of saha factor than number of stages we're actualy populating
    #//   for index accounting pirposes
    #//   For atomic ionization stages:
    # double[][] logSaha = new double[numStages+1][numStages+1];
    # double[][] saha = new double[numStages+1][numStages+1];
    logSaha = [[0.0 for i in range(numStages + 1)]
               for j in range(numStages + 1)]
    saha = [[0.0 for i in range(numStages + 1)] for j in range(numStages + 1)]
    #//

    logIonFrac = [0.0 for i in range(numStages)]
    #double expFac, logNe;

    #// Now - molecular variables:

    #//Treat at least one molecule - if there are really no molecules for an atomic species,
    #//there will be one phantom molecule in the denominator of the ionization fraction
    #//with an impossibly high dissociation energy
    ifMols = True
    if (numMols == 0):
        ifMols = False
        numMols = 1
        #//This should be inherited, but let's make sure:
        dissEArr[0] = 19.0  #//eV

#//Molecular partition functions - default initialization:
#double[] thisLogUwB = new double[numMols];
    thisLogUwB = [0.0 for i in range(numMols)]
    for iMol in range(numMols):
        thisLogUwB[
            iMol] = 0.0  #// variable for temp-dependent computed partn fn of array element B

    thisLogUwA = 0.0  #// element A
    thisLogQwAB = math.log(300.0)

    #//For clarity: neutral stage of atom whose ionization equilibrium is being computed is element A
    #// for molecule formation:
    logUwA = [0.0 for i in range(5)]
    if (numMols > 0):
        for kk in range(len(logUwA)):
            logUwA[kk] = logUw[0][kk]
        #// lburns

#// Array of elements B for all molecular species AB:
#double[][] logUwB = new double[numMols][2];
#logUwB = [ [ 0.0 for i in range(5) ] for j in range(numMols) ]
#//if (numMols > 0){
#for iMol in range(numMols):
#    for kk in range(5):
#        #print("iMol ", iMol, " kk ", kk)
#        logUwB[iMol][kk] = logE10*log10UwBArr[iMol][kk]
#// lburns new loop

#//}
#//// Molecular partition functions:
#//       double[] logQwAB = new double[numMols];
#//      //if (numMols > 0){
#//       for (int iMol = 0; iMol < numMols; iMol++){
#//          logQwAB[iMol] = logE10*log10QwABArr[iMol];
#//       }
#      //}
#//Molecular dissociation Boltzmann factors:
    boltzFacIAB = [0.0 for i in range(numMols)]
    logMolSahaFac = [0.0 for i in range(numMols)]
    #//if (numMols > 0){
    #double logDissE, logBoltzFacIAB;
    for iMol in range(numMols):
        logDissE = math.log(dissEArr[iMol]) + Useful.logEv()
        logBoltzFacIAB = logDissE - Useful.logK()
        boltzFacIAB[iMol] = math.exp(logBoltzFacIAB)
        logMolSahaFac[iMol] = (3.0 / 2.0) * (
            log2pi + logMuABArr[iMol] + Useful.logK() - 2.0 * Useful.logH())
        #//console.log("iMol " + iMol + " dissEArr[iMol] " + dissEArr[iMol] + " logDissE " + logE*logDissE + " logBoltzFacIAB " + logE*logBoltzFacIAB + " boltzFacIAB[iMol] " + boltzFacIAB[iMol] + " logMuABArr " + logE*logMuABArr[iMol] + " logMolSahaFac " + logE*logMolSahaFac[iMol]);

    #//}
#//   For molecular species:
    logSahaMol = [0.0 for i in range(numMols)]
    invSahaMol = [0.0 for i in range(numMols)]

    for id in range(numDeps):

        #//// reduce or enhance number density by over-all Rosseland opcity scale parameter
        #//
        #//Row 1 of Ne is log_e Ne in cm^-3
        logNe = Ne[1][id]

        #//Determine temperature dependent partition functions Uw:
        thisTemp = temp[0][id]
        #Ttheta = 5040.0 / thisTemp
        """         
        if (Ttheta >= 1.0):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][0]
           
            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][0]
           
            
       
        if (Ttheta <= 0.5):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][1]
           
            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][1]
           
       
        if (Ttheta > 0.5 and Ttheta < 1.0):
            for iStg in range(numStages):
                thisLogUw[iStg] = ( logUw[iStg][1] * (Ttheta - 0.5)/(1.0 - 0.5) ) \
                                + ( logUw[iStg][0] * (1.0 - Ttheta)/(1.0 - 0.5) )
        """

        #// NEW Determine temperature dependent partition functions Uw: lburns
        if (thisTemp <= 130):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][0]

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][0]

        if (thisTemp > 130 and thisTemp <= 500):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][1] * (thisTemp - 130)/(500 - 130) \
                                + logUw[iStg][0] * (500 - thisTemp)/(500 - 130)

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][1] * (thisTemp - 130)/(500 - 130) \
                                 + logUwB[iMol][0] * (500 - thisTemp)/(500 - 130)

        if (thisTemp > 500 and thisTemp <= 3000):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][2] * (thisTemp - 500)/(3000 - 500) \
                                + logUw[iStg][1] * (3000 - thisTemp)/(3000 - 500)

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][2] * (thisTemp - 500)/(3000 - 500) \
                                 + logUwB[iMol][1] * (3000 - thisTemp)/(3000 - 500)

        if (thisTemp > 3000 and thisTemp <= 8000):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][3] * (thisTemp - 3000)/(8000 - 3000) \
                                + logUw[iStg][2] * (8000 - thisTemp)/(8000 - 3000)

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][3] * (thisTemp - 3000)/(8000 - 3000) \
                                 + logUwB[iMol][2] * (8000 - thisTemp)/(8000 - 3000)

        if (thisTemp > 8000 and thisTemp < 10000):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][4] * (thisTemp - 8000)/(10000 - 8000) \
                                + logUw[iStg][3] * (10000 - thisTemp)/(10000 - 8000)

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][4] * (thisTemp - 8000)/(10000 - 8000) \
                                 + logUwB[iMol][3] * (10000 - thisTemp)/(10000 - 8000)

        if (thisTemp >= 10000):
            for iStg in range(numStages):
                thisLogUw[iStg] = logUw[iStg][4]

            for iMol in range(numMols):
                thisLogUwB[iMol] = logUwB[iMol][4]

        thisLogUw[numStages] = 0.0
        for iMol in range(numMols):
            if (thisTemp < 3000.0):
                thisLogQwAB = ( logQwABArr[iMol][1] * (3000.0 - thisTemp)/(3000.0 - 500.0) ) \
                            + ( logQwABArr[iMol][2] * (thisTemp - 500.0)/(3000.0 - 500.0) )

            if ((thisTemp >= 3000.0) and (thisTemp <= 8000.0)):
                thisLogQwAB = ( logQwABArr[iMol][2] * (8000.0 - thisTemp)/(8000.0 - 3000.0) ) \
                            + ( logQwABArr[iMol][3] * (thisTemp - 3000.0)/(8000.0 - 3000.0) )

            if (thisTemp > 8000.0):
                thisLogQwAB = ( logQwABArr[iMol][3] * (10000.0 - thisTemp)/(10000.0 - 8000.0) ) \
                            + ( logQwABArr[iMol][4] * (thisTemp - 8000.0)/(10000.0 - 8000.0) )

        #// iMol loop

#//For clarity: neutral stage of atom whose ionization equilibrium is being computed is element A
#// for molecule formation:
        thisLogUwA = thisLogUw[0]

        #//Ionization stage Saha factors:
        for iStg in range(numStages):
            #print("iStg ", iStg)
            #stop
            logSaha[iStg + 1][iStg] = logSahaFac - logNe - (
                boltzFacI[iStg] /
                temp[0][id]) + (3.0 * temp[1][id] /
                                2.0) + thisLogUw[iStg + 1] - thisLogUw[iStg]
            saha[iStg + 1][iStg] = math.exp(logSaha[iStg + 1][iStg])

            #// if (id == 36){
            #// console.log("iStg " + iStg + " boltzFacI[iStg] " + boltzFacI[iStg] + " thisLogUw[iStg] " + logE*thisLogUw[iStg] + " thisLogUw[iStg+1] " + logE*thisLogUw[iStg+1]);
            #// console.log("iStg+1 " + (iStg+1) + " iStg " + iStg + " logSahaji " + logE*logSaha[iStg+1][iStg] + " saha[iStg+1][iStg] " + saha[iStg+1][iStg]);
        #// }

#//Molecular Saha factors:
        for iMol in range(numMols):
            logSahaMol[iMol] = logMolSahaFac[iMol] - logNumB[iMol][id] - (
                boltzFacIAB[iMol] / temp[0][id]) + (
                    3.0 * temp[1][id] /
                    2.0) + thisLogUwB[iMol] + thisLogUwA - thisLogQwAB
            #//For denominator of ionization fraction, we need *inverse* molecular Saha factors (N_AB/NI):
            logSahaMol[iMol] = -1.0 * logSahaMol[iMol]
            invSahaMol[iMol] = math.exp(logSahaMol[iMol])
            #//TEST invSahaMol[iMol] = 1.0e-99; //test
            #// if (id == 36){
            #//     console.log("iMol " + iMol + " boltzFacIAB[iMol] " + boltzFacIAB[iMol] + " thisLogUwB[iMol] " + logE*thisLogUwB[iMol] + " logNumB[iMol][id] " + logE*logNumB[iMol][id] + " logMolSahaFac[iMol] " + logMolSahaFac[iMol]);
            #//     console.log("iMol " + iMol + " logSahaMol " + logE*logSahaMol[iMol] + " invSahaMol[iMol] " + invSahaMol[iMol]);
            #// }

        #//logSaha32 = logSahaFac - logNe - (boltzFacI2 / temp[0][id]) + (3.0 * temp[1][id] / 2.0) + thisLogUw3 - thisLogUw2; // log(RHS) of standard Saha equation
        #//saha32 = Math.exp(logSaha32);   //RHS of standard Saha equation

#//Compute log of denominator is ionization fraction, f_stage
        denominator = 1.0  #//default initialization - leading term is always unity
        #//ion stage contributions:
        for jStg in range(1, numStages + 1):
            addend = 1.0  #//default initialization for product series
            for iStg in range(jStg):
                #//console.log("jStg " + jStg + " saha[][] indices " + (iStg+1) + " " + iStg);
                addend = addend * saha[iStg + 1][iStg]

            denominator = denominator + addend

#//molecular contribution
        if (ifMols == True):
            for iMol in range(numMols):
                denominator = denominator + invSahaMol[iMol]

#//
        logDenominator = math.log(denominator)
        #//if (id == 36){
        #//     console.log("logDenominator " + logE*logDenominator);
        #// }
        #//var logDenominator = Math.log( 1.0 + saha21 + (saha32 * saha21) + (saha43 * saha32 * saha21) + (saha54 * saha43 * saha32 * saha21) );

        logIonFrac[
            0] = -1.0 * logDenominator  #// log ionization fraction in stage I
        #//if (id == 36){
        #     //console.log("jStg 0 " + " logIonFrac[jStg] " + logE*logIonFrac[0]);
        #//}
        for jStg in range(1, numStages):
            addend = 0.0  #//default initialization for product series
            for iStg in range(jStg):
                #//console.log("jStg " + jStg + " saha[][] indices " + (iStg+1) + " " + iStg);
                addend = addend + logSaha[iStg + 1][iStg]

            logIonFrac[jStg] = addend - logDenominator
        #//if (id == 36){
        #//    console.log("jStg " + jStg + " logIonFrac[jStg] " + logE*logIonFrac[jStg]);
        #//}

        #//logIonFracI = -1.0 * logDenominator;     // log ionization fraction in stage I
        #//logIonFracII = logSaha21 - logDenominator; // log ionization fraction in stage II
        #//logIonFracIII = logSaha32 + logSaha21 - logDenominator; //log ionization fraction in stage III
        #//logIonFracIV = logSaha43 + logSaha32 + logSaha21 - logDenominator; //log ionization fraction in stage III

        #//if (id == 36) {
        #//    System.out.println("logSaha21 " + logE*logSaha21 + " logSaha32 " + logE*logSaha32);
        #//    System.out.println("IonFracII " + Math.exp(logIonFracII) + " IonFracI " + Math.exp(logIonFracI) + " logNe " + logE*logNe);
        #//}
        #//System.out.println("LevelPops: id, ionFracI, ionFracII: " + id + " " + Math.exp(logIonFracI) + " " + Math.exp(logIonFracII) );
        #    //System.out.println("LevPops: ionized branch taken, ionized =  " + ionized);

        for iStg in range(numStages):
            logNums[iStg][id] = logNum[id] + logIonFrac[iStg]

    #//id loop

    return logNums
Пример #11
0
def levelPops(lam0In, logNStage, chiL, logUw, gwL, numDeps, temp):
    """ Returns depth distribution of occupation numbers in lower level of b-b transition,

// Input parameters:
// lam0 - line centre wavelength in nm
// logNStage - log_e density of absorbers in relevent ion stage (cm^-3)
// logFlu - log_10 oscillator strength (unitless)
// chiL - energy of lower atomic E-level of b-b transition in eV
// Also needs atsmopheric structure information:
// numDeps
// temp structure """

    c = Useful.c()
    logC = Useful.logC()
    k = Useful.k()
    logK = Useful.logK()
    logH = Useful.logH()
    logEe = Useful.logEe()
    logMe = Useful.logMe()

    ln10 = math.log(10.0)
    logE = math.log10(math.e)
    #// for debug output
    log2pi = math.log(2.0 * math.pi)
    log2 = math.log(2.0)

    #//double logNl = logNlIn * ln10;  // Convert to base e

    #// Parition functions passed in are 2-element vectore with remperature-dependent base 10 log Us
    #// Convert to natural logs:
    #double thisLogUw, Ttheta;
    thisLogUw = 0.0  # //default initialization
    #logUw = [ 0.0 for i in range(5) ]
    logE10 = math.log(10.0)
    #print("log10UwStage ", log10UwStage)
    #for kk in range(len(logUw)):
    #    logUw[kk] = logE10*log10UwStage[kk] #// lburns new loop

    logGwL = math.log(gwL)

    #//System.out.println("chiL before: " + chiL);
    #// If we need to subtract chiI from chiL, do so *before* converting to tiny numbers in ergs!
    #////For testing with Ca II lines using gS3 internal line list only:
    #//boolean ionized = true;
    #//if (ionized) {
    #//    //System.out.println("ionized, doing chiL - chiI: " + ionized);
    #//    //         chiL = chiL - chiI;
    #//             chiL = chiL - 6.113;
    #//          }
    #//   //

    #//Log of line-center wavelength in cm
    logLam0 = math.log(lam0In)  #// * 1.0e-7);

    #// energy of b-b transition
    logTransE = logH + logC - logLam0  #//ergs

    if (chiL <= 0.0):
        chiL = 1.0e-49
    logChiL = math.log(
        chiL) + Useful.logEv()  #// Convert lower E-level from eV to ergs

    logBoltzFacL = logChiL - Useful.logK(
    )  #// Pre-factor for exponent of excitation Boltzmann factor
    boltzFacL = math.exp(logBoltzFacL)

    boltzFacGround = 0.0 / k  #//I know - its zero, but let's do it this way anyway'

    #// return a 1D numDeps array of logarithmic number densities
    #// level population of lower level of bb transition (could be in either stage I or II!)

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

    #double num, logNum, expFac;

    for id in range(numDeps):

        #//Determine temperature dependenet partition functions Uw:

        #Ttheta = 5040.0 / temp[0][id]
        #//NEW Determine temperature dependent partition functions Uw: lburns
        thisTemp = temp[0][id]
        """
        if (Ttheta >= 1.0):
            thisLogUw = logUw[0]
        
        if (Ttheta <= 0.5):
            thisLogUw = logUw[1]
        
        if (Ttheta > 0.5 and Ttheta < 1.0):
            thisLogUw = ( logUw[1] * (Ttheta - 0.5)/(1.0 - 0.5) ) \
                      + ( logUw[0] * (1.0 - Ttheta)/(1.0 - 0.5) )
        """
        if (thisTemp >= 10000):
            thisLogUw = logUw[4]

        if (thisTemp <= 130):
            thisLogUw = logUw[0]

        if (thisTemp > 130 and thisTemp <= 500):
            thisLogUw = logUw[1] * (thisTemp - 130)/(500 - 130) \
                      + logUw[0] * (500 - thisTemp)/(500 - 130)

        if (thisTemp > 500 and thisTemp <= 3000):
            thisLogUw = logUw[2] * (thisTemp - 500)/(3000 - 500) \
                      + logUw[1] * (3000 - thisTemp)/(3000 - 500)

        if (thisTemp > 3000 and thisTemp <= 8000):
            thisLogUw = logUw[3] * (thisTemp - 3000)/(8000 - 3000) \
                      + logUw[2] * (8000 - thisTemp)/(8000 - 3000)

        if (thisTemp > 8000 and thisTemp < 10000):
            thisLogUw = logUw[4] * (thisTemp - 8000)/(10000 - 8000) \
                      + logUw[3] * (10000 - thisTemp)/(10000 - 8000)

        #print("logUw ", logUw, " thisLogUw ", thisLogUw)

        #//System.out.println("LevPops: ionized branch taken, ionized =  " + ionized);
        #// Take stat weight of ground state as partition function:
        logNums[id] = logNStage[id] - boltzFacL / temp[0][
            id] + logGwL - thisLogUw  #// lower level of b-b transition
        #print("LevelPopsServer.stagePops id ", id, " logNStage[id] ", logNStage[id], " boltzFacL ", boltzFacL, " temp[0][id] ", temp[0][id], " logGwL ", logGwL, " thisLogUw ", thisLogUw, " logNums[id] ", logNums[id]);

        #// System.out.println("LevelPops: id, logNums[0][id], logNums[1][id], logNums[2][id], logNums[3][id]: " + id + " "
        #//          + Math.exp(logNums[0][id]) + " "
        #//         + Math.exp(logNums[1][id]) + " "
        #//          + Math.exp(logNums[2][id]) + " "
        #//        + Math.exp(logNums[3][id]));
        #//System.out.println("LevelPops: id, logNums[0][id], logNums[1][id], logNums[2][id], logNums[3][id], logNums[4][id]: " + id + " "
        #//        + logE * (logNums[0][id]) + " "
        #//        + logE * (logNums[1][id]) + " "
        #//        + logE * (logNums[2][id]) + " "
        # //        + logE * (logNums[3][id]) + " "
        #//        + logE * (logNums[4][id]) );
        #//System.out.println("LevelPops: id, logIonFracI, logIonFracII: " + id + " " + logE*logIonFracI + " " + logE*logIonFracII
        #//        + "logNum, logNumI, logNums[0][id], logNums[1][id] "
        #//        + logE*logNum + " " + logE*logNumI + " " + logE*logNums[0][id] + " " + logE*logNums[1][id]);
        #//System.out.println("LevelPops: id, logIonFracI: " + id + " " + logE*logIonFracI
        #//        + "logNums[0][id], boltzFacL/temp[0][id], logNums[2][id]: "
        #//        + logNums[0][id] + " " + boltzFacL/temp[0][id] + " " + logNums[2][id]);
    #//id loop
    #stop
    return logNums
Пример #12
0
def lineKap(lam0In, logNums, logFluIn, linePoints, lineProf, numDeps, zScale,
            tauRos, temp, rho, logFudgeTune):

    logE10 = math.log(10.0)  #//natural log of 10

    c = Useful.c()
    logC = Useful.logC()
    k = Useful.k()
    logK = Useful.logK()
    logH = Useful.logH()
    logEe = Useful.logEe()
    logMe = Useful.logMe()

    ln10 = math.log(10.0)
    logE = math.log10(math.e)  #// for debug output
    log2pi = math.log(2.0 * math.pi)
    log2 = math.log(2.0)

    lam0 = lam0In  #// * 1.0E-7; //nm to cm
    logLam0 = math.log(lam0)
    #//double logNl = logNlIn * ln10;  // Convert to base e
    logFlu = logFluIn * ln10  #// Convert to base e
    logKScale = math.log10(zScale)

    #//chiI = chiI * Useful.eV;  // Convert lower E-level from eV to ergs
    #//double boltzFacI = chiI / k; // Pre-factor for exponent of excitation Boltzmann factor
    #//double logSahaFac = log2 + (3.0/2.0) * ( log2pi + logMe + logK - 2.0*logH);
    #//chiL = chiL * Useful.eV;  // Convert lower E-level from eV to ergs
    #//double boltzFac = chiL / k; // Pre-factor for exponent of excitation Boltzmann factor
    numPoints = len(linePoints[0])
    #//System.out.println("LineKappa: numPoints: " + numPoints);

    #double logPreFac;
    #//This converts f_lu to a volume extinction coefficient per particle - Rutten, p. 23
    logPreFac = logFlu + math.log(math.pi) + 2.0 * logEe - logMe - logC
    #//System.out.println("LINEKAPPA: logPreFac " + logPreFac);

    #//Assume wavelength, lambda, is constant throughout line profile for purpose
    #// of computing the stimulated emission correction
    #double logExpFac;
    logExpFac = logH + logC - logK - logLam0
    #//System.out.println("LINEKAPPA: logExpFac " + logExpFac);

    #// int refRhoIndx = TauPoint.tauPoint(numDeps, tauRos, 1.0);
    #// double refLogRho = rho[1][refRhoIndx];
    #//System.out.println("LINEKAPPA: refRhoIndx, refRho " + refRhoIndx + " " + logE*refRho);
    #// return a 2D numPoints x numDeps array of monochromatic *LINE* extinction line profiles

    logKappaL = [[0.0 for i in range(numDeps)] for j in range(numPoints)]
    #double num, logNum, logExpFac2, expFac, stimEm, logStimEm, logSaha, saha, logIonFrac;
    #double logNe;

    for id in range(numDeps):

        logExpFac2 = logExpFac - temp[1][id]
        expFac = -1.0 * math.exp(logExpFac2)

        stimEm = 1.0 - math.exp(expFac)
        logStimEm = math.log(stimEm)

        logNum = logNums[id]

        #//if (id == refRhoIndx) {
        #//    System.out.println("LINEKAPPA: logStimEm " + logE*logStimEm);
        #//}
        for il in range(numPoints):

            #// From Radiative Transfer in Stellar Atmospheres (Rutten), p.31
            #// This is a *volume* co-efficient ("alpha_lambda") in cm^-1:
            logKappaL[il][id] = logPreFac + logStimEm + logNum + math.log(
                lineProf[il][id])
            #//if (id == 36) {
            #//    System.out.println("il " + il + " logNum " + logE*logNum + " Math.log(lineProf[il][id]) " + logE*Math.log(lineProf[il][id]));
            #////    //System.out.println("logPreFac " + logPreFac + " logStimEm " + logStimEm);
            #//}
            #//System.out.println("LINEKAPPA: id, il " + id + " " + il + " logKappaL " + logE * logKappaL[il][id]);

            #//Convert to mass co-efficient in g/cm^2:
            #// This direct approach won't work - is not consistent with fake Kramer's law scaling of Kapp_Ros with g instead of rho
            logKappaL[il][id] = logKappaL[il][id] - rho[1][id]
            #//Try something:
            #//
            #// **********************
            #//  Opacity problem #2
            #//
            #//Line opacity needs to be enhanced by same factor as the conitnuum opacity
            #//  - related to Opacity problem #1 (logFudgeTune in GrayStarServer3.java) - ??
            #//
            logKappaL[il][id] = logKappaL[il][id] + logE10 * logFudgeTune

            #//if (id == 12) {
            #//  System.out.println("LINEKAPPA: id, il " + id + " " + il + " logKappaL " + logE * logKappaL[il][id]
            #//   + " logPreFac " + logE*logPreFac + " logStimEm " + logE*logStimEm + " logNum " + logE*logNum
            #//  + " log(lineProf[il]) " + logE*Math.log(lineProf[il][id]) + " rho[1][id] " + logE * rho[1][id]);
            #// }
            #//if (id == refRhoIndx-45) {
            #//    System.out.println("LINEKAPPA: id, il " + id + " " + il + " logKappaL " + logE*logKappaL[il][id]
            #//    + " logPreFac " + logE*logPreFac + " logStimEm " + logE*logStimEm + " logNum " + logE*logNum + " logRho " + logE*rho[1][id]
            #//    + " log(lineProf[1]) " + logE*Math.log(lineProf[1][il]) );
            #//}
        #} // il - lambda loop

    #} // id - depth loop

    return logKappaL