In [1]:
from pycalphad import Database
dbf = Database('Mg-piecewise-example.tdb')


/Users/brandon/anaconda3/envs/pycalphad/lib/python3.6/site-packages/xarray/core/formatting.py:16: FutureWarning: The pandas.tslib module is deprecated and will be removed in a future version.
  from pandas.tslib import OutOfBoundsDatetime

In [2]:
from sympy import Symbol
from sympy.utilities import topological_sort
from pycalphad import variables as v

def extract_symbol_value(symbol):
    """Return the value of a Piecewise if it only has one expression
    """
    # A Piecewise with a length of 2 has the expression over the range and then 0 otherwise.
    # We want to return the expression in this case, otherwise the expression is a "real" Piecewise.
    if len(symbol.args) == 2:
        return symbol.args[0].expr
    return symbol

def sorted_symbols(symbols):
    """Takes a dictionary of {Symbol: Piecewise} and returns the topological sort replacement
    """
    # Topological sorting requires the verticies and edges of the a graph of symbol dependencies.
    verticies = list(symbols.keys())
    edges = []
    for vertex in verticies:
        free_symbols = symbols[vertex].free_symbols
        # Filter out the StateVariables.
        # This will ensure P, T variables are not included in the graph because they can be variables in TDBs.
        free_symbols = [symbol for symbol in free_symbols if not isinstance(symbol, v.StateVariable)]
        # construct the edges (dependencies) of the symbols if there are any
        if len(free_symbols):
            edges.extend([(str(vertex), str(symbol)) for symbol in free_symbols])
    return topological_sort((verticies, edges))

def get_reduced_expression(dbf, symbol):
    """Return an expression for the passed symbol (as a string) reduced to only a function of state variables
    """
    # To reduce an expression, we have to pass a list of substitions to the expression in the order
    # we want to substitute them to get to having only StateVaribles as degrees of freedom.
    # Topological sorting orders the replacements in the correct order.
    topologically_sorted_symbols = sorted_symbols(dbf.symbols)
    # Then we construct the values that we will replace each symbol with, deconstructing the
    # symbols that are Piecewise, if necessary.
    replacements = [(sym, extract_symbol_value(dbf.symbols[sym])) for sym in topologically_sorted_symbols]
    return dbf.symbols[symbol].subs(replacements)

In [3]:
print(sorted_symbols(dbf.symbols))


['GFCCMg', 'GHSERMg', 'GLIQMg', 'GEINMg', 'GEINMgF', 'CMgF', 'BMgF', 'AMgF', 'GEINMgS', 'CMgS', 'BMgS', 'AMgS']

In [4]:
print(get_reduced_expression(dbf, 'GHSERMg'))


Piecewise((0.0047195465*T**2 + 3.2404446864*T*log(exp(95.82831/T) - 1.0) + 21.6535319868*T*log(exp(247.8675/T) - 1.0) - 10652.1012810789, And(T < 36.71926, T >= 0.01)), (-1.53643054262276e-5*T**3 + 0.00810454205399037*T**2 - 0.124294531845816*T*log(T) + 3.2404446864*T*log(exp(95.82831/T) - 1.0) + 21.6535319868*T*log(exp(247.8675/T) - 1.0) + 0.385723396310737*T - 10653.6226154894, And(T < 143.18844, T >= 36.71926)), (-0.0050954035*T**2 + 1.765785080115*T*log(T) + 3.2404446864*T*log(exp(95.82831/T) - 1.0) + 21.6535319868*T*log(exp(247.8675/T) - 1.0) - 8.0518972866125*T - 10563.4100984519, And(T < 922.205302616508, T >= 143.18844)), (-34.3088*T*log(T) + 204.341485347575*T - 13775.4156328263 + 9.4687256586798e+27/T**9, And(T < 3000.0, T >= 922.205302616508)), (0, True))

In [5]:
print(get_reduced_expression(dbf, 'GLIQMg'))


Piecewise((-2.2050100179942e-6*T**3 - 4.63131660076452e-5*T**2 + 3.2404446864*T*log(exp(95.82831/T) - 1.0) + 21.6535319868*T*log(exp(247.8675/T) - 1.0) - 7.6943066168765*T - 2555.58510336379, And(T < 298.15, T >= 0.01)), (-8.0176e-20*T**7 - 1.393669e-6*T**3 + 0.0004858*T**2 - 26.1849782*T*log(T) + 134.838617*T - 165.096999676889 + 78950/T, And(T < 922.205302616508, T >= 298.15)), (-34.3088*T*log(T) + 195.324057*T - 5439.86911093575, And(T < 3000.0, T >= 922.205302616508)), (0, True))

In [6]:
print(get_reduced_expression(dbf, 'GFCCMg'))


Piecewise((-2.18283562784578e-6*T**3 - 6.21802726222479e-5*T**2 + 3.2404446864*T*log(exp(95.82831/T) - 1.0) + 21.6535319868*T*log(exp(247.8675/T) - 1.0) + 0.246565697987779*T - 8158.16393259455, And(T < 298.15, T >= 0.01)), (-1.393669e-6*T**3 + 0.0004858*T**2 - 26.1849782*T*log(T) + 142.775547*T - 5767.34 + 78950/T, And(T < 922.205302616508, T >= 298.15)), (-34.3088*T*log(T) + 203.816215*T - 11530.1836392866 + 1.038192e+28/T**9, And(T < 3000.0, T >= 922.205302616508)), (0, True))

In [ ]: