Ejemplo n.º 1
0
    elapsed = end - start
    print("iterate.py imports: " + str(elapsed))

# Read run-time arguments
header = argv[1:][0]              # Name of header file
desc   = argv[1:][1]              # Directory name

# Create and name outputs and results directories if they do not exist
datadir   = location_out + desc + '/outputs/' + 'transient/'
datadirr  = location_out + desc + '/results'                

if not os.path.exists(datadir): os.makedirs(datadir)
if not os.path.exists(datadirr): os.makedirs(datadirr)

# Retrieve header info
inhead    = form.readheader(header)
pressure  = inhead[0]
temp      = inhead[1]

# Locate and read initial iteration output from balance.py
infile    = datadir + '/lagrange-iteration-0-machine-read.txt'
input     = form.readoutput(infile)

# Retrieve and set initial values
speclist  = input[2]
x         = input[3]
x_bar     = input[6]

# Set up first iteration 
it_num  = 1
repeat  = True
Ejemplo n.º 2
0
    elapsed = end - start
    print("iterate.py imports: " + str(elapsed))

# Read run-time arguments
header = argv[1:][0]  # Name of header file
desc = argv[1:][1]  # Directory name

# Create and name outputs and results directories if they do not exist
datadir = location_out + desc + '/outputs/' + 'transient/'
datadirr = location_out + desc + '/results'

if not os.path.exists(datadir): os.makedirs(datadir)
if not os.path.exists(datadirr): os.makedirs(datadirr)

# Retrieve header info
inhead = form.readheader(header)
pressure = inhead[0]
temp = inhead[1]

# Locate and read initial iteration output from balance.py
infile = datadir + '/lagrange-iteration-0-machine-read.txt'
input = form.readoutput(infile)

# Retrieve and set initial values
speclist = input[2]
x = input[3]
x_bar = input[6]

# Set up first iteration
it_num = 1
repeat = True
Ejemplo n.º 3
0
def lambdacorr(it_num, datadir, doprint, direct):
    '''
    This module applies lambda correction method (see Section 1.3 in TEA 
    Document). When input mole numbers are negative, the code corrects them to
    positive values and pass them to the next iteration cycle. The code reads
    the values from the last lagrange output, the information from the header
    file, performs checks, and starts setting basic equations. It sets a smart
    range so it can efficiently explore the lambda values from [0,1]. Half of 
    the range is sampled exponentially, and the other half linearly, totalling
    150 points. The code retrieves the last lambda value before first 
    derivative becomes positive (equation (33) in TEA Document), and corrects
    negative mole numbers to positive.

    Parameters
    ----------
    it_num:  integer 
             Iteration number.
    datadir: string
             Current directory where TEA is run.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.
    direct:  object
             Object containing all of the results/data from the previous
             calculation in lagrange.py or lambdacorr.py. It is a list
             containing current header directory, current iteration 
             number, array of species names, array of initial guess, 
             array of non-corrected Lagrange values, and array of 
             lambdacorr corrected values.

    Returns
    -------
    header:  string
             Name of the header file used.
    it_num:  integer 
             Iteration number.
    speclist: array of strings
             Array containing names of molecular species. 
    y: array of floats
             Array containing initial guess of molecular species for
             current iteration.
    x_corr:  array of floats
             Array containing final mole numbers of molecular species for
             current iteration.
    delta_corr: array of floats
             Array containing change of initial and final mole numbers of 
             molecular species for current iteration.
    y_bar: float
             Array containing total initial guess of all molecular species for
             current iteration.
    x_corr_bar: float
             Total sum of the final mole numbers of all molecular species.
    detla_corr_bar: float 
             Change in total number of all species.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.

    Notes
    -----
    The code works without adjustments and with high precision for the
    the fractional abundances (mixing fractions) up to 10e-14 and the
    temperature range of 1000 - 4000 K. For temperatures below 1000 K and 
    mixing fractions below 10e-14, the code produces results with low 
    precision. To improve the precision, adjust the lambda exploration
    variables 'lower' and 'steps' to larger magnitudes (i.e., lower = -100,
    steps = 1000). This will lengthen the time of execution.
    '''

    # Suppress nan warnings, as they are used for finding valid minima
    np.seterr(invalid='ignore')
    np.seterr(divide='ignore')
    
     # Read values from last lagrange output
    input  = direct

    # Take the current header file
    header = input[0]

    # Read values from the header file
    pressure, temp, i, j, speclist, a, b, g_RT = form.readheader(header)
   
    # Take final values from last iteration, lagrange.py
    y         = input[3]
    x         = input[4]
    delta     = input[5]
    y_bar     = input[6]
    x_bar     = input[7]
    delta_bar = input[8]

    # Perform checks to be safe
    it_num_check   = input[1]
    speclist_check = input[2]
    
    # Make array of checks
    check = np.array([it_num_check != it_num,
                      False in (speclist_check == speclist) ])

    # If iteration number given by iterate.py is not one larger as in 'direct',
    #      give error
    if check[0]:
        print("\n\nMAJOR ERROR! Read in file's it_num is not the    \
                current iteration!\n\n")
    # If species names in the header are not the same as in 'direct', 
    #      give error 
    if check[1]:
        print("\n\nMAJOR ERROR! Read in file uses different species \
                order/list!\n\n")
    
    # Create 'c' value, equation (16) TEA Document
    # c_i = (g/RT)i + ln(P)    
    c = g_RT + np.log(pressure)
    
    # Set equation (33) TEA Document
    # dF(lam)/dlam = sum_i delta_i[(g(T)/RT)_i + lnP + 
    #                ln (yi+lam*delta_i)/(y_bar+lam*delta_bar)]
    def dF_dlam(s, i, x, y, delta, c, x_bar, y_bar, delta_bar):
        dF_dlam = 0
        for n in np.arange(i):
            dF_dlam += delta[n] * (c[n] + np.log(y[n] + s*delta[n]) - \
                       np.log(y_bar + s*delta_bar))
        return dF_dlam
    
    # Create the range of lambda values to explore. To speed up finding
    #        the correct lambda value to use, the range is split into two
    #        parts at range_split: the lower exponential range and the 
    #        higher linear range. This helps the system to converge faster.
    range_split = 0.5

    # Create exponential range, low_range
    # Exponent parameter that gives a value close to zero for the start of
    #          lambda exploration
    lower       = -50

    # Define number of steps to explore exponential range
    steps       = 100

    # Create lower exponential range
    low_range = np.exp(np.linspace(lower, 0, steps+1))

    # Create linear, evenly spaced range, high_range
    high_step = 0.01
    high_range = np.arange(0.5, 1 + high_step, high_step)

    # Combine the two ranges to create one overall range for lambda exploration
    smart_range = np.append(low_range[low_range <= range_split], high_range)

    # Set that lambda is not found
    lam_not_found = True

    # Retrieve last lambda value explored before the minimum energy is passed
    for h in smart_range:
        val = dF_dlam(h, i, x, y, delta, c, x_bar, y_bar, delta_bar)
        if val > 0 or np.isnan(val) == True:
            break

        # If lambda found, take lambda and set lambda not found to false
        lam = h
        lam_not_found = False

    # If lambda is not found (break), function F (equation (35) in TEA
    #    Document) set the final x mole numbers to the values calculated
    #    in the last iteration output 
    if lam_not_found:
        x_corr = y
    else:
        x_corr = y + lam * delta

    # Correct x values given this value of lambda
    x_corr_bar = np.sum(x_corr)
    delta_corr = y - x_corr
    delta_corr_bar = x_corr_bar - y_bar
    
    # Name output files with corresponding iteration number name
    file       = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                           '-machine-read.txt'
    file_fancy = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                                 '-visual.txt'

    # Export all values into machine and human readable output files
    form.output(datadir, header, it_num, speclist, y, x_corr, delta_corr,  \
                    y_bar, x_corr_bar, delta_corr_bar, file, doprint)
    form.fancyout(datadir, it_num, speclist, y, x_corr, delta_corr, y_bar, \
                     x_corr_bar, delta_corr_bar, file_fancy, doprint)
        
    return [header, it_num, speclist, y, x_corr, delta_corr, y_bar,       \
                                x_corr_bar, delta_corr_bar, doprint]
Ejemplo n.º 4
0
# Correct location_TEA name
if location_out[-1] != '/':
    location_out += '/'

# Read run-time arguments
header = argv[1:][0]  # Name of header file
desc = argv[1:][1]  # Directory name

# Create and name outputs and results directories if they do not exist
datadir = location_out + desc + '/outputs/' + 'transient/'

# If output directory does not exist already, make it
if not os.path.exists(datadir): os.makedirs(datadir)

# Read in values from header file
pressure, temp, i, j, speclist, a, b, c = form.readheader(header)

# Print b values for debugging purposes
if doprint:
    print("b values: " + str(b))

# Find chunk of ai_j array that will allow the corresponding yi values
#      to be free variables such that all elements are considered
for n in np.arange(i - j + 1):
    # Get lower and upper indices for chunk of ai_j array to check
    lower = n
    upper = n + j

    # Retrieve chunk of ai_j that would contain free variables
    a_chunk = a[lower:upper]
def lagrange(it_num, datadir, doprint, direct):
    '''
    This code applies Lagrange's method and calculates minimum based on the 
    methodology elaborated in the TEA theory document in Section (3). Equations in
    this code contain both references and an explicitly written definitions.
    The program reads the last iteration's output and data from the last header
    file, creates variables for the Lagrange equations, sets up the Lagrange
    equations, and calculates final x_i mole numbers for the current iteration 
    cycle. Note that the mole numbers that result from this function are 
    allowed to be negative. If negatives are returned, lambda correction 
    (lambdacorr.py) is necessary. The final x_i values, as well as x_bar, 
    y_bar, delta, and delta_bar are written into machine- and human-readable
    output files. This function is executed by iterate.py.

    Parameters
    ----------
    it_num:  integer 
             Iteration number.
    datadir: string
             Current directory where TEA is run.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.
    direct:  object
             Object containing all of the results/data from the previous
             calculation in lagrange.py or lambdacorr.py. It is a list
             containing current header directory, current iteration 
             number, array of species names, array of initial guess, 
             array of non-corrected Lagrange values, and array of 
             lambdacorr corrected values.

    Returns
    -------
    header: string
            Name of the header file used.
    it_num: integer 
            Iteration number.
    speclist: string array
            Array containing names of molecular species. 
    y: float array
            Array containing initial guess of molecular species for
            current iteration.
    x: float array
            Array containing final mole numbers of molecular species for
            current iteration.
    delta: float array
            Array containing change in initial and final mole numbers of
            molecular species for current iteration.
    y_bar: float
            Array containing total sum of initial guesses of all molecular 
            species for current iteration.
    x_bar: float
            Total sum of the final mole numbers of all molecular species.
    delta_bar: float 
            Change in total of initial and final mole numbers of molecular
            species.
    '''

    # Read values from last iteration   
    input  = direct 

    # Take the current header file  
    header = input[0]

    # Read values from the header file
    pressure, temp, i, j, speclist, a, b, g_RT = form.readheader(header)
    
    # Use final values from last iteration (x values) as new initial
    y     = input[4] 
    y_bar = input[7] 

    # Perform checks to be safe
    it_num_check   = input[1]
    speclist_check = input[2]
    
    # Make array of checks
    check = np.array([it_num_check != it_num - 1,
            False in (speclist_check == speclist) ])
    # If iteration number given by iterate.py is not one larger as in 'direct',
    #      give error
    if check[0]:
        print("\n\nMAJOR ERROR! Read in file's it_num is not the most \
                recent iteration!\n\n")
    # If species names in the header are not the same as in 'direct', 
    #      give error 
    if check[1]:
        print("\n\nMAJOR ERROR! Read in file uses different species   \
                order/list!\n\n")      
    
        
    # ============== CREATE VARIABLES FOR LAGRANGE EQUATION ============== #

    # Create 'c' value, equation (18) TEA theory document
    # ci = (g/RT)_i + ln(P)    
    c = g_RT + np.log(pressure)
    
    # Allocates array of fi(Y) over different values of i (species)
    fi_y = np.zeros(i)
    
    # Fill in fi(Y) values equation (19) TEA theory document
    # fi = x_i * [ci + ln(x_i/x_bar)]
    for n in np.arange(i):
        y_frac  = np.float(y[n] / y_bar)
        fi_y[n] = y[n] * ( c[n] + np.log(y_frac) )
    
    # Allocate values of rjk. Both j and k goes from 1 to m.
    k = j 
    rjk = np.zeros((j,k))

    # Fill out values of rjk, equation (26) TEA theory document 
    # rjk = rkj = sum_i(a_ij * a_ik) * y_i
    for l in np.arange(k):
        for m in np.arange(j):
            r_sum = 0.0
            for n in np.arange(i): 
                r_sum += a[n, m] * a[n, l] * y[n]      
            rjk[m, l] = r_sum
    
    # Allocate value of u, equation (28) TEA theory document
    u = Symbol('u')
    
    # Allocate pi_j variables, where j is element index
    # Example: pi_2 is Lagrange multiplier of N (j = 2)
    pi = []
    for m in np.arange(j):
        name = 'pi_' + np.str(m+1)
        pi = np.append(pi, Symbol(name))
    
    # Allocate rjk * pi_j summations, equation (27) TEA theory document
    # There will be j * k terms of rjk * pi_j
    sq_pi = [pi]
    for m in np.arange(j-1):
        # Make square array of pi values with shape j * k
        sq_pi = np.append(sq_pi, [pi], axis = 0) 

    # Multiply rjk * sq_pi to get array of rjk * pi_j 
    # equation (27) TEA theory document
    rpi = rjk * sq_pi 
    

    # ======================= SET FINAL EQUATIONS ======================= #
    # Total number of equations is j + 1
    
    # Set up a_ij * fi(Y) summations equation (27) TEA theory document
    # sum_i[a_ij * fi(Y)]
    aij_fiy = np.zeros((j))
    for m in np.arange(j):
        rhs = 0.0
        for n in np.arange(i):
            rhs += a[n,m] * fi_y[n]
        aij_fiy[m] = rhs
    
    # Create first j'th equations equation (27) TEA theory document
    # r_1m*pi_1 + r_2m*pi_2 + ... + r_mm*pi_m + b_m*u = sum_i[a_im * fi(Y)]
    for m in np.arange(j):
        if m == 0:
            equations   = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
        else:
            lagrange_eq = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
            equations   = np.append(equations, lagrange_eq)

    # Last (j+1)th equation (27) TEA theory document
    # b_1*pi_1 + b_2*pi_2 + ... + b_m*pi_m + 0*u = sum_i[fi(Y)]
    bpi = b * pi
    lagrange_eq_last = np.array([np.sum(bpi) - np.sum(fi_y)])
    equations = np.append(equations, lagrange_eq_last)
            
    # List all unknowns in the above set of equations
    unknowns = list(pi)
    unknowns.append(u)

    # Solve final system of j+1 equations
    fsol = solve(list(equations), unknowns, rational=False)
    
    
    # ============ CALCULATE xi VALUES FOR CURRENT ITERATION ============ #
    
    # Make array of pi values
    pi_f = []
    for m in np.arange(j):
        pi_f = np.append(pi_f, [fsol[pi[m]]])

    # Calculate x_bar from solution to get 'u', equation (28) TEA theory document
    # u = -1. + (x_bar/y_bar)
    u_f = fsol[u]
    x_bar = (u_f + 1.) * y_bar
    
    # Initiate array for x values of size i
    x = np.zeros(i)
    
    # Apply Lagrange solution for final set of x_i values for this iteration
    # equation (23) TEA theory document
    # x_i = -fi(Y) + (y_i/y_bar) * x_bar + [sum_j(pi_j * a_ij)] * y_i
    for n in np.arange(i):
        sum_pi_aij = 0.0
        for m in np.arange(j):
            sum_pi_aij += pi_f[m] * a[n, m]
        x[n] = - fi_y[n] + (y[n]/y_bar) * x_bar + sum_pi_aij * y[n]
    
    # Calculate other variables of interest
    x_bar = np.sum(x)             # sum of all x_i
    delta = x - y                 # difference between initial and final values
    delta_bar = x_bar - y_bar     # difference between sum of initial and
                                  # final values
    
    # Name output files with corresponding iteration number name
    file       = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                         'machine-read-nocorr.txt'
    file_fancy = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                              '-visual-nocorr.txt'

    # Export all values into machine and human readable output files
    form.output(datadir, header, it_num, speclist, y, x, \
                       delta, y_bar, x_bar, delta_bar, file, doprint)
    form.fancyout(datadir, it_num, speclist, y, x, delta,\
                         y_bar, x_bar, delta_bar, file_fancy, doprint)
       
    return [header, it_num, speclist, y, x, delta, y_bar, x_bar, delta_bar]
        
def lambdacorr(it_num, datadir, doprint, direct):
    '''
    This module applies lambda correction method (see Section 4 in the TEA theory 
    document). When input mole numbers are negative, the code corrects them to
    positive values and pass them to the next iteration cycle. The code reads
    the values from the last lagrange output, the information from the header
    file, performs checks, and starts setting basic equations. It defines a 
    'smart' range so it can efficiently explore the lambda values from [0,1]. 
    Half of the range is sampled exponentially, and the other half linearly, 
    totalling 150 points. The code retrieves the last lambda value before first 
    derivative becomes positive (equation (34) in TEA theory document), and
    corrects negative mole numbers to positive.

    Parameters
    ----------
    it_num:  integer 
             Iteration number.
    datadir: string
             Current directory where TEA is run.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.
    direct:  object
             Object containing all of the results/data from the previous
             calculation in lagrange.py or lambdacorr.py. It is a list
             containing current header directory, current iteration 
             number, array of species names, array of initial guess, 
             array of non-corrected Lagrange values, and array of 
             lambdacorr corrected values.

    Returns
    -------
    header:  string
             Name of the header file used.
    it_num:  integer 
             Iteration number.
    speclist: array of strings
             Array containing names of molecular species. 
    y: array of floats
             Array containing initial guess of molecular species for
             current iteration.
    x_corr:  array of floats
             Array containing final mole numbers of molecular species for
             current iteration.
    delta_corr: array of floats
             Array containing change of initial and final mole numbers of 
             molecular species for current iteration.
    y_bar: float
             Array containing total initial guess of all molecular species for
             current iteration.
    x_corr_bar: float
             Total sum of the final mole numbers of all molecular species.
    detla_corr_bar: float 
             Change in total number of all species.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.

    Notes
    -----
    The code works without adjustments and with high precision for the
    temperatures above ~600 K. For temperatures below 600 K and 
    mixing fractions below 10e-14, the code produces results with low 
    precision. To improve the precision, adjust the lambda exploration
    variables 'lower' and 'steps' to larger magnitudes (i.e., lower = -100,
    steps = 1000). This will lengthen the time of execution.
    '''

    # Suppress nan warnings, as they are used for finding valid minima
    np.seterr(invalid='ignore')
    np.seterr(divide='ignore')

    # Read values from last lagrange output
    input = direct

    # Take the current header file
    header = input[0]

    # Read values from the header file
    pressure, temp, i, j, speclist, a, b, g_RT = form.readheader(header)

    # Take final values from last iteration, lagrange.py
    y = input[3]
    x = input[4]
    delta = input[5]
    y_bar = input[6]
    x_bar = input[7]
    delta_bar = input[8]

    # Perform checks to be safe
    it_num_check = input[1]
    speclist_check = input[2]

    # Make array of checks
    check = np.array(
        [it_num_check != it_num, False in (speclist_check == speclist)])

    # If iteration number given by iterate.py is not one larger as in 'direct',
    #      give error
    if check[0]:
        print("\n\nMAJOR ERROR! Read in file's it_num is not the    \
                current iteration!\n\n")
    # If species names in the header are not the same as in 'direct',
    #      give error
    if check[1]:
        print("\n\nMAJOR ERROR! Read in file uses different species \
                order/list!\n\n")

    # Create 'c' value, equation (17) TEA theory document
    # c_i = (g/RT)i + ln(P)
    c = g_RT + np.log(pressure)

    # Set equation (34) TEA theory document
    # dF(lam)/dlam = sum_i delta_i[(g(T)/RT)_i + lnP +
    #                ln (yi+lam*delta_i)/(y_bar+lam*delta_bar)]
    def dF_dlam(s, i, x, y, delta, c, x_bar, y_bar, delta_bar):
        dF_dlam = 0
        for n in np.arange(i):
            dF_dlam += delta[n] * (c[n] + np.log(y[n] + s*delta[n]) - \
                       np.log(y_bar + s*delta_bar))
        return dF_dlam

    # Create the range of lambda values to explore. To speed up finding
    #        the correct lambda value to use, the range is split into two
    #        parts at range_split: the lower exponential range and the
    #        higher linear range. This helps the system to converge faster.
    range_split = 0.5

    # Create exponential range, low_range
    # Exponent parameter that gives a value close to zero for the start of
    #          lambda exploration
    lower = -50

    # Define number of steps to explore exponential range
    steps = 100

    # Create lower exponential range
    low_range = np.exp(np.linspace(lower, 0, steps + 1))

    # Create linear, evenly spaced range, high_range
    high_step = 0.01
    high_range = np.arange(0.5, 1 + high_step, high_step)

    # Combine the two ranges to create one overall range for lambda exploration
    smart_range = np.append(low_range[low_range <= range_split], high_range)

    # Set that lambda is not found
    lam_not_found = True

    # Retrieve last lambda value explored before the minimum energy is passed
    for h in smart_range:
        val = dF_dlam(h, i, x, y, delta, c, x_bar, y_bar, delta_bar)
        if val > 0 or np.isnan(val) == True:
            break

        # If lambda found, take lambda and set lambda not found to false
        lam = h
        lam_not_found = False

    # If lambda is not found (break), function F (equation (33) in the TEA
    #    theory document) set the final x mole numbers to the values calculated
    #    in the last iteration output
    if lam_not_found:
        x_corr = y
    else:
        x_corr = y + lam * delta

    # Correct x values given this value of lambda
    x_corr_bar = np.sum(x_corr)
    delta_corr = y - x_corr
    delta_corr_bar = x_corr_bar - y_bar

    # Name output files with corresponding iteration number name
    file       = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                           '-machine-read.txt'
    file_fancy = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                                 '-visual.txt'

    # Export all values into machine and human readable output files
    form.output(datadir, header, it_num, speclist, y, x_corr, delta_corr,  \
                    y_bar, x_corr_bar, delta_corr_bar, file, doprint)
    form.fancyout(datadir, it_num, speclist, y, x_corr, delta_corr, y_bar, \
                     x_corr_bar, delta_corr_bar, file_fancy, doprint)

    return [header, it_num, speclist, y, x_corr, delta_corr, y_bar,       \
                                x_corr_bar, delta_corr_bar, doprint]
Ejemplo n.º 7
0
def lagrange(it_num, datadir, doprint, direct):
    '''
    This code applies Lagrange's method and calculates minimum based on the 
    methodology elaborated in the TEA theory document in Section (3). Equations in
    this code contain both references and an explicitly written definitions.
    The program reads the last iteration's output and data from the last header
    file, creates variables for the Lagrange equations, sets up the Lagrange
    equations, and calculates final x_i mole numbers for the current iteration 
    cycle. Note that the mole numbers that result from this function are 
    allowed to be negative. If negatives are returned, lambda correction 
    (lambdacorr.py) is necessary. The final x_i values, as well as x_bar, 
    y_bar, delta, and delta_bar are written into machine- and human-readable
    output files. This function is executed by iterate.py.

    Parameters
    ----------
    it_num:  integer 
             Iteration number.
    datadir: string
             Current directory where TEA is run.
    doprint: string
             Parameter in configuration file that allows printing for 
             debugging purposes.
    direct:  object
             Object containing all of the results/data from the previous
             calculation in lagrange.py or lambdacorr.py. It is a list
             containing current header directory, current iteration 
             number, array of species names, array of initial guess, 
             array of non-corrected Lagrange values, and array of 
             lambdacorr corrected values.

    Returns
    -------
    header: string
            Name of the header file used.
    it_num: integer 
            Iteration number.
    speclist: string array
            Array containing names of molecular species. 
    y: float array
            Array containing initial guess of molecular species for
            current iteration.
    x: float array
            Array containing final mole numbers of molecular species for
            current iteration.
    delta: float array
            Array containing change in initial and final mole numbers of
            molecular species for current iteration.
    y_bar: float
            Array containing total sum of initial guesses of all molecular 
            species for current iteration.
    x_bar: float
            Total sum of the final mole numbers of all molecular species.
    delta_bar: float 
            Change in total of initial and final mole numbers of molecular
            species.
    '''

    # Read values from last iteration   
    input  = direct 

    # Take the current header file  
    header = input[0]

    # Read values from the header file
    pressure, temp, i, j, speclist, a, b, g_RT = form.readheader(header)
    
    # Use final values from last iteration (x values) as new initial
    y     = input[4] 
    y_bar = input[7] 

    # Perform checks to be safe
    it_num_check   = input[1]
    speclist_check = input[2]
    
    # Make array of checks
    check = np.array([it_num_check != it_num - 1,
            False in (speclist_check == speclist) ])
    # If iteration number given by iterate.py is not one larger as in 'direct',
    #      give error
    if check[0]:
        print("\n\nMAJOR ERROR! Read in file's it_num is not the most \
                recent iteration!\n\n")
    # If species names in the header are not the same as in 'direct', 
    #      give error 
    if check[1]:
        print("\n\nMAJOR ERROR! Read in file uses different species   \
                order/list!\n\n")      
    
        
    # ============== CREATE VARIABLES FOR LAGRANGE EQUATION ============== #

    # Create 'c' value, equation (18) TEA theory document
    # ci = (g/RT)_i + ln(P)    
    c = g_RT + np.log(pressure)
    
    # Allocates array of fi(Y) over different values of i (species)
    fi_y = np.zeros(i)
    
    # Fill in fi(Y) values equation (19) TEA theory document
    # fi = x_i * [ci + ln(x_i/x_bar)]
    for n in np.arange(i):
        y_frac  = np.float(y[n] / y_bar)
        fi_y[n] = y[n] * ( c[n] + np.log(y_frac) )
    
    # Allocate values of rjk. Both j and k goes from 1 to m.
    k = j 
    rjk = np.zeros((j,k))

    # Fill out values of rjk, equation (26) TEA theory document 
    # rjk = rkj = sum_i(a_ij * a_ik) * y_i
    for l in np.arange(k):
        for m in np.arange(j):
            r_sum = 0.0
            for n in np.arange(i): 
                r_sum += a[n, m] * a[n, l] * y[n]      
            rjk[m, l] = r_sum
    
    # Allocate value of u, equation (28) TEA theory document
    u = Symbol('u')
    
    # Allocate pi_j variables, where j is element index
    # Example: pi_2 is Lagrange multiplier of N (j = 2)
    pi = []
    for m in np.arange(j):
        name = 'pi_' + np.str(m+1)
        pi = np.append(pi, Symbol(name))
    
    # Allocate rjk * pi_j summations, equation (27) TEA theory document
    # There will be j * k terms of rjk * pi_j
    sq_pi = [pi]
    for m in np.arange(j-1):
        # Make square array of pi values with shape j * k
        sq_pi = np.append(sq_pi, [pi], axis = 0) 

    # Multiply rjk * sq_pi to get array of rjk * pi_j 
    # equation (27) TEA theory document
    rpi = rjk * sq_pi 
    

    # ======================= SET FINAL EQUATIONS ======================= #
    # Total number of equations is j + 1
    
    # Set up a_ij * fi(Y) summations equation (27) TEA theory document
    # sum_i[a_ij * fi(Y)]
    aij_fiy = np.zeros((j))
    for m in np.arange(j):
        rhs = 0.0
        for n in np.arange(i):
            rhs += a[n,m] * fi_y[n]
        aij_fiy[m] = rhs
    
    # Create first j'th equations equation (27) TEA theory document
    # r_1m*pi_1 + r_2m*pi_2 + ... + r_mm*pi_m + b_m*u = sum_i[a_im * fi(Y)]
    for m in np.arange(j):
        if m == 0:
            equations   = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
        else:
            lagrange_eq = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
            equations   = np.append(equations, lagrange_eq)

    # Last (j+1)th equation (27) TEA theory document
    # b_1*pi_1 + b_2*pi_2 + ... + b_m*pi_m + 0*u = sum_i[fi(Y)]
    bpi = b * pi
    lagrange_eq_last = np.array([np.sum(bpi) - np.sum(fi_y)])
    equations = np.append(equations, lagrange_eq_last)
            
    # List all unknowns in the above set of equations
    unknowns = list(pi)
    unknowns.append(u)

    # Solve final system of j+1 equations
    fsol = solve(list(equations), unknowns, rational=False)
    
    
    # ============ CALCULATE xi VALUES FOR CURRENT ITERATION ============ #
    
    # Make array of pi values
    pi_f = []
    for m in np.arange(j):
        pi_f = np.append(pi_f, [fsol[pi[m]]])

    # Calculate x_bar from solution to get 'u', equation (28) TEA theory document
    # u = -1. + (x_bar/y_bar)
    u_f = fsol[u]
    x_bar = (u_f + 1.) * y_bar
    
    # Initiate array for x values of size i
    x = np.zeros(i)
    
    # Apply Lagrange solution for final set of x_i values for this iteration
    # equation (23) TEA theory document
    # x_i = -fi(Y) + (y_i/y_bar) * x_bar + [sum_j(pi_j * a_ij)] * y_i
    for n in np.arange(i):
        sum_pi_aij = 0.0
        for m in np.arange(j):
            sum_pi_aij += pi_f[m] * a[n, m]
        x[n] = - fi_y[n] + (y[n]/y_bar) * x_bar + sum_pi_aij * y[n]
    
    # Calculate other variables of interest
    x_bar = np.sum(x)             # sum of all x_i
    delta = x - y                 # difference between initial and final values
    delta_bar = x_bar - y_bar     # difference between sum of initial and
                                  # final values
    
    # Name output files with corresponding iteration number name
    file       = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                         'machine-read-nocorr.txt'
    file_fancy = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                              '-visual-nocorr.txt'

    # Export all values into machine and human readable output files
    form.output(datadir, header, it_num, speclist, y, x, \
                       delta, y_bar, x_bar, delta_bar, file, doprint)
    form.fancyout(datadir, it_num, speclist, y, x, delta,\
                         y_bar, x_bar, delta_bar, file_fancy, doprint)
       
    return [header, it_num, speclist, y, x, delta, y_bar, x_bar, delta_bar]
Ejemplo n.º 8
0
def iterator(head, destination, location_out):
    # Correct location_TEA name
    if location_out[-1] != '/':
        location_out += '/'

    # Time / speed testing
    if times:
        end = time.time()
        elapsed = end - start
        print("iterate.py imports: " + str(elapsed))

    # Read run-time arguments
    header = head              # Name of header file
    desc   = destination              # Directory name

    # Create and name outputs and results directories if they do not exist
    datadir   = location_out + desc + '/outputs/' + 'transient/'
    datadirr  = location_out + desc + '/results'                

    if not os.path.exists(datadir): os.makedirs(datadir)
    if not os.path.exists(datadirr): os.makedirs(datadirr)

    # Retrieve header info
    inhead    = form.readheader(header)
    pressure  = inhead[0]
    temp      = inhead[1]

    # Locate and read initial iteration output from balance.py
    infile    = datadir + '/lagrange-iteration-0-machine-read.txt'
    input     = form.readoutput(infile)

    # Retrieve and set initial values
    speclist  = input[2]
    x         = input[3]
    x_bar     = input[6]

    # Set up first iteration 
    it_num  = 1
    repeat  = True

    # Prepare data object for iterative process 
    #         (see description of the 'direct' object in lagrange.py)
    lambdacorr_data = [header, 0, speclist, x, x, 0, x_bar, x_bar, 0]

    # Time / speed testing
    if times:
        new = time.time()
        elapsed = new - end
        print("pre-loop setup:     " + str(elapsed))

    # ====================== PERFORM MAIN TEA LOOP ====================== #

    while repeat:
        # Output iteration number
        if ((not doprint) & (not times)):
            stdout.write(' ' + str(it_num) + '\r')
            stdout.flush()

        # Time / speed testing for lagrange.py
        if times:
            ini = time.time()
        
        # Execute Lagrange minimization
        lagrange_data = lg.lagrange(it_num, datadir, doprint, lambdacorr_data)
        
        # Time / speed testing for lagrange.py
        if times:
            fin = time.time()
            elapsed = fin - ini
            print("lagrange" + str(it_num).rjust(4) + " :      " + str(elapsed))    
          
        # Print for debugging purposes
        if doprint:
            printout('Iteration %d Lagrange complete. Starting lambda correction...', it_num)
        
        # Take final x_i mole numbers from last Lagrange calculation 
        lagrange_x = lagrange_data[4]
        
        # Check if x_i have negative mole numbers, and if yes perform lambda correction
        if where((lagrange_x < 0) == True)[0].size != 0:
            # Print for debugging purposes 
            if doprint:
                printout('Correction required. Initializing...')
                
            # Time / speed testing for lambdacorr.py
            if times:
                ini = time.time()
            
            # Execute lambda correction
            lambdacorr_data = lc.lambdacorr(it_num, datadir, doprint, \
                                                       lagrange_data)
            
            # Print for debugging purposes
            if times:
                fin = time.time()
                elapsed = fin - ini
                print("lambcorr" + str(it_num).rjust(4) + " :      " + \
                                                          str(elapsed))
            
            # Print for debugging purposes
            if doprint:
                printout('Iteration %d lambda correction complete. Checking precision...', it_num)

        # Lambda correction is not needed
        else:
            # Pass previous Lagrange results as inputs to next iteration
            lambdacorr_data = lagrange_data

            # Print for debugging purposes
            if doprint:
                printout('Iteration %d did not need lambda correction.', it_num)
        
        # Retrieve most recent iteration values
        input_new = lambdacorr_data

        # Take most recent x_i and x_bar values    
        x_new     = input_new[4]
        x_bar_new = input_new[7]
        
        # If max iteration not met, continue with next iteration cycle
        if it_num < maxiter: 
            # Add 1 to iteration number
            it_num += 1

            # Print for debugging purposes
            if doprint:
                printout('Max interation not met. Starting next iteration...\n')
        
        # ============== Stop the loop, max iteration reached ============== #

        # Stop if max iteration is reached 
        else:
            # Print to screen
            printout('Maximum iteration reached, ending minimization.\n')

            # Set repeat to False to stop the loop
            repeat = False

            # Calculate delta values
            delta = x_new - x

            # Calculate delta_bar values
            delta_bar = x_bar_new - x_bar
            
            # Name output files with corresponding iteration number name
            file_results       = datadirr + '/results-machine-read.txt'
            file_fancyResults  = datadirr + '/results-visual.txt'

            # Export all values into machine and human readable output files  
            form.output(datadirr, header, it_num, speclist, x, x_new, delta,    \
                        x_bar, x_bar_new, delta_bar, file_results, doprint)
            form.fancyout_results(datadirr, header, it_num, speclist, x, x_new, \
                                  delta, x_bar, x_bar_new, delta_bar, pressure, \
                                  temp, file_fancyResults, doprint)
Ejemplo n.º 9
0
# Correct location_TEA name
if location_out[-1] != '/':
    location_out += '/'

# Read run-time arguments
header = argv[1:][0]              # Name of header file
desc   = argv[1:][1]              # Directory name

# Create and name outputs and results directories if they do not exist
datadir   = location_out + desc + '/outputs/' + 'transient/'  

# If output directory does not exist already, make it
if not os.path.exists(datadir): os.makedirs(datadir)

# Read in values from header file
pressure, temp, i, j, speclist, a, b, c = form.readheader(header)

# Print b values for debugging purposes
if doprint:
    print("b values: " + str(b))

# Find chunk of ai_j array that will allow the corresponding yi values
#      to be free variables such that all elements are considered
for n in np.arange(i - j + 1):
    # Get lower and upper indices for chunk of ai_j array to check
    lower = n
    upper = n + j
    
    # Retrieve chunk of ai_j that would contain free variables
    a_chunk = a[lower:upper]
    
Ejemplo n.º 10
0
def balanceFunction(head, destination, location_out):
    if location_out[-1] != '/':
        location_out += '/'

    header = head              # Name of header file
    desc   = destination              # Directory name

    # Create and name outputs and results directories if they do not exist
    datadir   = location_out + desc + '/outputs/' + 'transient/'  

    # If output directory does not exist already, make it
    if not os.path.exists(datadir): os.makedirs(datadir)

    # Read in values from header file
    pressure, temp, i, j, speclist, a, b, c = form.readheader(header)

    # Print b values for debugging purposes
    if doprint:
        print("b values: " + str(b))

    # Find chunk of ai_j array that will allow the corresponding yi values
    #      to be free variables such that all elements are considered
    for n in np.arange(i - j + 1):
        # Get lower and upper indices for chunk of ai_j array to check
        lower = n
        upper = n + j
        
        # Retrieve chunk of ai_j that would contain free variables
        a_chunk = a[lower:upper]
        
        # Sum columns to get total of ai_j in chunk for each species 'j'
        check = map(sum,zip(*a_chunk))
        
        # Look for zeros in check. If a zero is found, this chunk of data can't 
        # be used for free variables, as this signifies an element is ignored
        has_zero = 0 in check
        
        # If zero not found, create list of free variables' indices
        if has_zero == False:
            free_id = []
            for m in np.arange(j):
                if doprint == True:
                    print('Using y_' + np.str(n + m + 1) + ' as a free variable')
                free_id = np.append(free_id, n + m)
            break

    # Set initial guess of non-free y_i 
    scale = 0.1

    # Assume that all or some y_i are negative or zeros
    nofit = True

    # Loop until all y_i are non-zero positive
    while nofit:
        # Set up list of 'known' initial mole numbers before and after free chunk
        pre_free = np.zeros(free_id[0]) + scale
        post_free = np.zeros(i - free_id[-1] - 1) + scale
        
        # Set up list of free variables
        free = []
        for m in np.arange(j):
            name = 'y_unknown_' + np.str(m)
            free = np.append(free, Symbol(name))

        # Combine free and 'known' to make array of y_initial mole numbers
        y_init = np.append(pre_free,      free)
        y_init = np.append(  y_init, post_free)

        # Make 'j' equations satisfying mass balance equation (17) in TEA theory doc:
        # sum_i(ai_j * y_i) = b_j
        eq = [[]]
        for m in np.arange(j):
            rhs = 0
            for n in np.arange(i):
                rhs += a[n, m] * y_init[n]
            rhs -= b[m]
            eq = np.append(eq, rhs)
            
        # Solve system of linear equations to get free y_i variables
        result = solve(list(eq), list(free), rational=False)
        
        # Correct for no-solution-found results. 
        # If no solution found, decrease scale size.
        if result == []:
            scale /= 10
            if doprint:
                print("Correcting initial guesses for realistic mass. \
                        Trying " + str(scale) + "...")

        # Correct for negative-mass results.  If found, decrease scale size.
        else:
            # Assume no negatives and check
            hasneg = False    
            for m in np.arange(j):
                if result[free[m]] < 0: 
                    hasneg = True
            # If negatives found, decrease scale size
            if hasneg:
                scale /= 10
                if doprint:
                    print("Negative numbers found in fit.")
                    print("Correcting initial guesses for realistic mass. \
                            Trying " + str(scale) + "...")
            # If no negatives found, exit the loop (good fit is found)
            else:
                nofit = False
                if doprint:
                    print(str(scale) + " provided a viable initial guess.")
        
    # Gather the results
    fit = []
    for m in np.arange(j):
        fit = np.append(fit, result[free[m]])

    # Put the result into the final y_init array
    y_init[free_id[0]:free_id[j-1]+1] = fit

    # This part of the code is only for debugging purposes 
    # It rounds the values and checks whether the balance equation is satisfied
    # No values are changed and this serves solely as a check 
    if doprint == True:
        print('\nCHECKS:')
    for m in np.arange(j):
        bool = round((sum(a[:,m] * y_init[:])), 2) == round(b[m], 2)
        if bool == True:
            if doprint == True:
                print('Equation ' + np.str(m+1) + ' is satisfied.')
        if bool == False:
            print('Equation ' + np.str(m+1) + \
                             ' is NOT satisfied. Check for errors!')

    # Set iteration number to zero
    it_num    = 0

    # Put all initial mole numbers in y array
    y         = y_init

    # Make y_bar (sum of all y values)
    y_bar     = np.sum(y)

    # Initialize delta variables to 0. (this signifies the first iteration)
    delta     = np.zeros(i)   
    delta_bar = np.sum(delta) 

    # Name output files with corresponding iteration number name
    file       = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                                  '-machine-read.txt'
    file_fancy = datadir + '/lagrange-iteration-' + np.str(it_num) + \
                                                        '-visual.txt'

    # Put results into machine readable file
    form.output(datadir, header, it_num, speclist, y, y, delta, \
                y_bar, y_bar, delta_bar, file, doprint)

    # Put results into human readable file
    form.fancyout(datadir, it_num, speclist, y, y, delta, y_bar, \
                  y_bar, delta_bar, file_fancy, doprint)
Ejemplo n.º 11
0
def lagrange(it_num, datadir, doprint, direct):
    '''
    DOCSTRING
    '''
    
    infile = datadir + '/lagrange-iteration-' + np.str(it_num - 1) + '.txt'
    
    # Read in values from header.txt and previous output
    #if direct:
    input = direct
    #else:
    #    input = form.readoutput(infile)
    
    header = input[0]
    pressure, temp, i, j, speclist, a, b, g_RT = form.readheader(header)
    
    y     = input[4] # 'x' in output file, using final values as new initials
    y_bar = input[7] # see above
    
    # Perform checks to be safe
    it_num_check = input[1]
    speclist_check = input[2]
    
    check = np.array([
            it_num_check != it_num - 1,
            False in (speclist_check == speclist) ])
    
    if check[0]:
        print("\n\nMAJOR ERROR! Read in file's it_num is not the most previous iteration!\n\n")
    
    if check[1]:
        print("\n\nMAJOR ERROR! Read in file uses different species order/list!\n\n")
    
    # FINDME: DEGRADED, CHECK IS SALVAGABLE
    save_JANAF = False
    if save_JANAF:
        dir_save = os.getcwd()
        # CHANGE THIS TO MATCH DESC IN runatm.py or runinput.py
        desc_save = 'checkJANAF'
        JANAF_file_save = '/outputs/' + desc_save + '/JANAF_check_' + '%.0f'%temp + 'K.txt' 
        f = open(dir_save + JANAF_file_save, 'w+')
        for r in np.arange(np.size(speclist)):
            f.write(speclist[r] + '  ' + '%4.3f'%c[r] + '\n')
            #print(speclist[r], c[r])
        f.close()
        
    
    # Create 'c' value from 'g_RT' value with pressure correction    
    c = g_RT + np.log(pressure)
    
    # Set up values of fi(Y) over different values of i
    fi_y = np.zeros(i)
    
    for n in np.arange(i):
        y_frac  = np.float(y[n] / y_bar)
        fi_y[n] = y[n] * ( c[n] + np.log(y_frac) )
    
    # ### Set up values of rjk over different values of i
    # NOTE: j , k = 1, 2, ... , total elements 
    #       so rj_k = rk_j, making a matrix symmetrical across the diagonal
    k = j # Both the same size
    rjk = np.zeros((j,k))
    for l in np.arange(k):
        for m in np.arange(j):
            foo = 0.0
            for n in np.arange(i): # summate (ai_j * ai_k * yi) over i
                foo += a[n, m] * a[n, l] * y[n]
            rjk[m, l] = foo
    
    
    # ### Set up value of u
    # Depends on if you want output of u or output of xi
    # For now, use u for simplicity in checking
    #u = -1. + (x_bar/y_bar)
    u = Symbol('u')
    
    # ### Set up pi_j variables, where j is species index
    # Example: pi_2 is lagrangian multipier of N (j = 2)
    pi = []
    for m in np.arange(j):
        name = 'pi_' + np.str(m+1)
        pi = np.append(pi, Symbol(name))
    
    # ### Set up r_jk * pi_j summations
    # There will be j x k terms of r_jk * pi_j
    sq_pi = [pi]
    for m in np.arange(j-1):
        # Make square array of pi values with shape j x k
        sq_pi = np.append(sq_pi, [pi], axis = 0) 
    
    # Multiply rjk * sq_pi to get array of rjk * pi_j 
    rpi = rjk * sq_pi 
    
    # ################################################################### #
    # ####################### SET FINAL EQUATIONS! ###################### #
    # ################################################################### #
    # Total number of equations is j + 1
    
    # Set up ai_j * fi(Y) summations
    aij_fiy = np.zeros((j))
    for m in np.arange(j):
        foo = 0.0
        for n in np.arange(i): # summate (ai_j * fi(Y)) over i
            foo += a[n,m] * fi_y[n]
        aij_fiy[m] = foo
    
    # Create first j-1 equations
    for m in np.arange(j):
        if m == 0:
            equations   = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
        else:
            lagrange_eq = np.array([np.sum(rpi[m]) + b[m]*u - aij_fiy[m]])
            equations   = np.append(equations, lagrange_eq)
    
    # Last equation, only one here
    bpi = b * pi
    lagrange_eq = np.array([np.sum(bpi) - np.sum(fi_y)])
    equations = np.append(equations, lagrange_eq)
            
    # Solve final system of equations
    unknowns = list(pi)
    unknowns.append(u)
    fsol = solve(list(equations), unknowns)
    
    
    # ################################################################### #
    # ########################## GET xi VALUES ########################## #
    # ################################################################### #
    
    # Make array of pi values
    pi_f = []
    for m in np.arange(j):
        pi_f = np.append(pi_f, [fsol[pi[m]]])
    
    # Calculate x_bar from solution to 'u'
    u_f = fsol[u]
    x_bar = (u_f + 1.)*y_bar
    
    # Start array for x values size of i
    x = np.zeros(i)
    
    # Apply lagrange solution for final values (eq 14)
    for n in np.arange(i):
        sum_pi_aij = 0.0
        for m in np.arange(j):
            sum_pi_aij += pi_f[m] * a[n, m]
        x[n] = - fi_y[n] + (y[n]/y_bar) * x_bar \
             + sum_pi_aij * y[n]
    
    # ### Now have final mole values for this iteration!         
    # Also note the distance between initial and final
    # Correct x_bar
    x_bar = np.sum(x)
    delta = x - y
    delta_bar = x_bar - y_bar
    
    # Export all values into output files or via memory 
    #TESTING: ALWAYS WRITE FILES
    form.output_nocorr(datadir, header, it_num, speclist, y, x, delta, y_bar, x_bar, delta_bar, doprint)
    form.fancyout_nocorr(datadir, it_num, speclist, y, x, delta, y_bar, x_bar, delta_bar, doprint)
       
    #if direct:
    return [header, it_num, speclist, y, x, delta, y_bar, x_bar, delta_bar]