def calculate_darcy_flow(self): # equation 5a du = self.mech_velocity p = self.pressure rho = Constant(self.parameters['rho']) phi = [Constant(phi) for phi in self.parameters['phi']] F = df.variable(kinematics.DeformationGradient(self.displacement)) J = kinematics.Jacobian(F) dx = self.geometry.dx N = self.parameters['N'] # Calculate endo to epi permeability gradient w = [TrialFunction(self.vector_space) for i in range(N)] v = [TestFunction(self.vector_space) for i in range(N)] a = [(1 / phi[i]) * df.inner(F * J * df.inv(F) * w[i], v[i]) * dx for i in range(N)] # a = [phi[i]*df.inner((w[i]-du), v[i])*dx for i in range(N)] # porous dynamics if self.parameters['mechanics']: A = [-J * self.K[i] * df.inv(F.T) for i in range(N)] else: A = [self.K[i] for i in range(N)] L = [-df.dot(A[i] * df.grad(p[i]), v[i]) * dx for i in range(N)] [ df.solve(a[i] == L[i], self.darcy_flow[i], [], solver_parameters={ "linear_solver": "cg", "preconditioner": "sor" }) for i in range(N) ]
def Coupled_setup(d_, v_, p_, psi_v, psi_p, psi_d, dS2, n, mu_f, body_force, dx_s, dx_f, mu_s, rho_s, lamda_s, k, mesh_file, rho_f, **semimp_namespace): F_coupled_linear = rho_s / k**2 * inner( d_["n"] - 2 * d_["n-1"] + d_["n-2"], psi_d) * dx_s F_coupled_linear -= rho_s * inner(body_force, psi_d) * dx_s F_coupled_linear = rho_f / k * J_(d_["tilde"]) * inner( v_["n"] - v_["tilde"], psi_v) * dx_f F_coupled_linear += J_(d_["tilde"]) * inner( inv(F_(d_["tilde"])).T * grad(p_["n"]), psi_v) * dx_f F_coupled_linear += inner( div(J_(d_["tilde"]) * inv(F_(d_["tilde"])) * v_["n"]), psi_p) * dx_f # Non-linear part F_coupled_nonlinear = Constant(0.5) * inner(Piola1(d_["n"], lamda_s, mu_s), grad(psi_d))*dx_s \ + Constant(0.5) * inner(Piola1(d_["n-2"], lamda_s, mu_s), grad(psi_d))*dx_s # Impose BC weakly F_coupled_nonlinear -= inner(J_(d_["tilde"]("+"))*sigma_f(p_["n"]("+"), v_["tilde"]("+"), d_["tilde"]("+"), mu_f) \ * inv(F_(d_["tilde"]("+"))).T*n("+"), psi_d("+"))*dS2(5) # TODO: This might be better strongly... F_coupled_linear += J_(d_["tilde"]("+")) * inner( dot(v_["n"]("+") - -(d_["n"]("-") - d_["n-1"]("-")) / k, n("+")), psi_p("+")) * dS2(5) return dict(F_coupled_linear=F_coupled_linear, F_coupled_nonlinear=F_coupled_nonlinear)
def fluid_setup(v_, p_, d_, n, psi, gamma, dx_f, ds, dS, mu_f, rho_f, k, v_deg, **semimp_namespace): F_fluid_linear = (rho_f / k) * inner( J_(d_["n"]) * (v_["n"] - v_["n-1"]), psi) * dx_f F_fluid_linear -= inner(div(J_(d_["n"]) * inv(F_(d_["n"])) * v_["n"]), gamma) * dx_f F_fluid_linear += inner( J_(d_["n"]) * sigma_f_new(v_["n"], p_["n"], d_["n"], mu_f) * inv(F_(d_["n"])).T, grad(psi)) * dx_f F_fluid_linear -= inner(dot(J_(d_["n"]("-"))*\ sigma_f_new(v_["n"]("-"), p_["n"]("-"), d_["n"]("-"), mu_f)*inv(F_(d_["n"]("-"))).T, n("+")) , psi("-") )*dS(5) F_fluid_nonlinear = rho_f * inner( J_(d_["n"]) * grad(v_["n"]) * inv(F_(d_["n"])) * (v_["n"] - ((d_["n"] - d_["n-1"]) / k)), psi) * dx_f if v_deg == 1: F_fluid -= beta * h * h * inner( J_(d_["n"]) * inv(F_(d_["n"]).T) * grad(p), grad(gamma)) * dx_f print "v_deg", v_deg return dict(F_fluid_linear=F_fluid_linear, F_fluid_nonlinear=F_fluid_nonlinear)
def fluid_setup(v_, p_, d_, n, psi, gamma, dx_f, ds, mu_f, rho_f, k, dt, v_deg, theta, **semimp_namespace): J_theta = theta * J_(d_["n"]) + (1 - theta) * J_(d_["n-1"]) d_cn = Constant(theta) * d_["n"] + Constant(1 - theta) * d_["n-1"] v_cn = Constant(theta) * v_["n"] + Constant(1 - theta) * v_["n-1"] p_cn = Constant(theta) * p_["n"] + Constant(1 - theta) * p_["n-1"] F_fluid_linear = rho_f / k * inner(J_theta * (v_["n"] - v_["n-1"]), psi) * dx_f F_fluid_nonlinear = rho_f*inner(J_(d_cn)*grad(v_cn)*inv(F_(d_cn))* \ (0.5*(3*v_["n-1"] - v_["n-2"]) - \ 0.5/k*((3*d_["n-1"] - d_["n-2"]) - (3*d_["n-2"] - d_["n-3"]))), psi)*dx_f #(d_["n"]-d_["n-1"])/k), psi)*dx_f F_fluid_nonlinear += inner( J_(d_cn) * sigma_f_p(p_cn, d_cn) * inv(F_(d_cn)).T, grad(psi)) * dx_f F_fluid_nonlinear += inner( J_(d_cn) * sigma_f_u(v_cn, d_cn, mu_f) * inv(F_(d_cn)).T, grad(psi)) * dx_f #OrgF_fluid_nonlinear +=inner(div(J_(d_["n"])*inv(F_(d_["n"]))*v_["n"]), gamma)*dx_f F_fluid_nonlinear += inner(div(J_(d_cn) * inv(F_(d_cn)) * v_cn), gamma) * dx_f return dict(F_fluid_linear=F_fluid_linear, F_fluid_nonlinear=F_fluid_nonlinear)
def SecondPiolaStress(self, F, p=None, deviatoric=False): import dolfin from pulse import kinematics material = self.material I = kinematics.SecondOrderIdentity(F) f0 = material.f0 f0f0 = dolfin.outer(f0, f0) I1 = dolfin.variable(material.active.I1(F)) I4f = dolfin.variable(material.active.I4(F)) Fe = material.active.Fe(F) Fa = material.active.Fa Ce = Fe.T * Fe # fe = Fe*f0 # fefe = dolfin.outer(fe, fe) # Elastic volume ratio J = dolfin.variable(dolfin.det(Fe)) # Active volume ration Ja = dolfin.det(Fa) dim = self.geometry.dim() Ce_bar = pow(J, -2.0 / float(dim)) * Ce w1 = material.W_1(I1, diff=1, dim=dim) w4f = material.W_4(I4f, diff=1) # Total Stress S_bar = Ja * (2 * w1 * I + 2 * w4f * f0f0) * dolfin.inv(Fa).T if material.is_isochoric: # Deviatoric Dev_S_bar = S_bar - (1.0 / 3.0) * dolfin.inner( S_bar, Ce_bar) * dolfin.inv(Ce_bar) S_mat = J**(-2.0 / 3.0) * Dev_S_bar else: S_mat = S_bar # Volumetric if p is None or deviatoric: S_vol = dolfin.zero((dim, dim)) else: psi_vol = material.compressibility(p, J) S_vol = J * dolfin.diff(psi_vol, J) * dolfin.inv(Ce) # Active stress wactive = material.active.Wactive(F, diff=1) eta = material.active.eta S_active = wactive * (f0f0 + eta * (I - f0f0)) S = S_mat + S_vol + S_active return S
def Fluid_correction_variation(v, p, v_, d_, vp_, dw_, psi, eta, dx_f, \ mu_f, rho_f, k, dt, n, dS, **semimp_namespace): # Pressure update F_correction = rho_f/k*J_(d_["tilde"])*inner(v - v_["tilde"], psi)*dx_f F_correction += J_(d_["tilde"])*inner(inv(F_(d_["tilde"])).T*grad(p), psi)*dx_f #F_correction -= p*J_(d_["tilde"])*inner(inv(F_(d_["tilde"])).T, grad(psi))*dx_f F_correction += inner(div(J_(d_["n"])*inv(F_(d_["n"]))*v), eta)*dx_f return dict(F_correction=F_correction)
def SecondPiolaStress(self, F, p=None, deviatoric=False, *args, **kwargs): # First Piola Kirchoff if deviatoric: p = None P = self.FirstPiolaStress(F, p) S = dolfin.inv(F) * P * dolfin.inv(F).T return S
def permeability_tensor(self, K): FS = self.geometry.f0.function_space() TS = TensorFunctionSpace(self.geometry.mesh, 'P', 1) d = self.geometry.dim() fibers = Function(FS) fibers.vector()[:] = self.geometry.f0.vector().get_local() fibers.vector()[:] /= df.norm(self.geometry.f0) if self.geometry.s0 is not None: # normalize vectors sheet = Function(FS) sheet.vector()[:] = self.geometry.s0.vector().get_local() sheet.vector()[:] /= df.norm(self.geometry.s0) if d == 3: csheet = Function(FS) csheet.vector()[:] = self.geometry.n0.vector().get_local() csheet.vector()[:] /= df.norm(self.geometry.n0) else: return Constant(1) from ufl import diag factor = 10 if d == 3: ftensor = df.as_matrix(((fibers[0], sheet[0], csheet[0]), (fibers[1], sheet[1], csheet[1]), (fibers[2], sheet[2], csheet[2]))) ktensor = diag(df.as_vector([K, K / factor, K / factor])) else: ftensor = df.as_matrix( ((fibers[0], sheet[0]), (fibers[1], sheet[1]))) ktensor = diag(df.as_vector([K, K / factor])) permeability = df.project( df.dot(df.dot(ftensor, ktensor), df.inv(ftensor)), TS) return permeability
def Fluid_correction_variation(v, p, v_, d_, vp_, dw_, psi, eta, dx_f, \ mu_f, rho_f, k, dt, n, dS2, **semimp_namespace): # Pressure update F_correction = rho_f/k*J_(d_["tilde"])*inner(v - v_["tilde"], psi)*dx_f # This gives no pressure gradient thorugh the pipe #F_correction -= J_(d_["tilde"])*inner(p*inv(F_(d_["tilde"])).T, grad(psi))*dx_f F_correction += J_(d_["tilde"])*inner(inv(F_(d_["tilde"])).T*grad(p), psi)*dx_f F_correction += inner(div(J_(d_["tilde"])*inv(F_(d_["tilde"]))*v), eta)*dx_f #F_correction += J_(d_["tilde"]("+"))*inner(dot(v("+") - \ # (d_["n"]("-") - d_["n-1"]("-"))/k, n("+")), eta("+"))*dS2(5) return dict(F_correction=F_correction)
def Fe(self, F): if self.model == ActiveModels.active_stress: return F Fa = self.Fa Fe = F * dolfin.inv(Fa) return Fe
def __call__(self, u=None): if u is None: u = dolfin.Function( self._displacement_space, name="Zero displacement from strain observation", ) u_int = map_displacement( u, self._displacement_space, self._interpolation_space, self._approx ) # We need to correct for th reference deformation F = pulse.kinematics.DeformationGradient(u_int) * dolfin.inv(self._F_ref) # Compute the strains if self._tensor == "gradu": tensor = pulse.kinematics.EngineeringStrain(F, isochoric=self._isochoric) elif self._tensor == "E": tensor = pulse.kinematics.GreenLagrangeStrain(F, isochoric=self._isochoric) elif self._tensor == "almansi": tensor = pulse.kinematics.EulerAlmansiStrain(F, isochoric=self._isochoric) form = dolfin.inner(tensor * self.field, self.field) strain = dolfin_adjoint.Function(self._V, name="Simulated Strain") dolfin_adjoint.solve( dolfin.inner(self._trial, self._test) / self._vol * self._dmu == dolfin.inner(self._test, form) * self._dmu, strain, solver_parameters={"linear_solver": "gmres"}, ) return strain
def __call__(self, u=None): """ Arguments --------- u : :py:class:`dolfin.Function` The displacement """ if u is None: volume_form = (-1.0 / 3.0) * dolfin.dot(self._X, self._N) else: u_int = map_displacement( u, self._displacement_space, self._interpolation_space, self._approx ) # Compute volume F = pulse.kinematics.DeformationGradient(u_int) J = pulse.kinematics.Jacobian(F) volume_form = (-1.0 / 3.0) * dolfin.dot( self._X + u_int, J * dolfin.inv(F).T * self._N ) volume = dolfin_adjoint.Function(self._V, name="Simulated volume") # Make a project for dolfin-adjoint recording dolfin_adjoint.solve( dolfin.inner(self._trial, self._test) / self._endoarea * self._dmu == dolfin.inner(volume_form, self._test) * self._dmu, volume, ) return volume
def Structure_setup(d_, w_, v_, p_, phi, gamma, dS, n, mu_f, \ vp_, dx_s, mu_s, rho_s, lamda_s, k, mesh_file, theta, **semimp_namespace): delta = 1E10 theta = 1.0 F_solid_linear = rho_s/k*inner(w_["n"] - w_["n-1"], phi)*dx_s \ + delta*(1./k)*inner(d_["n"] - d_["n-1"], gamma)*dx_s \ - delta*inner(Constant(theta)*w_["n"] \ + Constant(1 - theta)*w_["n-1"], gamma)*dx_s F_solid_nonlinear = inner(Piola1(Constant(theta)*d_["n"] \ + Constant(1 - theta)*d_["n-1"], lamda_s, mu_s), grad(phi))*dx_s #F_solid_nonlinear -= inner(J_(d_["n"]("+")) * \ #3sigma_f(p_["n"]("+"),v_["tilde"]("+"), d_["n"]("+"), mu_f) \ #*inv(F_(d_["n"]("+"))).T*n("+"), phi("+"))*dS(5) #org F_solid_nonlinear -= inner(J_(d_["tilde"]("+")) * \ sigma_f(p_["n"]("+"),v_["tilde"]("+"), d_["tilde"]("+"), mu_f) \ *inv(F_(d_["tilde"]("+"))).T*n("+"), phi("-"))*dS(5) return dict(F_solid_linear=F_solid_linear, F_solid_nonlinear=F_solid_nonlinear)
def Structure_setup(d_, w_, v_, p_, phi, gamma, dS2, n, mu_f, body_force, \ vp_, dx_s, mu_s, rho_s, lamda_s, k, mesh_file, theta, **semimp_namespace): delta = 1E10 #theta = 1.0 theta = 0.5 F_solid_linear = rho_s/k*inner(w_["n"] - w_["n-1"], phi)*dx_s \ + delta*(1./k)*inner(d_["n"] - d_["n-1"], gamma)*dx_s \ - delta*inner(Constant(theta)*w_["n"] \ + Constant(1 - theta)*w_["n-1"], gamma)*dx_s F_solid_linear -= rho_s * inner(body_force, phi) * dx_s # Non-linear part F_solid_nonlinear = Constant(theta)*inner(Piola1(d_["n"], lamda_s, mu_s), grad(phi))*dx_s \ + Constant(1 - theta)*inner(Piola1(d_["n-1"], lamda_s, mu_s), grad(phi))*dx_s u = vp_["tilde"].sub(0) p = vp_["n"].sub(1) F_solid_nonlinear -= inner(J_(d_["tilde"]("+"))*sigma_f(p("+"), u("+"), d_["tilde"]("+"), mu_f) \ *inv(F_(d_["tilde"]("+"))).T*n("+"), phi("+"))*dS2(5) return dict(F_solid_linear=F_solid_linear, F_solid_nonlinear=F_solid_nonlinear)
def get_volume(geometry, u=None, chamber="lv"): if "ENDO" in geometry.markers: lv_endo_marker = geometry.markers["ENDO"] rv_endo_marker = None else: lv_endo_marker = geometry.markers["ENDO_LV"] rv_endo_marker = geometry.markers["ENDO_RV"] marker = lv_endo_marker if chamber == "lv" else rv_endo_marker if marker is None: return None if hasattr(marker, "__len__"): marker = marker[0] ds = df.Measure( "exterior_facet", subdomain_data=geometry.ffun, domain=geometry.mesh )(marker) X = df.SpatialCoordinate(geometry.mesh) N = df.FacetNormal(geometry.mesh) if u is None: vol = df.assemble((-1.0 / 3.0) * df.dot(X, N) * ds) else: F = df.grad(u) + df.Identity(3) J = df.det(F) vol = df.assemble((-1.0 / 3.0) * df.dot(X + u, J * df.inv(F).T * N) * ds) return vol
def fluid_setup(v_, p_, d_, n, psi, gamma, dx_f, ds, mu_f, rho_f, k, dt, v_deg, theta, **semimp_namespace): #J_theta = theta*J_(d_["n"]) + (1 - theta)*J_(d_["n-1"]) #F_fluid_linear = rho_f/k*inner(J_theta*(v_["n"] - v_["n-1"]), psi)*dx_f #F_fluid_nonlinear = rho_f/k*inner(J_theta*(v_["n"] - v_["n-1"]), psi)*dx_f J_theta = theta * J_(d_["n"]) + (1 - theta) * J_(d_["n-1"]) F_fluid_nonlinear = rho_f / k * inner( J_theta * (v_["n"]) - theta * J_(d_["n"]) * v_["n-1"], psi) * dx_f F_fluid_linear = rho_f / k * inner( Constant(1 - theta) * J_(d_["n-1"]) * -(v_["n-1"]), psi) * dx_f F_fluid_nonlinear = Constant(theta) * rho_f * inner( J_(d_["n"]) * grad(v_["n"]) * inv(F_(d_["n"])) * v_["n"], psi) * dx_f F_fluid_nonlinear += inner( J_(d_["n"]) * sigma_f_p(p_["n"], d_["n"]) * inv(F_(d_["n"])).T, grad(psi)) * dx_f F_fluid_nonlinear += Constant(theta) * inner( J_(d_["n"]) * sigma_f_u(v_["n"], d_["n"], mu_f) * inv(F_(d_["n"])).T, grad(psi)) * dx_f F_fluid_linear += Constant(1 - theta) * inner( J_(d_["n-1"]) * sigma_f_u(v_["n-1"], d_["n-1"], mu_f) * inv(F_(d_["n-1"])).T, grad(psi)) * dx_f F_fluid_nonlinear += inner(div(J_(d_["n"]) * inv(F_(d_["n"])) * v_["n"]), gamma) * dx_f F_fluid_linear += Constant(1 - theta) * rho_f * inner( J_(d_["n-1"]) * grad(v_["n-1"]) * inv(F_(d_["n-1"])) * v_["n-1"], psi) * dx_f F_fluid_nonlinear -= rho_f * inner( J_(d_["n"]) * grad(v_["n"]) * inv(F_(d_["n"])) * ((d_["n"] - d_["n-1"]) / k), psi) * dx_f return dict(F_fluid_linear=F_fluid_linear, F_fluid_nonlinear=F_fluid_nonlinear)
def Fluid_correction_variation(v_f, p_f, v_, p_, d_, dvp_, psi, gamma, dx_f, \ mu_f, rho_f, k, dt, n, dS, **semimp_namespace): F_correction = rho_f/k*J_(d_["tilde"])*inner(v_f - v_["tilde"], psi)*dx_f F_correction -= p_f*J_(d_["tilde"])*inner(inv(F_(d_["tilde"])).T, grad(psi))*dx_f F_correction += J_(d_["tilde"])*inner(grad(v_f), inv(F_(d_["tilde"])).T)*gamma*dx_f #Use newly computed "n" from step 3.2m first time "tilde" F_correction += J_(d_["tilde"]("-"))*dot(v_f("-") - \ (d_["n"]("-")-d_["n-1"]("-"))/k, n("-"))*gamma("-")*dS(5) #F_correction += J_(d_["tilde"]("+"))*dot(v_f("+") - \ #(d_["n"]("-")-d_["n-1"]("-"))/k, n("+"))*gamma("+")*dS(5) #F_correction += dot(v_f("+") - \ #(d_["n"]("-")-d_["n-1"]("-"))/k, n("+"))*gamma("+")*dS(5) return dict(F_correction=F_correction)
def Fluid_tentative_variation(v_tent, v_, d_, beta, dx_f, mu_f, rho_f, k, dS2, **semimp_namespace): F_tentative = rho_f / k * J_(d_["tilde"]) * inner(v_tent - v_["n-1"], beta) * dx_f F_tentative += rho_f*inner(J_(d_["tilde"])*grad(v_tent)*inv(F_(d_["tilde"])) \ * (v_["tilde-1"] - (d_["tilde"] - d_["n-1"]) / k), beta)*dx_f F_tentative += 2*mu_f*J_(d_["tilde"])*inner(eps(d_["tilde"], v_tent), \ eps(d_["tilde"], beta))*dx_f F_tentative -= inner(Constant((0, 0)), beta) * dx_f return dict(F_tentative=F_tentative)
def fluid_setup(v_, p_, d_, psi, gamma, dx_f, mu_f, rho_f, k, theta, **namespace): """ ALE formulation (theta-scheme) of the incompressible Navier-Stokes flow problem: du/dt + u * grad(u - w) = grad(p) + nu * div(grad(u)) div(u) = 0 """ theta0 = Constant(theta) theta1 = Constant(1 - theta) # Note that we here split the equation into a linear and nonlinear part for faster # computation of the Jacobian matrix. # Temporal derivative F_fluid_nonlinear = rho_f / k * inner( J_(d_["n"]) * theta0 * (v_["n"] - v_["n-1"]), psi) * dx_f F_fluid_linear = rho_f / k * inner( J_(d_["n-1"]) * theta1 * (v_["n"] - v_["n-1"]), psi) * dx_f # Convection F_fluid_nonlinear += theta0 * rho_f * inner( grad(v_["n"]) * inv(F_(d_["n"])) * J_(d_["n"]) * v_["n"], psi) * dx_f F_fluid_linear += theta1 * rho_f * inner( grad(v_["n-1"]) * inv(F_(d_["n-1"])) * J_(d_["n-1"]) * v_["n-1"], psi) * dx_f # Stress from pressure F_fluid_nonlinear += inner( J_(d_["n"]) * sigma_f_p(p_["n"], d_["n"]) * inv(F_(d_["n"])).T, grad(psi)) * dx_f # Stress from velocity F_fluid_nonlinear += theta0 * inner( J_(d_["n"]) * sigma_f_u(v_["n"], d_["n"], mu_f) * inv(F_(d_["n"])).T, grad(psi)) * dx_f F_fluid_linear += theta1 * inner( J_(d_["n-1"]) * sigma_f_u(v_["n-1"], d_["n-1"], mu_f) * inv(F_(d_["n-1"])).T, grad(psi)) * dx_f # Divergence free term F_fluid_nonlinear += inner(div(J_(d_["n"]) * inv(F_(d_["n"])) * v_["n"]), gamma) * dx_f # ALE term F_fluid_nonlinear -= rho_f / k * inner( J_(d_["n"]) * grad(v_["n"]) * inv(F_(d_["n"])) * (d_["n"] - d_["n-1"]), psi) * dx_f return dict(F_fluid_linear=F_fluid_linear, F_fluid_nonlinear=F_fluid_nonlinear)
def fluid_setup(d, v, p, v_, p_, d_, n, psi, gamma, dx_f, ds, mu_f, rho_f, k, dt, v_deg, theta, **semimp_namespace): #First Order """ dvdt = 1./k*(d - v_["n-1"]) dudt = 1./(2*k)*(d_["n-1"] - d_["n-3"]) J_tilde = J_(d_["n-1"]) F_tilde = F_(d_["n-1"]) d_tilde = d_["n-1"] """ #Second Order dvdt = 1. / (2 * k) * (3. * v - 4. * v_["n-1"] + v_["n-2"]) dudt = 1. / (2 * k) * (3. * d_["n-1"] - 4. * d_["n-2"] + d_["n-3"]) J_tilde = 2. * J_(d_["n-1"]) - J_(d_["n-2"]) F_tilde = 2. * F_(d_["n-1"]) - F_(d_["n-2"]) d_tilde = 2. * d_["n-1"] - d_["n-2"] F_fluid = rho_f * inner(J_tilde * dvdt, psi) * dx_f F_fluid += rho_f * inner( J_tilde * grad(v) * inv(F_tilde) * (v_["n-1"] - dudt), psi) * dx_f F_fluid += J_tilde * inner(2 * mu_f * D_U(d_tilde, v), D_U(d_tilde, psi)) * dx_f F_fluid -= inner(J_tilde * p * inv(F_tilde).T, grad(psi)) * dx_f #F_fluid += inner(div(J_tilde*inv(F_tilde)*v), gamma)*dx_f #Check 2.13 paper F_fluid += inner(J_tilde * grad(v), inv(F_tilde).T * gamma) * dx_f #Check 2.13 paper #Not a must #djdt = 1./(2*k)*(3.*J_(d_["n-1"]) - 4.*J_(d_["n-2"]) + J_(d_["n-3"]) ) #F_fluid += rho_f/2.*inner(djdt*v, psi)*dx_f #F_fluid += rho_f/2.*inner(div(J_(d_["n-1"])*inv(F_tilde)\ # *(v_["n-1"] - dudt))*v, psi)*dx_f return dict(F_fluid=F_fluid)
def get_cavity_volume_form(mesh, u=None, xshift=0.0): from . import kinematics shift = Constant((xshift, 0.0, 0.0)) X = dolfin.SpatialCoordinate(mesh) - shift N = dolfin.FacetNormal(mesh) if u is None: vol_form = (-1.0 / 3.0) * dolfin.dot(X, N) else: F = kinematics.DeformationGradient(u) J = kinematics.Jacobian(F) vol_form = (-1.0 / 3.0) * dolfin.dot(X + u, J * dolfin.inv(F).T * N) return vol_form
def Fluid_tentative_variation(v_tent, v_, p_, d_, dw_, vp_, v, \ beta, dx_f, mu_f, rho_f, k, dt, dS2, **semimp_namespace): #Reuse of TrialFunction w, TestFunction psi #used in extrapolation assuming same degree F_tentative = rho_f/k*J_(d_["tilde"])*inner(v_tent - v_["n-1"], beta)*dx_f F_tentative += rho_f*inner(J_(d_["tilde"])*grad(v_tent)*inv(F_(d_["tilde"])) \ * (v_["tilde-1"] - 1./k*(d_["tilde"] - d_["n-1"])), beta)*dx_f F_tentative += J_(d_["tilde"])*inner(2*mu_f*eps(d_["tilde"], v_tent), eps(d_["tilde"], beta))*dx_f F_tentative -= inner(Constant((0, 0)), beta)*dx_f return dict(F_tentative=F_tentative)
def FirstPiolaStress(self, F, p=None, *args, **kwargs): F = dolfin.variable(F) # First Piola Kirchoff psi_iso = self.strain_energy(F) P = dolfin.diff(psi_iso, F) if p is not None: J = dolfin.variable(kinematics.Jacobian(F)) psi_vol = self.compressibility(p, J) # PiolaTransform P_vol = J * dolfin.diff(psi_vol, J) * dolfin.inv(F).T P += P_vol return P
def extrapolate_setup(F_fluid_linear, extype, mesh_file, d_, phi, gamma, dx_f, **semimp_namespace): def F_(U): return Identity(len(U)) + grad(U) def J_(U): return det(F_(U)) def eps(U): return 0.5 * (grad(U) * inv(F_(U)) + inv(F_(U)).T * grad(U).T) def STVK(U, alfa_mu, alfa_lam): return alfa_lam * tr(eps(U)) * Identity( len(U)) + 2.0 * alfa_mu * eps(U) #return F_(U)*(alfa_lam*tr(eps(U))*Identity(len(U)) + 2.0*alfa_mu*eps(U)) alfa = 1.0 # holder value if linear is chosen if extype == "det": #alfa = inv(J_(d_["n"])) alfa = 1. / (J_(d_["n"])) if extype == "smallconst": alfa = 0.01 * (mesh_file.hmin())**2 if extype == "const": alfa = 1.0 F_extrapolate = alfa * inner(grad(d_["n"]), grad(phi)) * dx_f if extype == "linear": hmin = mesh_file.hmin() #E_y = 1./(J_(d_["n"])) #nu = -0.2 #(-1, 0.5) E_y = 1. / CellVolume(mesh_file) nu = 0.25 alfa_lam = nu * E_y / ((1. + nu) * (1. - 2. * nu)) alfa_mu = E_y / (2. * (1. + nu)) #alfa_lam = hmin*hmin ; alfa_mu = hmin*hmin F_extrapolate = inner( J_(d_["n"]) * STVK(d_["n"], alfa_mu, alfa_lam) * inv(F_(d_["n"])).T, grad(phi)) * dx_f #F_extrapolate = inner(STVK(d_["n"],alfa_mu,alfa_lam) , grad(phi))*dx_f F_fluid_linear += F_extrapolate return dict(F_fluid_linear=F_fluid_linear)
def extrapolate_setup(F_fluid_linear, mesh, d_, phi, gamma, dx_f, **namespace): """ Elastic lifting operator solving the equation of linear elasticity. div(sigma(d)) = 0 in the fluid domain d = 0 on the fluid boundaries other than FSI interface d = solid_d on the FSI interface """ E_y = 1.0 / CellVolume(mesh) nu = 0.25 alpha_lam = nu * E_y / ((1.0 + nu) * (1.0 - 2.0 * nu)) alpha_mu = E_y / (2.0 * (1.0 + nu)) F_extrapolate = inner( J_(d_["n"]) * S_linear(d_["n"], alpha_mu, alpha_lam) * inv(F_(d_["n"])).T, grad(phi)) * dx_f F_fluid_linear += F_extrapolate return dict(F_fluid_linear=F_fluid_linear)
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 Fluid_tentative_variation(v_, p_, d_, dvp_, w, w_f, v_tilde_n1, \ psi, beta, gamma, dx_f, mu_f, rho_f, k, dt, **semimp_namespace): d_tent = dvp_["tilde"].sub(0, deepcopy=True) d_n = dvp_["tilde"].sub(0, deepcopy=True) d_n1 = dvp_["n-1"].sub(0, deepcopy=True) v_n1 = dvp_["n-1"].sub(1, deepcopy=True) #Reuse of TrialFunction w, TestFunction beta #used in extrapolation assuming same degree F_tentative = rho_f/k*J_(d_tent)*inner(w - v_n1, beta)*dx_f F_tentative += rho_f*inner(J_(d_tent)*grad(w)*inv(F_(d_tent)) \ * (v_tilde_n1 - 1./k*(d_n - d_n1)), beta)*dx_f F_tentative += J_(d_tent)*inner(mu_f*D_U(d_tent, w), D_U(d_tent, beta))*dx_f F_tentative -= inner(Constant((0, 0)), beta)*dx_f return dict(F_tentative=F_tentative)
def eps(U): return 0.5 * (grad(U) * inv(F_(U)) + inv(F_(U)).T * grad(U).T)
def sigma_f(p, u, d, mu_f): return -p*Identity(len(u)) +\ mu_f*(grad(u)*inv(F_(d)) + inv(F_(d)).T*grad(u).T)
def main(dt, tEnd, length=10.0, height=5.0, numElementsFilm=2.0, reGen=True, ratLame=5.0, ratFilmSub=100.0): #fileDir = ("results-dt-%.2f-tEnd-%.0f-L-%.1f-H-%.1f-ratioLame-%.0f-ratioFilm-%.0f" % # (dt, tEnd, length, height, ratLame, ratFilmSub)) fileDir = "results-1" # create geometry rectDomain = Geometry(length=length, height=height, filmHeight=0.05) rectDomain.read_mesh(numElementsFilm, reGen) # define periodic boundary conditions periodicBC = PeriodicBoundary(rectDomain) # specify physical parameters physParams = Physical_Params(lmbdaSub=ratLame, muSub=1.0, ratFilmSub=100.0) physParams.create_Lame(rectDomain) # create discrete function space element = create_vector_element(rectDomain, order=1) W = dl.FunctionSpace(rectDomain.mesh, element, constrained_domain=periodicBC) # define boundaries def left(x, on_boundary): return dl.near(x[0], 0.) and on_boundary def right(x, on_boundary): return dl.near(x[0], rectDomain.length) and on_boundary def bottom(x, on_boundary): return dl.near(x[1], 0.0) and on_boundary def top(x, on_boundary): return dl.near(x[1], rectDomain.height) and on_boundary def corner(x, on_boundary): return dl.near(x[0], 0.0) and dl.near(x[1], 0.0) # define fixed boundary bcs = [ dl.DirichletBC(W.sub(0), dl.Constant(0), left), dl.DirichletBC(W.sub(0), dl.Constant(0), right), dl.DirichletBC(W.sub(1), dl.Constant(0), bottom), dl.DirichletBC(W.sub(0), dl.Constant(0), corner, method="pointwise") ] bcs = bcs[-2:] # the variable to solve for w = dl.Function(W, name="Variables at current step") # test and trial function dw = dl.TrialFunction(W) w_ = dl.TestFunction(W) # dealing with physics of growth growthFactor = create_growthFactor(rectDomain, filmGrowth=1, subGrowth=0) Fg = create_Fg(growthFactor, "uniaxial") # kinematics I = dl.Identity(2) F = I + dl.grad(w) Fe = F * dl.inv(Fg) # write the variational form from potential energy psi = cal_neoHookean(Fe, physParams) Energy = psi * dl.dx Residual = dl.derivative(Energy, w, w_) Jacobian = dl.derivative(Residual, w, dw) problem = BucklingProblem(w, Energy, Residual, Jacobian) wLowerBound, wUpperBound = create_bounds(wMin=[-0.5, -0.5], wMax=[0.5, 0.5], functionSpace=W, boundaryCondtions=bcs) # Create the PETScTAOSolver solver = dl.PETScTAOSolver() TAOSolverParameters = { "method": "tron", "maximum_iterations": 1000, "monitor_convergence": True } solver.parameters.update(TAOSolverParameters) #solver.parameters["report"] = False #solver.parameters["linear_solver"] = "umfpack" #solver.parameters["line_search"] = "gpcg" #solver.parameters["preconditioner"] = "ml_amg" growthRate = 0.1 growthEnd = growthRate * tEnd gF = 0.0 outDisp = dl.File(fileDir + "/displacement.pvd") outDisp << (w, 0.0) iCounter = 0 wArray = w.compute_vertex_values() while gF <= growthEnd - tol: gF += growthRate * dt iCounter += 1 growthFactor.gF = gF w.vector()[:] += 2e-04 * np.random.uniform(-1, 1, w.vector().local_size()) nIters, converged = solver.solve(problem, w.vector(), wLowerBound.vector(), wUpperBound.vector()) wArray[:] = w.compute_vertex_values() np.save(fileDir + "/w-{}.npy".format(iCounter), wArray) print("--- growth = %.4f, niters = %d, dt = %.5f -----" % (1 + gF, nIters, dt)) outDisp << (w, gF)