def holzapfelogden_dev(self, params, f0, s0, C): # anisotropic invariants - keep in mind that for growth, self.C is the elastic part of C (hence != to function input variable C) I4 = dot(dot(self.C,f0), f0) I6 = dot(dot(self.C,s0), s0) I8 = dot(dot(self.C,s0), f0) # to guarantee initial configuration is stress-free (in case of initially non-orthogonal fibers f0 and s0) I8 -= dot(f0,s0) a_0, b_0 = params['a_0'], params['b_0'] a_f, b_f = params['a_f'], params['b_f'] a_s, b_s = params['a_s'], params['b_s'] a_fs, b_fs = params['a_fs'], params['b_fs'] try: fiber_comp = params['fiber_comp'] except: fiber_comp = False # conditional parameters: fibers are only active in tension if fiber_comp is False if not fiber_comp: a_f_c = conditional(ge(I4,1.), a_f, 0.) a_s_c = conditional(ge(I6,1.), a_s, 0.) else: a_f_c = a_f a_s_c = a_s # Holzapfel-Ogden (Holzapfel and Ogden 2009) material w/o split applied to invariants I4, I6, I8 (Sansour 2008) psi_dev = a_0/(2.*b_0)*(exp(b_0*(self.Ic_bar-3.)) - 1.) + \ a_f_c/(2.*b_f)*(exp(b_f*(I4-1.)**2.) - 1.) + a_s_c/(2.*b_s)*(exp(b_s*(I6-1.)**2.) - 1.) + \ a_fs/(2.*b_fs)*(exp(b_fs*I8**2.) - 1.) S = 2.*diff(psi_dev,C) return S
def g(self, lam): amp_min = self.params['amp_min'] amp_max = self.params['amp_max'] lam_threslo = self.params['lam_threslo'] lam_maxlo = self.params['lam_maxlo'] lam_threshi = self.params['lam_threshi'] lam_maxhi = self.params['lam_maxhi'] # Diss Hirschvogel eq. 2.107 # TeX: g(\lambda_{\mathrm{myo}}) = \begin{cases} a_{\mathrm{min}}, & \lambda_{\mathrm{myo}} \leq \hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,lo}}, \\ a_{\mathrm{min}}+\frac{1}{2}\left(a_{\mathrm{max}}-a_{\mathrm{min}}\right)\left(1-\cos \frac{\pi(\lambda_{\mathrm{myo}}-\hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,lo}})}{\hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,lo}}-\hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,lo}}}\right), & \hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,lo}} \leq \lambda_{\mathrm{myo}} \leq \hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,lo}}, \\ a_{\mathrm{max}}, & \hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,lo}} \leq \lambda_{\mathrm{myo}} \leq \hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,hi}}, \\ a_{\mathrm{min}}+\frac{1}{2}\left(a_{\mathrm{max}}-a_{\mathrm{min}}\right)\left(1-\cos \frac{\pi(\lambda_{\mathrm{myo}}-\hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,hi}})}{\hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,hi}}-\hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,hi}}}\right), & \hat{\lambda}_{\mathrm{myo}}^{\mathrm{thres,hi}} \leq \lambda_{\mathrm{myo}} \leq \hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,hi}}, \\ a_{\mathrm{min}}, & \lambda_{\mathrm{myo}} \geq \hat{\lambda}_{\mathrm{myo}}^{\mathrm{max,hi}} \end{cases} return conditional( le(lam, lam_threslo), amp_min, conditional( And(ge(lam, lam_threslo), le(lam, lam_maxlo)), amp_min + 0.5 * (amp_max - amp_min) * (1. - cos(pi * (lam - lam_threslo) / (lam_maxlo - lam_threslo))), conditional( And(ge(lam, lam_maxlo), le(lam, lam_threshi)), amp_max, conditional( And(ge(lam, lam_threshi), le(lam, lam_maxhi)), amp_min + 0.5 * (amp_max - amp_min) * (1. - cos(pi * (lam - lam_maxhi) / (lam_maxhi - lam_threshi))), conditional(ge(lam, lam_maxhi), amp_min, as_ufl(0))))))
def __init__(self, functionSpace, value, xL, xR, eps=1e-10): cond = 1 x = ufl.SpatialCoordinate(functionSpace) for l, r, c in zip(xL, xR, x): if l is not None: cond *= ufl.conditional(c > l - eps, 1, 0) if r is not None: cond *= ufl.conditional(c < r + eps, 1, 0) DirichletBC.__init__(self, functionSpace, value, cond)
def increase_conductivity(self, cond, e): # Set up the three way choice function intermediate = e * self.k + self.h not_less_than = ufl.conditional(ufl.gt(e, self.threshold_irreversible), self.sigma_end, intermediate) cond_expression = ufl.conditional(ufl.lt(e, self.threshold_reversible), self.sigma_start, not_less_than) # Project this onto the function space cond_function = d.project(ufl.Max(cond_expression, cond), cond.function_space()) cond.assign(cond_function)
def test_conditional(mode, compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) x = ufl.SpatialCoordinate(cell) condition = ufl.Or(ufl.ge(ufl.real(x[0] + x[1]), 0.1), ufl.ge(ufl.real(x[1] + x[1]**2), 0.1)) c1 = ufl.conditional(condition, 2.0, 1.0) a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx x1x2 = ufl.real(x[0] + ufl.as_ufl(2) * x[1]) c2 = ufl.conditional(ufl.ge(x1x2, 0), 6.0, 0.0) b = c2 * ufl.conj(v) * ufl.dx forms = [a, b] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) form0 = compiled_forms[0][0].create_cell_integral(-1) form1 = compiled_forms[1][0].create_cell_integral(-1) ffi = cffi.FFI() c_type, np_type = float_to_type(mode) A1 = np.zeros((3, 3), dtype=np_type) w1 = np.array([1.0, 1.0, 1.0], dtype=np_type) c = np.array([], dtype=np.float64) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.array([[2, -1, -1], [-1, 1, 0], [-1, 0, 1]], dtype=np_type) assert np.allclose(A1, expected_result) A2 = np.zeros(3, dtype=np_type) w2 = np.array([1.0, 1.0, 1.0], dtype=np_type) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form1.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.ones(3, dtype=np_type) assert np.allclose(A2, expected_result)
def test_cpp_formatting_of_conditionals(): x, y = ufl.SpatialCoordinate(ufl.triangle) # Test conditional expressions assert expr2cpp(ufl.conditional(ufl.lt(x, 2), y, 3)) \ == "x[0] < 2 ? x[1]: 3" assert expr2cpp(ufl.conditional(ufl.gt(x, 2), 4 + y, 3)) \ == "x[0] > 2 ? 4 + x[1]: 3" assert expr2cpp(ufl.conditional(ufl.And(ufl.le(x, 2), ufl.ge(y, 4)), 7, 8)) \ == "x[0] <= 2 && x[1] >= 4 ? 7: 8" assert expr2cpp(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8)) \ == "x[0] == 2 || x[1] != 4 ? 7: 8"
def handle_conditional(v, si, deps, SV_factors, FV, sv2fv, e2fi): fac0 = SV_factors[deps[0]] fac1 = SV_factors[deps[1]] fac2 = SV_factors[deps[2]] assert not fac0, "Cannot have argument in condition." if not (fac1 or fac2): # non-arg ? non-arg : non-arg # Record non-argument subexpression sv2fv[si] = add_to_fv(v, FV, e2fi) factors = noargs else: f0 = FV[sv2fv[deps[0]]] f1 = FV[sv2fv[deps[1]]] f2 = FV[sv2fv[deps[2]]] # Term conditional(c, argument, non-argument) is not legal unless non-argument is 0.0 assert fac1 or isinstance(f1, Zero) assert fac2 or isinstance(f2, Zero) assert () not in fac1 assert () not in fac2 z = as_ufl(0.0) # In general, can decompose like this: # conditional(c, sum_i fi*ui, sum_j fj*uj) -> sum_i conditional(c, fi, 0)*ui + sum_j conditional(c, 0, fj)*uj mas = sorted(set(fac1.keys()) | set(fac2.keys())) factors = {} for k in mas: fi1 = fac1.get(k) fi2 = fac2.get(k) f1 = z if fi1 is None else FV[fi1] f2 = z if fi2 is None else FV[fi2] factors[k] = add_to_fv(conditional(f0, f1, f2), FV, e2fi) return factors
def compute_welding_size(evo, V, threshold_temp, x, ds): '''Computes either the welding depth or the welding radius. Parameters: evo: ndarray The coefficients of the solution to the corresponding forward problem in the basis of the space V (see solve_forward). V: dolfin.FunctionSpace The FEM space of the problem being solved. threshold_temp: float The threshold temperature used as a criterion for successful welding. ds: dolfin.Measure The measure on either the symmetry axis (for welding depth) or the top boundary (for welding radius). Returns: evo_size: ndarray Contains size of either the welding depth or the welding radius over all time steps. ''' theta_k = dolfin.Function(V) Nt = len(evo) - 1 evo_size = np.zeros(Nt+1) for k in range(Nt+1): theta_k.vector().set_local(evo[k]) evo_size[k] = dolfin.assemble( conditional(ge(theta_k, threshold_temp), 1., 0.) * ds ) return evo_size
def p_sat(temp): """Water vapour saturation pressure Parameters ---------- temp0: Previous temp function [K] Note ---- Kunzel 1995, page 40, formula (50). """ a = conditional(ge(temp, 273.15), 17.08, 22.44) theta0 = conditional(ge(temp, 273.15), 234.18, 272.44) return 611. * exp(a * (temp - 273.15) / (theta0 + (temp - 273.15)))
def bessi0(x): """ Modified Bessel function of the first kind. Code taken from [Flannery et al. 1992] B.P. Flannery, W.H. Press, S.A. Teukolsky, W. Vetterling, "Numerical recipes in C", Press Syndicate of the University of Cambridge, New York (1992). """ ax = abs(x) y1 = x / 3.75 y1 *= y1 expr1 = 1.0 + y1 * (3.5156229 + y1 * (3.0899424 + y1 * (1.2067492 + y1 * (0.2659732 + y1 * (0.360768e-1 + y1 * 0.45813e-2))))) y2 = 3.75 / ax expr2 = (ufl.exp(ax) / ufl.sqrt(ax) * (0.39894228 + y2 * (0.1328592e-1 + y2 * (0.225319e-2 + y2 * (-0.157565e-2 + y2 * (0.916281e-2 + y2 * (-0.2057706e-1 + y2 * (0.2635537e-1 + y2 * (-0.1647633e-1 + y2 * 0.392377e-2))))))))) return ufl.conditional(ax < 3.75, expr1, expr2)
def sliding_law(self, alpha, U): constants = self.params.constants bed = self.bed H = self.H rhoi = constants.rhoi rhow = constants.rhow g = constants.g sl = self.params.ice_dynamics.sliding_law vel_rp = constants.vel_rp fl_ex = self.float_conditional(H) C = alpha * alpha u, v = split(U) if sl == 'linear': B2 = C elif sl == 'weertman': N = (1 - fl_ex) * (H * rhoi * g + ufl.Min(bed, 0.0) * rhow * g) U_mag = sqrt(U[0]**2 + U[1]**2 + vel_rp**2) # Need to catch N <= 0.0 here, as it's raised to # 1/3 (forward) and -2/3 (adjoint) N_term = ufl.conditional(N > 0.0, N**(1.0 / 3.0), 0) B2 = (1 - fl_ex) * (C * N_term * U_mag**(-2.0 / 3.0)) return B2
def liquidity(theta_k, theta_kp1, solidus, implicitness=1.): theta_avg = avg(theta_k, theta_kp1, implicitness) form = theta_avg - Constant(solidus) # filter to liquid parts form *= conditional(ge(form, 0.), 1., 0.) return form
def bessk0(x): """ Modified Bessel function of the second kind. Code taken from [Flannery et al. 1992] B.P. Flannery, W.H. Press, S.A. Teukolsky, W. Vetterling, "Numerical recipes in C", Press Syndicate of the University of Cambridge, New York (1992). """ y1 = x * x / 4.0 expr1 = -ufl.ln(x / 2.0) * bessi0(x) + ( -0.57721566 + y1 * (0.42278420 + y1 * (0.23069756 + y1 * (0.3488590e-1 + y1 * (0.262698e-2 + y1 * (0.10750e-3 + y1 * 0.74e-5)))))) y2 = 2.0 / x expr2 = (ufl.exp(-x) / ufl.sqrt(x) * (1.25331414 + y2 * (-0.7832358e-1 + y2 * (0.2189568e-1 + y2 * (-0.1062446e-1 + y2 * (0.587872e-2 + y2 * (-0.251540e-2 + y2 * 0.53208e-3))))))) return ufl.conditional(x > 2, expr2, expr1)
def _rush_larsen_step(rhs_exprs, diff_rhs_exprs, linear_terms, system_size, y0, stage_solution, dt, time, a, c, v, DX, time_dep_expressions): # If we need to replace the original solution with stage solution repl = None if stage_solution is not None: if system_size > 1: repl = {y0: stage_solution} else: repl = {y0[0]: stage_solution} # If we have time dependent expressions if time_dep_expressions and abs(float(c)) > DOLFIN_EPS: time_ = time time = time + dt * float(c) repl.update(_replace_dict_time_dependent_expression(time_dep_expressions, time_, dt, float(c))) repl[time_] = time # If all terms are linear (using generalized=True) we add a safe # guard to the linearized term. See below safe_guard = sum(linear_terms) == system_size # Add componentwise contribution to rl form rl_ufl_form = ufl.zero() num_rl_steps = 0 for ind in range(system_size): # forward euler step fe_du_i = rhs_exprs[ind] * dt * float(a) # If exact integration if linear_terms[ind]: num_rl_steps += 1 # Rush Larsen step Safeguard the divisor: let's hope # diff_rhs_exprs[ind] is never 1.0e-16! Let's get rid of # this when the conditional fixes land properly in UFL. eps = Constant(1.0e-16) rl_du_i = rhs_exprs[ind] / (diff_rhs_exprs[ind] + eps) * ( ufl.exp(diff_rhs_exprs[ind] * dt) - 1.0) # If safe guard if safe_guard: du_i = ufl.conditional(ufl.lt(abs(diff_rhs_exprs[ind]), 1e-8), fe_du_i, rl_du_i) else: du_i = rl_du_i else: du_i = fe_du_i # If we should replace solution in form with stage solution if repl: du_i = ufl.replace(du_i, repl) rl_ufl_form += (y0[ind] + du_i) * v[ind] return rl_ufl_form * DX
def handle_conditional(v, fac, sf, F): fac0 = fac[0] fac1 = fac[1] fac2 = fac[2] assert not fac0, "Cannot have argument in condition." if not (fac1 or fac2): # non-arg ? non-arg : non-arg raise RuntimeError("No arguments") else: f0 = sf[0] f1 = sf[1] f2 = sf[2] # Term conditional(c, argument, non-argument) is not legal unless non-argument is 0.0 assert fac1 or isinstance(f1, Zero) assert fac2 or isinstance(f2, Zero) assert () not in fac1 assert () not in fac2 z = as_ufl(0.0) # In general, can decompose like this: # conditional(c, sum_i fi*ui, sum_j fj*uj) -> sum_i conditional(c, fi, 0)*ui + sum_j conditional(c, 0, fj)*uj mas = sorted(set(fac1.keys()) | set(fac2.keys())) factors = {} for k in mas: fi1 = fac1.get(k) fi2 = fac2.get(k) f1 = z if fi1 is None else F.nodes[fi1]['expression'] f2 = z if fi2 is None else F.nodes[fi2]['expression'] factors[k] = graph_insert(F, conditional(f0, f1, f2)) return factors
def damage(eps_eqv, mesh, E, f_t, G_f): h_cb = ufl.CellVolume(mesh) ** (1 / 3) eps0 = f_t / E eps_f = G_f / 1.0e+6 / (f_t * h_cb) + eps0 / 2 dmg = ufl.Min(1.0 - eps0 / eps_eqv * ufl.exp(- (eps_eqv - eps0) / (eps_f - eps0)), 1.0 - dmg_eps) return ufl.conditional(eps_eqv <= eps0, 0.0, 0.0 if args.damage_off else dmg)
def res_dtheta_growth(self, u_, p_, ivar, theta_old_, thres, dt, rquant): theta_ = ivar["theta"] grfnc = growthfunction(theta_, self.I) try: omega = self.gandrparams['thres_tol'] except: omega = 0 try: reduc = self.gandrparams['trigger_reduction'] except: reduc = 1 assert (reduc <= 1 and reduc > 0) # threshold should not be lower than specified (only relevant for multiscale analysis, where threshold is set element-wise) threshold = conditional(gt(thres, self.gandrparams['growth_thres']), (1. + omega) * thres, self.gandrparams['growth_thres']) # trace of elastic Mandel stress if self.growth_trig == 'volstress': trigger = reduc * tr(self.M_e(u_, p_, self.kin.C(u_), ivar)) # elastic fiber stretch elif self.growth_trig == 'fibstretch': trigger = reduc * self.fibstretch_e(self.kin.C(u_), theta_, self.kin.fib_funcs[0]) else: raise NameError("Unknown growth_trig!") # growth function ktheta = grfnc.grfnc1(trigger, threshold, self.gandrparams) # growth residual r_growth = theta_ - theta_old_ - ktheta * (trigger - threshold) * dt # tangent K_growth = diff(r_growth, theta_) # increment del_theta = -r_growth / K_growth if rquant == 'res_del': return r_growth, del_theta elif rquant == 'ktheta': return ktheta elif rquant == 'tang': return K_growth else: raise NameError("Unknown return quantity!")
def grfnc1(self, trigger, thres, params): thetamax, thetamin = params['thetamax'], params['thetamin'] tau_gr, tau_gr_rev = params['tau_gr'], params['tau_gr_rev'] gamma_gr, gamma_gr_rev = params['gamma_gr'], params['gamma_gr_rev'] k_plus = (1./tau_gr) * ((thetamax-self.theta)/(thetamax-thetamin))**(gamma_gr) k_minus = (1./tau_gr_rev) * ((self.theta-thetamin)/(thetamax-thetamin))**(gamma_gr_rev) k = conditional(ge(trigger,thres), k_plus, k_minus) return k
def F(self, v, s, time=None): """ Right hand side for ODE system """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) v, w = s # Assign parameters u_c = self._parameters["u_c"] u_v = self._parameters["u_v"] tau_v1_minus = self._parameters["tau_v1_minus"] tau_v2_minus = self._parameters["tau_v2_minus"] tau_v_plus = self._parameters["tau_v_plus"] tau_w_minus = self._parameters["tau_w_minus"] tau_w_plus = self._parameters["tau_w_plus"] V_0 = self._parameters["V_0"] V_fi = self._parameters["V_fi"] # Init return args F_expressions = [ufl.zero()] * 2 # Expressions for the p component p = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_c), 0, 1) # Expressions for the q component q = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_v), 0, 1) # Expressions for the v gate component tau_v_minus = tau_v1_minus * q + tau_v2_minus * (1 - q) F_expressions[0] = (1 - p) * (1 - v) / tau_v_minus - p * v / tau_v_plus # Expressions for the w gate component F_expressions[1] = (1 - p) * (1 - w) / tau_w_minus - p * w / tau_w_plus # Return results return dolfin.as_vector(F_expressions)
def smooth(up_u_adv, up_u, o): # Calculate averaged velocities # Define the indicator function of the turbine support chi = ufl.conditional(ufl.gt(tf, 0), 1, 0) c_diff = Constant(1e6) F1 = chi * (inner(up_u - up_u_adv, o) + c_diff * inner(grad(up_u), grad(o))) * dx invchi = 1 - chi F2 = inner(invchi * up_u, o) * dx F = F1 + F2 return F
def eig(A): """Eigenvalues of 3x3 tensor""" eps = 1.0e-12 q = ufl.tr(A) / 3.0 p1 = 0.5 * (A[0, 1]**2 + A[1, 0]**2 + A[0, 2]**2 + A[2, 0]**2 + A[1, 2]**2 + A[2, 1]**2) p2 = (A[0, 0] - q)**2 + (A[1, 1] - q)**2 + (A[2, 2] - q)**2 + 2 * p1 p = ufl.sqrt(p2 / 6) B = (A - q * ufl.Identity(3)) r = ufl.det(B) / (2 * p**3) r = ufl.Max(ufl.Min(r, 1.0 - eps), -1.0 + eps) phi = ufl.acos(r) / 3.0 eig0 = ufl.conditional(p2 < eps, q, q + 2 * p * ufl.cos(phi)) eig2 = ufl.conditional(p2 < eps, q, q + 2 * p * ufl.cos(phi + (2 * numpy.pi / 3))) eig1 = ufl.conditional(p2 < eps, q, 3 * q - eig0 - eig2) # since trace(A) = eig1 + eig2 + eig3 return eig0, eig1, eig2
def __init__(self, spline, ufl_element): self._ufl_coef = ufl.Coefficient(ufl_element) t = self._ufl_coef knots = spline.knots coef_array = spline.coef_array # assigning left polynomial form = ufl.conditional(lt(t, knots[0]), 1., 0.)\ * Polynomial(coef_array[0])(t) # assigning internal polynomials for knot, knot_, coef in\ zip(knots[:-1], knots[1:], coef_array[1:-1]): form += ufl.conditional(And(ge(t, knot), lt(t, knot_)), 1., 0.)\ * Polynomial(coef)(t) # assigning right polynomial form += ufl.conditional(ge(t, knots[-1]), 1., 0.)\ * Polynomial(coef_array[-1])(t) self._ufl_form = form
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 7) m, h, j, Cai, d, f, x1 = s # Assign parameters E_Na = self._parameters["E_Na"] g_Na = self._parameters["g_Na"] g_Nac = self._parameters["g_Nac"] g_s = self._parameters["g_s"] IstimAmplitude = self._parameters["IstimAmplitude"] IstimPulseDuration = self._parameters["IstimPulseDuration"] IstimStart = self._parameters["IstimStart"] C = self._parameters["C"] # Init return args current = [ufl.zero()]*1 # Expressions for the Sodium current component i_Na = (g_Nac + g_Na*(m*m*m)*h*j)*(-E_Na + V) # Expressions for the Slow inward current component E_s = -82.3 - 13.0287*ufl.ln(0.001*Cai) i_s = g_s*(-E_s + V)*d*f # Expressions for the Time dependent outward current component i_x1 = 0.00197277571153*(-1 +\ 21.7584023962*ufl.exp(0.04*V))*ufl.exp(-0.04*V)*x1 # Expressions for the Time independent outward current component i_K1 = 0.0035*(-4 +\ 119.85640019*ufl.exp(0.04*V))/(8.33113748769*ufl.exp(0.04*V) +\ 69.4078518388*ufl.exp(0.08*V)) + 0.0035*(4.6 + 0.2*V)/(1 -\ 0.398519041085*ufl.exp(-0.04*V)) # Expressions for the Stimulus protocol component Istim = ufl.conditional(ufl.And(ufl.ge(time, IstimStart),\ ufl.le(time, IstimPulseDuration + IstimStart)), IstimAmplitude,\ 0) # Expressions for the Membrane component current[0] = (-i_K1 + Istim - i_Na - i_x1 - i_s)/C # Return results return current[0]
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v # Assign parameters g_leak = self._parameters["g_L"] Cm = self._parameters["Cm"] E_leak = self._parameters["E_L"] stim_type = self._parameters["stim_type"] g_s = self._parameters["g_S"] alpha = self._parameters["alpha"] v_eq = self._parameters["v_eq"] t0 = self._parameters["t_start"] t1 = self._parameters["t_stop"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Membrane component if stim_type == 0: i_stim = g_s * (-v_eq + V) * ufl.conditional( ufl.ge(time, t0), 1, 0) * ufl.exp((t0 - time) / alpha) elif stim_type == 1: i_stim = -g_s * ufl.conditional(ufl.ge(time, t0), 1, 0) elif stim_type == 2: i_stim = -g_s * ufl.conditional( ufl.And(ufl.ge(time, t0), ufl.le(time, t1)), 1, 0) i_leak = g_leak * (-E_leak + V) current[0] = (-i_leak - i_stim) / Cm # Return results return current[0]
def smooth(u, up_u, o): # Calculate averaged velocities # Define the indicator function of the turbine support chi = ufl.conditional(ufl.gt(tf, 0), 1, 0) # Solve the Helmholtz equation in each turbine area to obtain averaged velocity values c_diff = Constant(1e6) F1 = chi * (inner(up_u - norm_approx(u), o) + Constant(distance_to_upstream) / norm_approx(u) * (inner(dot(grad(norm_approx(u)), u), o) + c_diff * inner(grad(up_u), grad(o)))) * dx invchi = 1 - chi F2 = inner(invchi * up_u, o) * dx F = F1 + F2 return F
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) v, w = s # Assign parameters u_c = self._parameters["u_c"] g_fi_max = self._parameters["g_fi_max"] tau_0 = self._parameters["tau_0"] tau_r = self._parameters["tau_r"] k = self._parameters["k"] tau_si = self._parameters["tau_si"] u_csi = self._parameters["u_csi"] Cm = self._parameters["Cm"] V_0 = self._parameters["V_0"] V_fi = self._parameters["V_fi"] # Init return args current = [ufl.zero()] * 1 # Expressions for the p component p = ufl.conditional(ufl.lt((-V_0 + V) / (V_fi - V_0), u_c), 0, 1) # Expressions for the Fast inward current component tau_d = Cm / g_fi_max J_fi = -(1 - (-V_0 + V)/(V_fi - V_0))*(-u_c + (-V_0 + V)/(V_fi -\ V_0))*p*v/tau_d # Expressions for the Slow outward current component J_so = p / tau_r + (1 - p) * (-V_0 + V) / (tau_0 * (V_fi - V_0)) # Expressions for the Slow inward current component J_si = -(1 + ufl.tanh(k*(-u_csi + (-V_0 + V)/(V_fi -\ V_0))))*w/(2*tau_si) # Expressions for the Stimulus protocol component J_stim = 0 # Expressions for the Membrane component current[0] = (V_0 - V_fi) * (J_stim + J_fi + J_si + J_so) # Return results return current[0]
def velocity( theta_k, theta_kp1, dt, liquidus, solidus, velocity_max=0., filter_solidification=True, mean=False, filter_negative=True, inverse_sign=True, x=None, ): '''Provides the UFL form of the velocity function. Parameters: theta_k: dolfin.Function(V) Function representing the state from the current time slice. theta_kp1: dolfin.Function(V) Function representing the state from the next time slice. velocity_max: float The maximal allowed velocity which will not be penalized. implicitness: float The weight of theta_kp1 in the expression. Normally, should stay default. implicitness: float Returns: form: UFL form The UFL form of theta_k and theta_kp1. ''' velocity_ = velocity_expression(theta_k, theta_kp1, dt) \ + dolfin.Constant(velocity_max) if filter_solidification: ind = solidification_indicator(theta_k, theta_kp1, solidus, liquidus) velocity_ *= ind if mean: area = dolfin.assemble(integral(ind, x)) if area > 0: velocity_ /= area if filter_negative: velocity_ *= conditional(le(velocity_, 0.), 1., 0.) if inverse_sign: velocity_ *= -1 return velocity_
def test_latex_formatting_of_variables(): x, y = ufl.SpatialCoordinate(ufl.triangle) # Test user-provided C variables for subexpressions # we can use variables for x[0], and sum, and power assert expr2latex(x**2 + y**2, variables={x**2: 'x2', y**2: 'y2'}) == "x2 + y2" assert expr2latex(x**2 + y**2, variables={x: 'z', y**2: 'y2'}) == r"{z}^{2} + y2" assert expr2latex(x**2 + y**2, variables={x**2 + y**2: 'q'}) == "q" # we can use variables in conditionals if 0: assert expr2latex(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8), variables={ufl.eq(x, 2): 'c1', ufl.ne(y, 4): 'c2'}) == "c1 || c2 ? 7: 8" # we can replace coefficients (formatted by user provided code) V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2latex(f, variables={f: 'f'}) == "f" assert expr2latex(f**3, variables={f: 'f'}) == r"{f}^{3}" # variables do not replace derivatives of variable expressions assert expr2latex(f.dx(0), variables={f: 'f'}) == r"\overset{0}{w}_{, 0}" # variables do replace variable expressions that are themselves derivatives assert expr2latex(f.dx(0), variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df" assert expr2latex(ufl.grad(f)[0], variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df"
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert (len(s) == 2) s, m = s # Assign parameters Cm = self._parameters["Cm"] E_L = self._parameters["E_L"] g_L = self._parameters["g_L"] # synapse components alpha = self._parameters["alpha"] g_S = self._parameters["g_S"] t0 = self._parameters["t0"] v_eq = self._parameters["v_eq"] # Init return args current = [ufl.zero()] * 1 # Expressions for the Membrane component # FIXME: base on stim_type + add to Hodgkin # if # i_Stim = g_S*(-v_eq + V)*ufl.conditional(ufl.ge(time, t0), 1, 0)*ufl.exp((t0 - time)/alpha) # elif sss: # i_Stim = g_S*ufl.conditional(ufl.ge(time, t0), 1, 0) # else: # i_Stim = g_S*ufl.conditional(ufl.And(ufl.ge(time, t0), # ufl.le(time, t1), 1, 0)) i_Stim = g_S * (-v_eq + V) * ufl.conditional(ufl.ge( time, t0), 1, 0) * ufl.exp((t0 - time) / alpha) i_L = g_L * (-E_L + V) current[0] = (-i_L - i_Stim) / Cm # Return results return current[0]
def beta_cr(dt): """Beta creep coefficients Parameters ---------- dt: Timestep size [day] Returns ------- NumPy array of beta creep coefficients [-] Note ---- The Book, page 160, formula (5.36) """ beta = [] for ta in tau: beta.append(ufl.conditional(dt / ta > 30.0, 0.0, ufl.exp(-dt / ta))) return beta
def test_cpp_formatting_with_variables(): x, y = ufl.SpatialCoordinate(ufl.triangle) # Test user-provided C variables for subexpressions # we can use variables for x[0], and sum, and power assert expr2cpp(x**2 + y**2, variables={x**2: 'x2', y**2: 'y2'}) == "x2 + y2" assert expr2cpp(x**2 + y**2, variables={x: 'z', y**2: 'y2'}) == "pow(z, 2) + y2" assert expr2cpp(x**2 + y**2, variables={x**2 + y**2: 'q'}) == "q" # we can use variables in conditionals assert expr2cpp(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8), variables={ufl.eq(x, 2): 'c1', ufl.ne(y, 4): 'c2'}) == "c1 || c2 ? 7: 8" # we can replace coefficients (formatted by user provided code) V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2cpp(f, variables={f: 'f'}) == "f" assert expr2cpp(f**3, variables={f: 'f'}) == "pow(f, 3)" # variables do not replace derivatives of variable expressions assert expr2cpp(f.dx(0), variables={f: 'f'}) == "d1_w0[0]" # This test depends on which differentiation algorithm is in use # in UFL, representing derivatives as SpatialDerivative or Grad: # variables do replace variable expressions that are themselves derivatives assert expr2cpp(f.dx(0), variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df" assert expr2cpp(ufl.grad(f)[0], variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df"
def _I(self, v, s, time): """ Original gotran transmembrane current dV/dt """ time = time if time else Constant(0.0) # Assign states V = v assert(len(s) == 2) m, h = s # Assign parameters amp = self._parameters["amp"] duration = self._parameters["duration"] stimStart = self._parameters["stimStart"] E_Na = self._parameters["E_Na"] g_Na = self._parameters["g_Na"] E_K = self._parameters["E_K"] g_K = self._parameters["g_K"] k_r = self._parameters["k_r"] # Init return args current = [ufl.zero()]*1 # Expressions for the Fast sodium current component i_Na = g_Na*ufl.elem_pow(m, 3.0)*(-E_Na + V)*h # Expressions for the Potassium current component i_K = g_K*(-E_K + V)*ufl.exp((E_K - V)/k_r) # Expressions for the Membrane component i_stim = ufl.conditional(ufl.And(ufl.gt(time, stimStart),\ ufl.le(time, duration + stimStart)), amp, 0) current[0] = -i_K - i_Na - i_stim # Return results return current[0]
def SubDomainData(geometric_expr): """Creates a subdomain data object from a boolean-valued UFL expression. The result can be attached as the subdomain_data field of a :class:`ufl.Measure`. For example: x = mesh.coordinates sd = SubDomainData(x[0] < 0.5) assemble(f*dx(subdomain_data=sd)) """ import firedrake.functionspace as functionspace import firedrake.projection as projection # Find domain from expression m = geometric_expr.ufl_domain() # Find selected cells fs = functionspace.FunctionSpace(m, 'DG', 0) f = projection.project(ufl.conditional(geometric_expr, 1, 0), fs) # Create cell subset indices, = np.nonzero(f.dat.data_ro_with_halos > 0.5) return op2.Subset(m.cell_set, indices)
def __define_boundary_terms(self): if self.verb > 2: print0("Defining boundary terms") self.bnd_vector_form = numpy.empty(self.DD.G, dtype=object) self.bnd_matrix_form = numpy.empty(self.DD.G, dtype=object) n = FacetNormal(self.DD.mesh) i,p,q = ufl.indices(3) natural_boundaries = self.BC.vacuum_boundaries.union(self.BC.incoming_fluxes.keys()) nonzero = lambda x: numpy.all(x > 0) nonzero_inc_flux = any(map(nonzero, self.BC.incoming_fluxes.values())) if nonzero_inc_flux and not self.fixed_source_problem: coupled_solver_error(__file__, "define boundary terms", "Incoming flux specified for an eigenvalue problem"+\ "(Q must be given whenever phi_inc is; it may possibly be zero everywhere)") for g in range(self.DD.G): self.bnd_vector_form[g] = ufl.zero() self.bnd_matrix_form[g] = ufl.zero() if natural_boundaries: try: ds = Measure("ds")[self.DD.boundaries] except TypeError: coupled_solver_error(__file__, "define boundary terms", "File assigning boundary indices to facets required if vacuum or incoming flux boundaries " "are specified.") for bnd_idx in natural_boundaries: # NOTE: The following doesn't work because ufl.abs requires a function # #for g in range(self.DD.G): # self.bnd_matrix_form[g] += \ # abs(self.tensors.G[p,q,i]*n[i])*self.u[g][q]*self.v[g][p]*ds(bnd_idx) # # NOTE: Instead, the following explicit loop has to be used; this makes tensors.G unneccessary # for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for g in range(self.DD.G): self.bnd_matrix_form[g] += \ abs(omega_p_dot_n)*self.tensors.Wp[pp]*self.u[g][pp]*self.v[g][pp]*ds(bnd_idx) if nonzero_inc_flux: for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for bnd_idx, psi_inc in self.BC.incoming_fluxes.iteritems(): if psi_inc.shape != (self.DD.M, self.DD.G): coupled_solver_error(__file__, "define boundary terms", "Incoming flux with incorrect number of groups and directions specified: "+ "{}, expected ({}, {})".format(psi_inc.shape, self.DD.M, self.DD.G)) for g in range(self.DD.G): self.bnd_vector_form[g] += \ ufl.conditional(omega_p_dot_n < 0, omega_p_dot_n*self.tensors.Wp[pp]*psi_inc[pp,g]*self.v[g][pp]*ds(bnd_idx), ufl.zero()) # FIXME: This assumes zero adjoint outgoing flux else: # Apply vacuum b.c. everywhere ds = Measure("ds") for pp in range(self.DD.M): omega_p_dot_n = self.DD.ordinates_matrix[i,pp]*n[i] for g in range(self.DD.G): self.bnd_matrix_form[g] += abs(omega_p_dot_n)*self.tensors.Wp[pp]*self.u[g][pp]*self.v[g][pp]*ds()
def xtest_latex_formatting_of_conditionals(): # Test conditional expressions assert expr2latex(ufl.conditional(ufl.lt(x, 2), y, 3)) == "x_0 < 2 ? x_1: 3" assert expr2latex(ufl.conditional(ufl.gt(x, 2), 4 + y, 3)) == "x_0 > 2 ? 4 + x_1: 3" assert expr2latex(ufl.conditional(ufl.And(ufl.le(x, 2), ufl.ge(y, 4)), 7, 8)) == "x_0 <= 2 && x_1 >= 4 ? 7: 8" assert expr2latex(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8)) == "x_0 == 2 || x_1 != 4 ? 7: 8"
tf = project(Expression("sin(2*pi*x[0])"), V) def norm_approx(u, alpha=1e-4): # A smooth approximation to ||u|| return sqrt(inner(u, u)+alpha**2) # Advect shift = 0.1 theta = 0.5 uhalf = Constant(1.-theta)*u0 + Constant(theta)*u F = (inner(u-u0, q) + Constant(shift)*inner(uhalf.dx(0)*1, q) + Constant(1e-8)*inner(grad(u), grad(q)))*dx solve(F == 0, u) plot(u, interactive=True, title="Computed after shifting") u_shift = project(Expression("1+sin(2*pi*(x[0]-shift))", shift=shift), V) plot(u_shift, interactive=True, title="Expected after shifting") # Diffuse a = Function(V) chi = ufl.conditional(ufl.ge(tf, 0.0), 0, 1) F1 = chi*(inner(a-u0, q) + Constant(1e3)*inner(grad(a), grad(q)))*dx invchi = 1-chi F2 = inner(invchi*a, q)*dx F = F1 + F2 solve(F == 0, a) adg = interpolate(a, Vdg) f = File("averaged.pvd") f << adg plot(adg, interactive=True, title="Averaged")