def I(self, V, s, time=None): """dv/dt = -I.""" Cm = self._parameters["Cm"] GNa = self._parameters["GNa"] GNaL = self._parameters["GNaL"] GK = self._parameters["GK"] GKL = self._parameters["GKL"] GAHP = self._parameters["GAHP"] control = self._parameters["control"] GClL = self._parameters["GClL"] # Define some parameters beta0 = 7 Cli = 6 Clo = 130 Nao = 144 - beta0*(s[5] - 18) ENa = 26.64*df.ln(Nao/s[5]) Ki = 140 + (18 - s[5]) EK = 26.64*df.ln(control*s[4]/Ki) ECl = 26.64*df.ln(Cli/Clo) INa = GNa*s[0]**3*s[2]*(V - ENa) + GNaL*(V - ENa) IK = (GK*s[1]**4 + GAHP*s[3]/(1 + s[3]) + GKL)*(V - EK) ICl = GClL*(V - ECl) return (INa + IK + ICl)/Cm # Check the sign
def G_RK(self, v): # From the determined RK coefficients, obtain gMix P = self.P Vol = self.Vol # Convect vol frac to mol frac x = v/Vol[0]/((1-v)/Vol[1]+v/Vol[0]) # x = v return 1/np.sqrt(self.length[0]*self.length[1])*(x*ln(x)+(1.0-x)*ln(1.0-x)+x*(1-x)*sum([P[::-1][i]*(2*x-1)**i for i in range(len(P))]))
def create_hydrostatic_pressure(mesh, cc): x = df.MeshCoordinates(mesh) p_h = -0.25 * (2.0 * x[1] - cc[r"\eps"] * df.ln(df.cosh((1.0 - 2.0 * x[1]) / cc[r"\eps"]))) p_h += 0.25 * (2.0 - cc[r"\eps"] * df.ln(df.cosh(1.0 / cc[r"\eps"]))) p_h = cc[r"g_a"] * ((cc[r"\rho_1"] - cc[r"\rho_2"]) * p_h + cc[r"\rho_2"] * (1.0 - x[1])) return p_h
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) self.a = as_matrix([[-5. / ln(sqrt(pow(x, 2) + pow(y, 2))) + 15, 1.0], [1.0, -1. / ln(sqrt(pow(x, 2) + pow(y, 2))) + 3]]) # Init exact solution self.u_ = pow(sqrt(pow(x, 2) + pow(y, 2)), 7. / 4) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) # Set boundary conditions to exact solution self.g = self.u_
def softplus(y1, y2, alpha=1): # The softplus function is a differentiable approximation # to the ramp function. Its derivative is the logistic function. # Larger alpha makes a sharper transition. return Max(y1, y2) + (1. / alpha) * ln(1 + exp(alpha * (Min(y1, y2) - Max(y1, y2))))
def _init_forms(self): u = self.state v = self.state_test F = dolfin.variable(DeformationGradient(u)) J = Jacobian(F) dx = self.geometry.dx # Add penalty term internal_energy = self.material.strain_energy(F) \ + self.kappa * (J * dolfin.ln(J) - J + 1) self._virtual_work \ = dolfin.derivative(internal_energy * dx, self.state, self.state_test) self._virtual_work += self._external_work(u, v) self._jacobian \ = dolfin.derivative(self._virtual_work, self.state, dolfin.TrialFunction(self.state_space)) self._set_dirichlet_bc()
def append(self, uh): '''Update mesh size and dims of fem space and the error + rate''' error = self.get_error(uh) self.errors.append(error) h = uh.function_space().mesh().hmin() self.hs.append(h) ndofs = uh.function_space().dim() self.Vdims.append(ndofs) if len(self.errors) > 1: try: rate = df.ln(self.errors[-1]/self.errors[-2])/df.ln(self.hs[-1]/self.hs[-2]) except ZeroDivisionError: rate = np.nan else: rate = np.nan self.rates.append(rate)
def initialize_with_field(self, u): super().initialize_with_field(u) d = self.deformation_measures.d F = self.deformation_measures.F J = self.deformation_measures.J I1 = self.deformation_measures.I1 # I2 = self.deformation_measures.I2 # I3 = self.deformation_measures.I3 for m in self.material_parameters: E = m.get('E', None) nu = m.get('nu', None) mu = m.get('mu', None) lm = m.get('lm', None) if mu is None: if E is None or nu is None: raise RuntimeError( 'Material model requires parameter "mu"; ' 'otherwise, require parameters "E" and "nu".') mu = E / (2 * (1 + nu)) if lm is None: if E is None or nu is None: raise RuntimeError( 'Material model requires parameter "lm"; ' 'otherwise, require parameters "E" and "nu".') lm = E * nu / ((1 + nu) * (1 - 2 * nu)) psi = (mu / 2) * (I1 - d - 2 * ln(J)) + (lm / 2) * ln(J)**2 pk1 = diff(psi, F) pk2 = dot(inv(F), pk1) self.psi.append(psi) self.pk1.append(pk1) self.pk2.append(pk2)
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) z = -1. / ln(sqrt(pow(x, 2) + pow(y, 2))) # Init coefficient matrix self.a = as_matrix([[5 * z + 15, 1.], [1., 1 * z + 3]]) self.u_ = pow(pow(x, 2) + pow(y, 2), 7. / 8) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) # Set boundary conditions to exact solution self.g = self.u_
def r_temp_c_tilda_cal(c_tilda, Temp): a_0 = -5.73 a_1 = 1.25e-2 a_2 = 1.38 a_3 = 2.61e-5 a_4 = -4.01e-3 a_5 = 3.26e-1 #con_ln_log10 = 1. #con_ln_log10 = 2.3025850929940456840179914546843642076011 con_ln_log10 = ln(10.) r_condition_1 = a_0 + a_1*Temp + a_2*ln(abs(c_tilda))/con_ln_log10\ + a_3*pow(Temp, 2.0) + a_4*Temp*ln(abs(c_tilda))/con_ln_log10 + a_5*pow(ln(abs(c_tilda))/con_ln_log10, 2.0) b_0 = -6.45 b_1 = 2.09e-2 b_2 = -4.65e-2 b_3 = 3.06e-5 b_4 = 9.25e-3 b_5 = -4.59e-1 r_condition_2 = b_0 + b_1*Temp + b_2*ln(abs(c_tilda))/con_ln_log10\ + b_3*pow(Temp, 2.0) + b_4*Temp*ln(abs(c_tilda))/con_ln_log10 + b_5*pow(ln(abs(c_tilda))/con_ln_log10, 2.0) c_0 = -5.80 c_1 = 1.35e-2 c_2 = 9.97e-1 c_3 = 3.80e-5 c_4 = 1.51e-5 c_5 = -4.87e-4 r_condition_3 = c_0 + c_1*Temp + c_2*ln(abs(c_tilda))/con_ln_log10\ + c_3*pow(Temp, 2.0) + c_4*Temp*ln(abs(c_tilda))/con_ln_log10 + c_5*pow(ln(abs(c_tilda))/con_ln_log10, 2.0) return conditional( ge(c_tilda, 0.01), r_condition_1, conditional(ge(c_tilda, -0.01), r_condition_3, r_condition_2))
def compute(self, inputs, outputs): pde_problem = self.options['pde_problem'] # form = self.options['form'] rho = self.options['rho'] expression = self.options['expression'] self._set_values(inputs) von_Mises_max = df.project( expression, self.density_function_space).vector().get_local().max() self.form = (1 / df.CellVolume(self.mesh) * df.exp(rho * (expression - von_Mises_max))) * df.dx outputs['von_mises_max'] = 1 / rho * df.ln(df.assemble( self.form)) + von_Mises_max
def F(self, V, s, time=None): m, h, n, NKo, NKi, NNao, NNai, NClo, NCli, voli, O = s O = dolfin.conditional(dolfin.ge(O, 0), O, 0) G_K = self._parameters["G_K"] G_Na = self._parameters["G_Na"] G_ClL = self._parameters["G_ClL"] G_Kl = self._parameters["G_KL"] G_NaL = self._parameters["G_NaL"] C = self._parameters["C"] # Ion Concentration related Parameters eps_K = self._parameters["eps_K"] G_glia = self._parameters["G_glia"] eps_O = self._parameters["eps_O"] Ukcc2 = self._parameters["Ukcc2"] Unkcc1 = self._parameters["Unkcc1"] rho_max = self._parameters["rho_max"] # Volume vol = 1.4368e-15 # unit:m^3, when r=7 um,v=1.4368e-15 m^3 # TODO: add to parameters beta0 = self._parameters["beta0"] # Time Constant tau = self._parameters["tau"] KBath = self._parameters["KBath"] OBath = self._parameters["OBath"] gamma = self._gamma(voli) volo = (1 + 1 / beta0) * vol - voli # Extracellular volume beta = voli / volo # Ratio of intracelluar to extracelluar volume # Gating variables alpha_m = 0.32 * (54 + V) / (1 - exp(-(V + 54) / 4)) beta_m = 0.28 * (V + 27) / (exp((V + 27) / 5) - 1) alpha_h = 0.128 * exp(-(V + 50) / 18) beta_h = 4 / (1 + exp(-(V + 27) / 5)) alpha_n = 0.032 * (V + 52) / (1 - exp(-(V + 52) / 5)) beta_n = 0.5 * exp(-(V + 57) / 40) dotm = alpha_m * (1 - m) - beta_m * m doth = alpha_h * (1 - h) - beta_h * h dotn = alpha_n * (1 - n) - beta_n * n Ko, Ki, Nao, Nai, Clo, Cli = self._get_concentrations(V, s) fo = 1 / (1 + exp((2.5 - OBath) / 0.2)) fv = 1 / (1 + exp((beta - 20) / 2)) eps_K *= fo * fv G_glia *= fo rho = rho_max / (1 + exp((20 - O) / 3)) / gamma I_glia = G_glia / (1 + exp((18 - Ko) / 2.5)) Igliapump = rho / 3 / (1 + exp((25 - 18) / 3)) / (1 + exp(3.5 - Ko)) I_diff = eps_K * (Ko - KBath) + I_glia + 2 * Igliapump * gamma I_K = self._I_K(V, n, Ko, Ki) I_Na = self._I_Na(V, m, h, Nao, Nai) I_Cl = self._I_Cl(V, Clo, Cli) I_pump = self._I_pump(Nai, Ko, O, gamma) # Cloride transporter (mM/s) fKo = 1 / (1 + exp(16 - Ko)) FKCC2 = Ukcc2 * ln((Ki * Cli) / (Ko * Clo)) FNKCC1 = Unkcc1 * fKo * (ln((Ki * Cli) / (Ko * Clo)) + ln( (Nai * Cli) / (Nao * Clo))) dotNKo = tau * volo * (gamma * beta * (I_K - 2.0 * I_pump) - I_diff + FKCC2 * beta + FNKCC1 * beta) dotNKi = -tau * voli * (gamma * (I_K - 2.0 * I_pump) + FKCC2 + FNKCC1) dotNNao = tau * volo * beta * (gamma * (I_Na + 3.0 * I_pump) + FNKCC1) dotNNai = -tau * voli * (gamma * (I_Na + 3.0 * I_pump) + FNKCC1) dotNClo = beta * volo * tau * (FKCC2 - gamma * I_Cl + 2 * FNKCC1) dotNCli = voli * tau * (gamma * I_Cl - FKCC2 - 2 * FNKCC1) r1 = vol / voli r2 = 1 / beta0 * vol / ((1 + 1 / beta0) * vol - voli) pii = Nai + Cli + Ki + 132 * r1 pio = Nao + Ko + Clo + 18 * r2 vol_hat = vol * (1.1029 - 0.1029 * exp((pio - pii) / 20)) dotVoli = -(voli - vol_hat) / 0.25 * tau dotO = tau * (-5.3 * (I_pump + Igliapump) * gamma + eps_O * (OBath - O)) F_expressions = [ufl.zero()] * self.num_states() F_expressions[0] = dotm F_expressions[1] = doth F_expressions[2] = dotn F_expressions[3] = dotNKo F_expressions[4] = dotNKi F_expressions[5] = dotNNao F_expressions[6] = dotNNai F_expressions[7] = dotNClo F_expressions[8] = dotNCli F_expressions[9] = dotVoli F_expressions[10] = dotO return dolfin.as_vector(F_expressions)
def mu_newton_linear_adapt(c, mu_light, mu_heavy, c_light, c_heavy): mu_light = ln(mu_light) mu_heavy = ln(mu_heavy) mu = mu_light + (c - c_light) / (c_heavy - c_light) * (mu_heavy - mu_light) return exp(mu)
def F(self, V, s, time=None): """ds/dt = F(v, s).""" GCa = self._parameters["GCa"] gamma1 = self._parameters["gamma1"] Gglia = self._parameters["Gglia"] tau = self._parameters["tau"] control = self._parameters["control"] GNa = self._parameters["GNa"] GNaL = self._parameters["GNaL"] GK = self._parameters["GK"] GKL = self._parameters["GKL"] GAHP = self._parameters["GAHP"] Koinf = self._parameters["Koinf"] # Define some parameters ECa = 120 phi = 3 rho = 1.25 eps0 = 1.2 beta0 = 7 Cli = 6 Clo = 130 Nao = 144 - beta0*(s[5] - 18) ENa = 26.64*df.ln(Nao/s[5]) Ki = 140 + (18 - s[5]) EK = 26.64*df.ln(control*s[4]/Ki) INa = GNa*s[0]**3*s[2]*(V - ENa) + GNaL*(V - ENa) IK = (GK*s[1]**4 + GAHP*s[3]/(1 + s[3]) + GKL)*(V - EK) a_m = (3.0 + (0.1)*V)*(1 - df.exp(-3 -1/10*V))**(-1) b_m = 4*df.exp(-55/18 - 1/18*V) ah = (0.07)*df.exp(-11/5 - 1/20*V) bh = (1 + df.exp(-7/5 - 1/10*V))**(-1) an = (0.34 + (0.01)*V)*(1 - df.exp(-17/5 - 1/10*V))**(-1) bn = (0.125)*df.exp(-11/20 - 1/80*V) taum = (a_m + b_m)**(-1) minf = a_m*(a_m + b_m)**(-1) h_inf = (bh + ah)**(-1)*ah tauh = (bh + ah)**(-1) ninf = (an + bn)**(-1)*an taun = (an + bn)**(-1) dot_m = phi*(minf - s[0])*taum**(-1) dot_h = phi*(ninf - s[1])/taun dot_n = phi*(h_inf - s[2])/tauh Ipump = rho*(1/(1 + df.exp((25 - s[5])/3)))*(1/(1 + df.exp(5.5 - s[4]))) IGlia = Gglia/(1 + df.exp((18 - s[4])/2.5)) Idiff = eps0*(s[4] - Koinf) dot_Ca = -s[3]/80 - 0.002*GCa*(V - ECa)/(1 + df.exp(-(V + 25)/2.5)) dot_K = (gamma1*beta0*IK - 2*beta0*Ipump - IGlia - Idiff)/tau # dot_Na = (gamma1*INa + 3*Ipump)/tau dot_Na = -(gamma1*INa + 3*Ipump)/tau # Pretty sure it should me minus F_expressions = [ufl.zero()]*self.num_states() F_expressions[0] = dot_m F_expressions[1] = dot_h F_expressions[2] = dot_n F_expressions[3] = dot_Ca F_expressions[4] = dot_K F_expressions[5] = dot_Na return df.as_vector(F_expressions)
def get_residual_form(u, v, rho_e, V_density, tractionBC, T, iteration_number, additive='strain', k=8., method='RAMP'): df.dx = df.dx(metadata={"quadrature_degree": 4}) # stiffness = rho_e/(1 + 8. * (1. - rho_e)) if method == 'SIMP': stiffness = rho_e**3 else: stiffness = rho_e / (1 + 8. * (1. - rho_e)) # print('the value of stiffness is:', rho_e.vector().get_local()) # Kinematics d = len(u) I = df.Identity(d) # Identity tensor F = I + df.grad(u) # Deformation gradient C = F.T * F # Right Cauchy-Green tensor # Invariants of deformation tensors Ic = df.tr(C) J = df.det(F) stiffen_pow = 1. threshold_vol = 1. eps_star = 0.05 # print("eps_star--------") if additive == 'strain': print("additive == strain") if iteration_number == 1: print('iteration_number == 1') eps = df.sym(df.grad(u)) eps_dev = eps - 1 / 3 * df.tr(eps) * df.Identity(2) eps_eq = df.sqrt(2.0 / 3.0 * df.inner(eps_dev, eps_dev)) # eps_eq_proj = df.project(eps_eq, density_function_space) ratio = eps_eq / eps_star ratio_proj = df.project(ratio, V_density) c1_e = k * (5.e-2) / (1 + 8. * (1. - (5.e-2))) / 6 c2_e = df.Function(V_density) c2_e.vector().set_local(5e-4 * np.ones(V_density.dim())) fFile = df.HDF5File(df.MPI.comm_world, "c2_e_proj.h5", "w") fFile.write(c2_e, "/f") fFile.close() fFile = df.HDF5File(df.MPI.comm_world, "ratio_proj.h5", "w") fFile.write(ratio_proj, "/f") fFile.close() iteration_number += 1 E = k * stiffness phi_add = (1 - stiffness) * ((c1_e * (Ic - 3)) + (c2_e * (Ic - 3))**2) else: ratio_proj = df.Function(V_density) fFile = df.HDF5File(df.MPI.comm_world, "ratio_proj.h5", "r") fFile.read(ratio_proj, "/f") fFile.close() c2_e = df.Function(V_density) fFile = df.HDF5File(df.MPI.comm_world, "c2_e_proj.h5", "r") fFile.read(c2_e, "/f") fFile.close() c1_e = k * (5.e-2) / (1 + 8. * (1. - (5.e-2))) / 6 c2_e = df.conditional(df.le(ratio_proj, eps_star), c2_e * df.sqrt(ratio_proj), c2_e * (ratio_proj**3)) phi_add = (1 - stiffness) * ((c1_e * (Ic - 3)) + (c2_e * (Ic - 3))**2) E = k * stiffness c2_e_proj = df.project(c2_e, V_density) print('c2_e projected -------------') eps = df.sym(df.grad(u)) eps_dev = eps - 1 / 3 * df.tr(eps) * df.Identity(2) eps_eq = df.sqrt(2.0 / 3.0 * df.inner(eps_dev, eps_dev)) # eps_eq_proj = df.project(eps_eq, V_density) ratio = eps_eq / eps_star ratio_proj = df.project(ratio, V_density) fFile = df.HDF5File(df.MPI.comm_world, "c2_e_proj.h5", "w") fFile.write(c2_e_proj, "/f") fFile.close() fFile = df.HDF5File(df.MPI.comm_world, "ratio_proj.h5", "w") fFile.write(ratio_proj, "/f") fFile.close() elif additive == 'vol': print("additive == vol") stiffness = stiffness / (df.det(F)**stiffen_pow) # stiffness = df.conditional(df.le(df.det(F),threshold_vol), (stiffness/(df.det(F)/threshold_vol))**stiffen_pow, stiffness) E = k * stiffness elif additive == 'False': print("additive == False") E = k * stiffness # rho_e is the design variable, its values is from 0 to 1 nu = 0.4 # Poisson's ratio lambda_ = E * nu / (1. + nu) / (1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters # Stored strain energy density (compressible neo-Hookean model) psi = (mu / 2) * (Ic - 3) - mu * df.ln(J) + (lambda_ / 2) * (df.ln(J))**2 # print('the length of psi is:',len(psi.vector())) if additive == 'strain': psi += phi_add B = df.Constant((0.0, 0.0)) # Total potential energy '''The first term in this equation provided this error''' Pi = psi * df.dx - df.dot(B, u) * df.dx - df.dot(T, u) * tractionBC res = df.derivative(Pi, u, v) return res
def Softplus(a, b, alpha=1): return Max(a, b) + 1. / alpha * df.ln(1 + df.exp(-abs(a - b) * alpha))
d = len(u) # Displacement dimension I = dolfin.Identity(d) F = dolfin.variable(I + dolfin.grad(u)) C = F.T * F J = dolfin.det(F) I1 = dolfin.tr(C) # Lame material parameters lm = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) mu = E / (2.0 + 2.0 * nu) # Energy density of a Neo-Hookean material model psi = (mu / 2.0) * (I1 - d - 2.0 * dolfin.ln(J)) + (lm / 2.0) * dolfin.ln(J)**2 # First Piola-Kirchhoff pk1 = dolfin.diff(psi, F) # Boundary traction N = dolfin.FacetNormal(mesh) PN = dolfin.dot(pk1, N) # Potential energy Pi = psi * dx # NOTE: There is no external force potential # Equilibrium problem F = dolfin.derivative(Pi, u) ### Model cost and constraints
def A_s_cal(phi, phi0, A_0): return A_0 * phi / phi0 * ln(phi) / ln(phi0)
def _I_Cl(self, V, Clo, Cli): G_ClL = self._parameters["G_ClL"] E_Cl = 26.64 * ln(Cli / Clo) return G_ClL * (V - E_Cl)
def setup_EC(w_EC, c, V, V0, b, U, U0, rho_e, grad_g_c, c_reg, g_c, dx, ds, normal, dirichlet_bcs_EC, neumann_bcs, boundary_to_mark, c_1, u_1, K, veps, rho_, rho_1, dt, enable_NS, solutes, use_iterative_solvers, nonlinear_EC, V_lagrange, p_lagrange, q_rhs, reactions, beta, **namespace): """ Set up electrochemistry subproblem. """ if enable_NS: # Projected velocity u_star = u_1 - dt/rho_1*sum([ci_1*grad_g_ci for ci_1, grad_g_ci in zip(c_1, grad_g_c)]) F_c = [] for ci, ci_1, bi, Ki, grad_g_ci, solute, ci_reg in zip( c, c_1, b, K, grad_g_c, solutes, c_reg): F_ci = (1./dt*(ci-ci_1)*bi*dx + Ki*ci_reg*df.dot(grad_g_ci, df.grad(bi))*dx) if enable_NS: F_ci += - ci_1*df.dot(u_star, df.grad(bi))*dx if solute[0] in q_rhs: F_ci += - q_rhs[solute[0]]*bi*dx if enable_NS: for boundary_name, value in neumann_bcs[solute[0]].iteritems(): # F_ci += df.dot(u_1, normal)*bi*ci_1*ds( # boundary_to_mark[boundary_name]) pass F_c.append(F_ci) for reaction_constant, nu in reactions: g_less = [] g_more = [] for nui, ci_1, betai in zip(nu, c_1, beta): if nui < 0: g_less.append(-nui*(df.ln(ci_1)+betai)) elif nui > 0: g_more.append(nui*(df.ln(ci_1)+betai)) g_less = sum(g_less) g_more = sum(g_more) C = reaction_constant*( df.exp(g_less) - df.exp(g_more))/(g_less - g_more) R = C*sum([nui*g_ci for nui, g_ci in zip(nu, g_c)]) for nui, bi in zip(nu, b): if nui != 0: F_c.append(nui*R*bi*dx) F_V = veps*df.dot(df.grad(V), df.grad(U))*dx for boundary_name, sigma_e in neumann_bcs["V"].iteritems(): F_V += -sigma_e*U*ds(boundary_to_mark[boundary_name]) if rho_e != 0: F_V += -rho_e*U*dx if V_lagrange: F_V += veps*V0*U*dx + veps*V*U0*dx if "V" in q_rhs: F_V += q_rhs["V"]*U*dx F = sum(F_c) + F_V if nonlinear_EC: J = df.derivative(F, w_EC) problem = df.NonlinearVariationalProblem(F, w_EC, dirichlet_bcs_EC, J) solver = df.NonlinearVariationalSolver(problem) solver.parameters["newton_solver"]["relative_tolerance"] = 1e-7 if use_iterative_solvers: solver.parameters["newton_solver"]["linear_solver"] = "bicgstab" if not V_lagrange: solver.parameters["newton_solver"]["preconditioner"] = "hypre_amg" else: a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_EC, dirichlet_bcs_EC) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "bicgstab" solver.parameters["preconditioner"] = "hypre_amg" return solver
def alpha(c): return c*(df.ln(c)-1)
def P(u): # P = dW/dF: return mu*(F - inv(F.T)) + lmbda*ln(J)*inv(F.T)
def __init__(self, mesh): self.mesh = mesh # Write mesh to file (for debugging only) # write_mesh(self.mesh, '/tmp/meshfromslicer.vtu') # define function space element_degree = 1 quadrature_degree = element_degree + 1 print("Degree of element: ", element_degree) print("Degree of quadrature: ", quadrature_degree) self.V = dolfin.VectorFunctionSpace(self.mesh, "Lagrange", element_degree) # Mark boundary subdomains zmin = min(self.mesh.coordinates()[:, 2]) zmax = max(self.mesh.coordinates()[:, 2]) print("zmin:", zmin) print("zmax:", zmax) bot = dolfin.CompiledSubDomain("near(x[2], side) && on_boundary", side=zmin) top = dolfin.CompiledSubDomain("near(x[2], side) && on_boundary", side=zmax) # Define Dirichlet boundary (z = 0 or z = 1) c = dolfin.Constant((0.0, 0.0, 0.0)) self.r = dolfin.Expression(( "scale*(x0 + (x[0] - x0)*cos(theta) - (x[1] - y0)*sin(theta) - x[0])", "scale*(y0 + (x[0] - x0)*sin(theta) + (x[1] - y0)*cos(theta) - x[1])", "displacement"), scale=1.0, x0=0.5, y0=0.5, theta=0.0, displacement=0.0, degree=2) self.bcs = [ dolfin.DirichletBC(self.V, c, bot), dolfin.DirichletBC(self.V, self.r, top) ] # Define functions du = dolfin.TrialFunction(self.V) # Incremental displacement v = dolfin.TestFunction(self.V) # Test function # Displacement from previous iteration self.u = dolfin.Function(self.V) # Body force per unit volume self.B = dolfin.Constant((0.0, 0.0, 0.0)) # Traction force on the boundary self.T = dolfin.Constant((0.0, 0.0, 0.0)) # Kinematics d = len(self.u) I = dolfin.Identity(d) # Identity tensor F = I + dolfin.grad(self.u) # Deformation gradient C = F.T * F # Right Cauchy-Green tensor # Invariants of deformation tensors Ic = dolfin.tr(C) J = dolfin.det(F) # Elasticity parameters E = 10.0 nu = 0.3 mu = dolfin.Constant(E / (2 * (1 + nu))) lmbda = dolfin.Constant(E * nu / ((1 + nu) * (1 - 2 * nu))) # Stored strain energy density (compressible neo-Hookean model) psi = (mu / 2) * (Ic - 3) - mu * dolfin.ln(J) + (lmbda / 2) * (dolfin.ln(J))**2 dx = dolfin.Measure("dx", domain=mesh, metadata={'quadrature_degree': quadrature_degree}) ds = dolfin.Measure("ds", domain=mesh, metadata={'quadrature_degree': quadrature_degree}) print(dx) print(ds) Pi = psi*dx - dolfin.dot(self.B, self.u)*dx - \ dolfin.dot(self.T, self.u)*ds self.F = dolfin.derivative(Pi, self.u, v) self.J = dolfin.derivative(self.F, self.u, du)
def softplus(y1, y2, alpha=1): # The softplus function is a differentiable approximation # to the ramp function. Its derivative is the logistic function. # Larger alpha makes a sharper transition. return y1 + (1. / alpha) * df.ln(1 + df.exp(alpha * (y2 - y1)))
def alpha_c(c): return df.ln(c)
def _I_K(self, V, n, Ko, Ki): G_K = self._parameters["G_K"] G_KL = self._parameters["G_KL"] E_K = 26.64 * ln(Ko / Ki) return G_K * n**4 * (V - E_K) + G_KL * (V - E_K)
def _I_Na(self, V, m, h, Nao, Nai): G_Na = self._parameters["G_Na"] G_NaL = self._parameters["G_NaL"] E_Na = 26.64 * ln(Nao / Nai) return G_Na * m**3 * h * (V - E_Na) + G_NaL * (V - E_Na)
# Lame material parameters lm = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) mu = E / (2.0 + 2.0 * nu) if large_deformations: I = dolfin.Identity(len(u)) F = dolfin.variable(I + dolfin.grad(u)) # Deformation gradient C = F.T * F # Right Cauchy-Green deformation tensor I1 = dolfin.tr(C) det_F = dolfin.det(F) # Strain energy density of a Neo-Hookean material psi = (mu / 2.0) * (I1 - len(u) - 2.0 * dolfin.ln(det_F)) + ( lm / 2.0) * dolfin.ln(det_F)**2 # First Piola-Kirchhoff stress tensor pk1 = dolfin.diff(psi, F) else: I = dolfin.Identity(len(u)) e = sym(grad(u)) # Cauchy stress tensor s = 2 * mu * e + lm * dolfin.tr(e) * I # Strain energy density of a linear-elastic material psi = 0.5 * inner(s, e)