class Slide34Expr(bu.SymbExpr): # control and state variables w, s_x, s_y, Eps, Sig = w, s_x, s_y, Eps, Sig # model parameters E_T = E_T gamma_T = gamma_T K_T = K_T S_T = S_T c_T = c_T bartau = bartau E_N = E_N S_N = S_N c_N = c_N f_t = f_t f_c = f_c f_c0 = f_c0 m = m eta = eta r = r H_switch = H_switch Sig_signs = Sig_signs c_NT = c_NT S_NT = S_NT ONE = Cymbol(r'I') ZERO = Cymbol(r'O') # expressions Sig_ = Sig_.T dSig_dEps_ = dSig_dEps_.subs(0, ZERO) * ONE f_ = f_ df_dSig_ = df_dSig_.subs(0, ZERO) * ONE ddf_dEps_ = ddf_dEps_.subs(0, ZERO) * ONE phi_final_ = tr.Property() @tr.cached_property def _get_phi_final_(self): def g_ari_integrity(var1, var2): return 1 - sp.sqrt((1 - var1) * (1 - var2)) omega_NT = g_ari_integrity(omega_N, omega_T) phi_N = (1 - omega_N)**(c_N) * S_N / (r + 1) * (Y_N / S_N)**( r + 1) * H_switch phi_T = (1 - omega_T)**(c_T) * S_T / (r + 1) * (Y_T / S_T)**(r + 1) phi_NT = (1 - omega_NT)**(c_NT) * S_NT / (r + 1) * ( (Y_N + Y_T) / S_NT)**(r + 1) phi_ = f_ + ((1 - eta) * (phi_N + phi_T) + eta * phi_NT) * (bartau / (bartau - m * sig_pi)) return phi_.subs( r, 1 ) # @TODO - fix the passing of the parameter - it damages the T response Phi_final_ = tr.Property() @tr.cached_property def _get_Phi_final_(self): return -self.Sig_signs * self.phi_final_.diff(self.Sig) H_sig_pi_ = H(sig_pi) sig_eff_ = sig_pi / (1 - H(sig_pi) * omega_N) tau_eff_x_ = tau_pi_x / (1 - omega_T) tau_eff_y_ = tau_pi_y / (1 - omega_T) symb_model_params = [ 'E_T', 'gamma_T', 'K_T', 'S_T', 'c_T', 'bartau', 'E_N', 'S_N', 'c_N', 'm', 'f_t', 'f_c', 'f_c0', 'eta', 'r', 'c_NT', 'S_NT' ] # List of expressions for which the methods `get_` symb_expressions = [ ('Sig_', ('w', 's_x', 's_y', 'Sig', 'Eps')), ('dSig_dEps_', ('w', 's_x', 's_y', 'Sig', 'Eps', 'ZERO', 'ONE')), ('f_', ('Eps', 'Sig', 'H_switch')), ('df_dSig_', ('Eps', 'Sig', 'H_switch', 'ZERO', 'ONE')), ('ddf_dEps_', ('Eps', 'Sig', 'H_switch', 'ZERO', 'ONE')), ('phi_final_', ('Eps', 'Sig', 'H_switch')), ('Phi_final_', ('Eps', 'Sig', 'H_switch', 'ZERO', 'ONE')), ('H_sig_pi_', ('Sig', )) ]
# - Vector of thermodynamic streses $\boldsymbol{\mathcal{S}}$ # - Helmholtz free energy $\psi(\boldsymbol{\mathcal{E}})$ # - Threshold on thermodynamical forces $f(\boldsymbol{\mathcal{S}},\boldsymbol{\mathcal{E}})$ / Yield condition # - Flow potential $\varphi(\boldsymbol{\mathcal{S}},\boldsymbol{\mathcal{E}})$ # # as symbolic equations using the sympy package. The time-stepping algorithm gets generated automatically within the thermodynamically framework. The derived evolution equations and return-mapping to the yield surface is performed using Newton scheme. import sympy as sp from bmcs_matmod.slide.cymbol import Cymbol, ccode import traits.api as tr import numpy as np from bmcs_matmod.slide.f_double_cap import FDoubleCap import bmcs_utils.api as bu from ibvpy.tmodel import MATSEval H_switch = Cymbol(r'H(\sigma^\pi)', real=True) H = lambda x: sp.Piecewise((0, x <= 0), (1, True)) # **Code generation** The derivation is adopted for the purpose of code generation both in Python and C utilizing the `codegen` package provided in `sympy`. The expressions that are part of the time stepping algorithm are transformed to an executable code directly at the place where they are derived. At the end of the notebook the C code can be exported to external files and applied in external tools. # This code is needed to lambdify expressions named with latex symbols # it removes the backslashes and curly braces upon before code generation. # from sympy.utilities.codegen import codegen # import re # def _print_Symbol(self, expr): # CodePrinter = sp.printing.codeprinter.CodePrinter # name = super(CodePrinter, self)._print_Symbol(expr) # return re.sub(r'[\{^}]','_',re.sub(r'[\\\{\}]', '', name)) # sp.printing.codeprinter.CodePrinter._print_Symbol = _print_Symbol # ## Material parameters