def S(self, u_, p_, ivar=None, tang=False): C_ = variable(self.kin.C(u_)) stress = constantvalue.zero((3, 3)) # volumetric (kinematic) growth if self.mat_growth: theta_ = ivar["theta"] # material has to be evaluated with C_e only, however total S has # to be computed by differentiating w.r.t. C (S = 2*dPsi/dC) self.mat = materiallaw(self.C_e(C_, theta_), self.I) else: self.mat = materiallaw(C_, self.I) m = 0 for matlaw in self.matmodels: stress += self.add_stress_mat(matlaw, self.matparams[m], ivar, C_) m += 1 # add remodeled material if self.mat_growth and self.mat_remodel: self.stress_base = stress self.stress_remod = constantvalue.zero((3, 3)) m = 0 for matlaw in self.matmodels_remod: self.stress_remod += self.add_stress_mat( matlaw, self.matparams_remod[m], ivar, C_) m += 1 # update the stress expression: S = (1-phi(theta)) * S_base + phi(theta) * S_remod stress = ( 1. - self.phi_remod(theta_) ) * self.stress_base + self.phi_remod(theta_) * self.stress_remod # if we have p (hydr. pressure) as variable in a 2-field functional if self.incompr_2field: if self.mat_growth: # TeX: S_{\mathrm{vol}} = -2 \frac{\partial[p(J^{\mathrm{e}}-1)]}{\partial \boldsymbol{C}} stress += -2. * diff( p_ * (sqrt(det(self.C_e(C_, theta_))) - 1.), C_) else: # TeX: S_{\mathrm{vol}} = -2 \frac{\partial[p(J-1)]}{\partial \boldsymbol{C}} = -Jp\boldsymbol{C}^{-1} stress += -2. * diff(p_ * (sqrt(det(C_)) - 1.), C_) if tang: return 2. * diff(stress, C_) else: return stress
def add_stress_mat(self, matlaw, mparams, ivar, C_): # sanity check if self.incompr_2field and '_vol' in matlaw: raise AttributeError("Do not use a volumetric material law when using a 2-field variational principle with pressure dofs!") if matlaw == 'neohooke_dev': return self.mat.neohooke_dev(mparams,C_) elif matlaw == 'mooneyrivlin_dev': return self.mat.mooneyrivlin_dev(mparams,C_) elif matlaw == 'holzapfelogden_dev': return self.mat.holzapfelogden_dev(mparams,self.kin.fib_funcs[0],self.kin.fib_funcs[1],C_) elif matlaw == 'guccione_dev': return self.mat.guccione_dev(mparams,self.kin.fib_funcs[0],self.kin.fib_funcs[1],C_) elif matlaw == 'stvenantkirchhoff': return self.mat.stvenantkirchhoff(mparams,C_) elif matlaw == 'ogden_vol': return self.mat.ogden_vol(mparams,C_) elif matlaw == 'sussmanbathe_vol': return self.mat.sussmanbathe_vol(mparams,C_) elif matlaw == 'active_fiber': tau_a_ = ivar["tau_a"] return self.mat.active_fiber(tau_a_, self.kin.fib_funcs[0]) elif matlaw == 'active_iso': tau_a_ = ivar["tau_a"] return self.mat.active_iso(tau_a_) elif matlaw == 'inertia': # density is added to kinetic virtual work return constantvalue.zero((3,3)) elif matlaw == 'rayleigh_damping': # Rayleigh damping is added to virtual work return constantvalue.zero((3,3)) elif matlaw == 'growth': # growth (and remodeling) treated separately return constantvalue.zero((3,3)) else: raise NameError('Unknown solid material law!')
def __new__(cls, a, b): # Conversion a = as_ufl(a) b = as_ufl(b) # Type checking if not is_true_ufl_scalar(a): error("Cannot take the power of a non-scalar expression %s." % ufl_err_str(a)) if not is_true_ufl_scalar(b): error("Cannot raise an expression to a non-scalar power %s." % ufl_err_str(b)) # Simplification if isinstance(a, ScalarValue) and isinstance(b, ScalarValue): return as_ufl(a._value**b._value) if isinstance(b, Zero): return IntValue(1) if isinstance(a, Zero) and isinstance(b, ScalarValue): if isinstance(b, ComplexValue): error("Cannot raise zero to a complex power.") bf = float(b) if bf < 0: error("Division by zero, cannot raise 0 to a negative power.") else: return zero() if isinstance(b, ScalarValue) and b._value == 1: return a # Construction self = Operator.__new__(cls) self._init(a, b) return self
def set_acc_vel(self, u, u_old, v_old, a_old): # set forms for acc and vel if self.timint == 'genalpha': acc = self.update_a_newmark(u, u_old, v_old, a_old, ufl=True) vel = self.update_v_newmark(acc, u, u_old, v_old, a_old, ufl=True) elif self.timint == 'ost': acc = self.update_a_ost(u, u_old, v_old, a_old, ufl=True) vel = self.update_v_ost(acc, u, u_old, v_old, a_old, ufl=True) elif self.timint == 'static': acc = constantvalue.zero(3) vel = constantvalue.zero(3) else: raise NameError( "Unknown time-integration algorithm for solid mechanics!") return acc, vel
def set_acc(self, v, v_old, a_old): # set forms for acc and vel if self.timint == 'ost': acc = self.update_a_ost(v, v_old, a_old, ufl=True) elif self.timint == 'static': acc = constantvalue.zero(3) else: raise NameError( "Unknown time-integration algorithm for fluid mechanics!") return acc
def determinant_expr(A): "Compute the (pseudo-)determinant of A." sh = A.ufl_shape if isinstance(A, Zero): return zero() elif sh == (): return A elif sh[0] == sh[1]: if sh[0] == 1: return A[0, 0] elif sh[0] == 2: return determinant_expr_2x2(A) elif sh[0] == 3: return determinant_expr_3x3(A) else: return pseudo_determinant_expr(A) # TODO: Implement generally for all dimensions? error("determinant_expr not implemented for shape %s." % (sh, ))
def __new__(cls, a, b): a = as_ufl(a) b = as_ufl(b) if not is_true_ufl_scalar(a): error("Cannot take the power of a non-scalar expression.") if not is_true_ufl_scalar(b): error("Cannot raise an expression to a non-scalar power.") if isinstance(a, ScalarValue) and isinstance(b, ScalarValue): return as_ufl(a._value ** b._value) if a == 0 and isinstance(b, ScalarValue): bf = float(b) if bf < 0: error("Division by zero, annot raise 0 to a negative power.") else: return zero() if b == 1: return a if b == 0: return IntValue(1) # construct and initialize a new Power object self = AlgebraOperator.__new__(cls) self._init(a, b) return self