In [2]:
%load_ext Cython
In [68]:
%%cython
from pycalphad.core.rksum import RedlichKisterSum
from pycalphad import Database
cimport numpy as np
import numpy as np
from tinydb import where
from sympy import Symbol
cdef np.ndarray[ndim=1, dtype=np.float64_t] _eval_rk_matrix_gradient(double[:,:] coef_mat, double[:,:] symbol_mat,
double[:] eval_row, double[:] parameters):
cdef np.ndarray[ndim=1, dtype=np.float64_t] out = np.zeros(eval_row.shape[0]-2)
cdef double result = 0
cdef double prod_result
cdef int row_idx1 = 0
cdef int row_idx2 = 0
cdef int col_idx = 0
cdef int dof_idx
# eval_row order: P,T,ln(P),ln(T),y...
# dof order: P,T,y...
# coef_mat order: low_temp,high_temp,P,T,ln(P),ln(T),y...,constant_term,parameter_value
for dof_idx in range(eval_row.shape[0]-2):
if coef_mat.shape[1] > 0:
for row_idx1 in range(coef_mat.shape[0]):
if (eval_row[1] >= coef_mat[row_idx1, 0]) and (eval_row[1] < coef_mat[row_idx1, 1]):
if dof_idx < 2:
# special handling for state variables since they also can have a ln term
if coef_mat[row_idx1, 2+dof_idx] != 0:
prod_result = coef_mat[row_idx1, coef_mat.shape[1]-2] * coef_mat[row_idx1, coef_mat.shape[1]-1]
for col_idx in range(coef_mat.shape[1]-4):
if col_idx == dof_idx:
prod_result *= (eval_row[col_idx]**(coef_mat[row_idx1, 2+col_idx]-1) * eval_row[2+col_idx]**(coef_mat[row_idx1, 4+col_idx]-1) * (coef_mat[row_idx1, 4+col_idx]+coef_mat[row_idx1, 2+col_idx]*(eval_row[2+col_idx])))
else:
prod_result *= (eval_row[col_idx] ** coef_mat[row_idx1, 2+col_idx])
out[dof_idx] += prod_result
else:
if coef_mat[row_idx1, 4+dof_idx] != 0:
prod_result = coef_mat[row_idx1, coef_mat.shape[1]-2] * coef_mat[row_idx1, coef_mat.shape[1]-1]
for col_idx in range(coef_mat.shape[1]-4):
if col_idx == 2+dof_idx:
prod_result *= (coef_mat[row_idx1, 4+dof_idx] * eval_row[col_idx] ** (coef_mat[row_idx1, 2+col_idx] - 1))
else:
prod_result *= (eval_row[col_idx] ** coef_mat[row_idx1, 2+col_idx])
out[dof_idx] += prod_result
if symbol_mat.shape[1] > 0:
for row_idx2 in range(symbol_mat.shape[0]):
if (eval_row[1] >= symbol_mat[row_idx2, 0]) and (eval_row[1] < symbol_mat[row_idx2, 1]):
if dof_idx < 2:
# special handling for state variables since they also can have a ln term
if coef_mat[row_idx2, 2+dof_idx] != 0:
prod_result = coef_mat[row_idx2, coef_mat.shape[1]-2] * parameters[<int>symbol_mat[row_idx2, symbol_mat.shape[1]-1]]
for col_idx in range(coef_mat.shape[1]-4):
if col_idx == dof_idx:
prod_result *= (eval_row[col_idx]**(coef_mat[row_idx1, 2+col_idx]-1) * eval_row[2+col_idx]**(coef_mat[row_idx1, 4+col_idx]-1) * (coef_mat[row_idx1, 4+col_idx]+coef_mat[row_idx1, 2+col_idx]*(eval_row[2+col_idx])))
else:
prod_result *= (eval_row[col_idx] ** coef_mat[row_idx1, 2+col_idx])
out[dof_idx] += prod_result
else:
if coef_mat[row_idx1, 4+dof_idx] != 0:
prod_result = coef_mat[row_idx2, coef_mat.shape[1]-2] * parameters[<int>symbol_mat[row_idx2, symbol_mat.shape[1]-1]]
for col_idx in range(coef_mat.shape[1]-4):
if col_idx == 2+dof_idx:
prod_result *= (coef_mat[row_idx2, 4+dof_idx] * eval_row[col_idx] ** (coef_mat[row_idx2, 2+col_idx] - 1))
else:
prod_result *= (eval_row[col_idx] ** coef_mat[row_idx2, 2+col_idx])
out[dof_idx] += prod_result
return out
dbf = Database('alcocr-sandbox.tdb')
param_query = (
(where('phase_name') == 'LIQUID') & \
(where('parameter_type') == "G")
)
parameters = {}
all_symbols = dbf.symbols.copy()
# Convert string symbol names to sympy Symbol objects
# This makes xreplace work with the symbols dict
all_symbols = dict([(Symbol(s), val) for s, val in all_symbols.items()])
for param in parameters.keys():
all_symbols.pop(param, None)
rks = RedlichKisterSum(['AL','CO','CR','VA'], dbf.phases['LIQUID'], dbf.search, param_query, list(parameters.keys()), all_symbols)
exx = _eval_rk_matrix_gradient(rks.output_matrix[2:4,:], np.array([[]]),
np.array([1013235, 300, np.log(101325), np.log(300), 0.3, 0.3, 0.4]), np.array([]))
print(exx)
In [69]:
rks.output_matrix[2:4,:]
Out[69]:
In [70]:
-1.18418670e01 * 300 + -7.97615000e03
Out[70]:
In [ ]: