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 define_deformation_tensors(self): """ Define kinematic tensors needed for constitutive equations. Tensors that are irrelevant to the current problem are set to 0, e.g. the deformation gradient is set to 0 when simulating fluid flow. Secondary tensors are added with the suffix "0" if the problem is time-dependent. The names of member data added to an instance of the MechanicsProblem class are: - :code:`deformationGradient` - :code:`deformationGradient0` - :code:`velocityGradient` - :code:`velocityGradient0` - :code:`jacobian` - :code:`jacobian0` """ # Exit function if tensors have already been defined. if hasattr(self, 'deformationGradient') \ or hasattr(self, 'deformationRateGradient'): return None # Checks the type of material to determine which deformation # tensors to define. if self.config['material']['type'] == 'elastic': I = dlf.Identity(self.mesh.geometry().dim()) self.deformationGradient = I + dlf.grad(self.displacement) self.jacobian = dlf.det(self.deformationGradient) if self.config['formulation']['time']['unsteady']: self.velocityGradient = dlf.grad(self.velocity) self.deformationGradient0 = I + dlf.grad(self.displacement0) self.velocityGradient0 = dlf.grad(self.velocity0) self.jacobian0 = dlf.det(self.deformationGradient0) else: self.velocityGradient = 0 self.deformationGradient0 = 0 self.velocityGradient0 = 0 self.jacobian0 = 0 else: self.deformationGradient = 0 self.deformationGradient0 = 0 self.jacobian = 0 self.jacobian0 = 0 self.velocityGradient = dlf.grad(self.velocity) if self.config['formulation']['time']['unsteady']: self.velocityGradient0 = dlf.grad(self.velocity0) else: self.velocityGradient0 = 0 return None
def __init__(self, u): '''Deformation measures.''' self.d = d = len(u) self.I = I = Identity(d) self.F = F = variable(I + grad(u)) self.C = C = F.T * F self.E = 0.5 * (C - I) self.J = det(F) self.I1 = tr(C) self.I2 = 0.5 * (tr(C)**2 - tr(C * C)) self.I3 = det(C)
def dw_int(self, u, v): """ Construct internal energy. Parameters ---------- u: Function v: TestFunction """ # u Function (in the nonlinear case) assert isinstance(u, dlfn.function.function.Function) # v TestFunction assert isinstance(v, dlfn.function.argument.Argument) assert hasattr(self, "_elastic_ratio") assert hasattr(self, "_I") # deformation gradient F = self._I + grad(u) # right Cauchy-Green tensor C = F.T * F # volume ratio J = dlfn.det(F) # 2. Piola-Kirchhoff stress S = self._I - J**(-self._elastic_ratio) * inv(C) dE = dlfn.Constant(0.5) * (F.T * grad(v) + grad(v).T * F) return inner(S, dE)
def postprocess_cauchy_stress(self, displacement): """ Compute Cauchy stress from given numerical solution. Parameters ---------- displacement: Function Computed numerical displacement """ assert hasattr(self, "_elastic_ratio") assert hasattr(self, "_I") assert isinstance(displacement, dlfn.function.function.Function) # displacement gradient H = grad(displacement) # deformation gradient F = self._I + H # right Cauchy-Green tensor C = F.T * F # volume ratio J = dlfn.det(F) # dimensionless 2. Piola-Kirchhoff stress tensor (symbolic) S = self._I - J**(-self._elastic_ratio) * inv(C) # dimensionless Cauchy stress tensor (symbolic) sigma = (F * S * F.T) / J return sigma
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 extrapolate_setup(extype, mesh_file, d, w, phi, dx_f, d_, **semimp_namespace): alpha = 1. / det(Identity(len(d_["n"])) + grad(d_["n"])) F_extrapolate = alpha*inner(grad(d), grad(phi))*dx_f \ - inner(Constant((0, 0)), phi)*dx_f return dict(F_extrapolate=F_extrapolate)
def compute(self, get): u = get("Velocity") S = (grad(u) + grad(u).T) / 2 Omega = (grad(u) - grad(u).T) / 2 Q = 0.5 * (Omega**2 - S**2) expr = Q**3 / 3 + det(grad(u))**2 / 2 return self.expr2function(expr, self._function)
def cal_neoHookean(F, physParams): """ neoHookean elastic energy density: psi """ lmbda, mu = physParams.lmbda, physParams.mu ln = dl.ln J = dl.det(F) Ic = dl.tr(F.T * F) # Invariants of deformation tensors return (lmbda / 4) * (J**2 - 2 * ln(J) - 1) + (mu / 2) * (Ic - 2) - mu * ln(J)
m0 = 543.09 m1 = 4.73 m2 = 4.57 m3 = 5.27 m4 = 4.49 m5 = 4.49 m6 = 12.02 m = (m0,m1,m2,m3,m4,m5,m6) parameters = dl.interpolate(dl.Constant(m),parameterV) #Model d = len(u) I = dl.Identity(d) # Identity tensor F = I + dl.grad(u) # Deformation gradient C = F.T*F # Right Cauchy-Green tensor J = dl.det(F) # Jacobian of deformation gradient Cbar = C*(J**(-2.0/3.0)) # Deviatoric Right Cauchy-Green tensor E = dl.Constant(0.5)*(Cbar-I) # Deviatoric Green strain c0,c1,c2,c3,c4,c5,c6 = dl.split(parameters) Q = c1*(E[0,0]**2)+c2*(E[1,1]**2)+c3*(E[2,2]**2) + c4*(dl.Constant(4.0)*(E[1,2]**2)) #+c5*(dl.Constant(4.0)*(E[0,1]**2))#)#+c6*(dl.Constant(4.0)*(E[0,2]**2)) Energy = dl.Constant(0.5)*c0*(dl.exp(Q)-dl.Constant(1.0)) IncompressibilityConstraint = (J-dl.Constant(1.0)) Lagrangian = p*IncompressibilityConstraint*dl.dx + Energy*dl.dx yhat = dl.interpolate(dl.Constant((1,1,1,1)),TaylorHoodV) residual_form = dl.derivative(Lagrangian,y,yhat) residual_form_a = dl.derivative(residual_form, a,atest) residual_form_y = dl.derivative(residual_form, y,ytest) residual_form_ya = dl.assemble(dl.derivative(residual_form_y, a,atrial))
def Jacobian(F): """Determinant of the deformation gradient """ return det(F)
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
bcs.append(DirichletBC(V, zeros, fixed_vertex_000, "pointwise")) bcs.append(DirichletBC(Vz, zero, fixed_vertex_010, "pointwise")) ### Define hyperelastic material model material_parameters = {'E': Constant(1.0), 'nu': Constant(0.0)} E, nu = material_parameters.values() 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)
def _I3(self, F): C = RightCauchyGreen(F, self._isochoric) return det(C)
def J_(d): return det(F_(d))
def I3(F, isochoric=False): C = RightCauchyGreen(F, isochoric) return det(C)
'fiber_files': fiber_files, 'fiber_names': fiber_names, 'element': 'p%i' % pd } from fenicsmechanics.materials.solid_materials import AnisotropicMaterial, FungMaterial mat1 = AnisotropicMaterial(fiber_dict1, mesh) hdf5_name = "fibers/n_all.h5" f = dlf.HDF5File(MPI_COMM_WORLD, hdf5_name, 'w') f.write(n1, "n1") f.write(n2, "n2") f.close() fiber_dict2 = { 'fiber_files': hdf5_name, 'fiber_names': fiber_names[:2], 'element': 'p%i' % pd } mat2 = AnisotropicMaterial(fiber_dict2, mesh) material_dict = {'kappa': 1e4, 'fibers': fiber_dict2} mat3 = FungMaterial(mesh, inverse=True, incompressible=False, **material_dict) u = dlf.Function(W) F = dlf.Identity(2) + dlf.grad(u) J = dlf.det(F) P = mat3.stress_tensor(F, J)
prob.run_model() # prob.check_partials(compact_print=True) prob.run_driver() eps = df.sym(df.grad(displacements_function)) 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 / eps_eq fFile = df.HDF5File(df.MPI.comm_world, "eps_eq_proj_1000.h5", "w") fFile.write(eps_eq_proj, "/f") fFile.close() F_m = df.grad(displacements_function) + df.Identity(2) det_F_m = df.det(F_m) det_F_m_proj = df.project(det_F_m, density_function_space) fFile = df.HDF5File(df.MPI.comm_world, "det_F_m_proj_1000.h5", "w") fFile.write(det_F_m_proj, "/f") fFile.close() f2 = df.Function(density_function_space) #save the solution vector df.File('solutions/case_1/hyperelastic_cantilever_beam/displacement.pvd' ) << displacements_function stiffness = df.project(density_function / (1 + 8. * (1. - density_function)), density_function_space) df.File( 'solutions/case_1/hyperelastic_cantilever_beam/stiffness.pvd') << stiffness df.File('solutions/case_1/hyperelastic_cantilever_beam/eps_eq_proj_1000.pvd'
def Extrapolate_setup(d, phi, dx_f, d_, **semimp_namespace): alfa = 1. / det(Identity(len(d_["n"])) + grad(d_["n"])) F_extrapolate = alfa*inner(grad(d), grad(phi))*dx_f - inner(Constant((0, 0)), phi)*dx_f return dict(F_extrapolate=F_extrapolate)
def J_(d): """ Determinant of the deformation gradient """ return det(F_(d))
"material": material, "bc": { "dirichlet": make_dirichlet_bcs, "neumann": [[T, 1]] } } df.parameters["adjoint"]["stop_annotating"] = True df.set_log_active(True) df.set_log_level(df.INFO) solver = LVSolver(params) solver.solve() uh, ph = solver.get_state().split(deepcopy=True) F = df.grad(uh) + df.Identity(2) J = df.project(df.det(F), DG1) err_u.append(df.errornorm(u_exact, uh, "H1", mesh=mesh)) err_p.append(df.errornorm(p_exact, ph, "L2", mesh=mesh)) err_J.append(df.errornorm(df.Expression("1.0"), J, "L2", mesh=mesh)) if 0: u = df.interpolate(u_exact, P2) p = df.interpolate(p_exact, P1) df.plot(u - uh, title="u-uh") df.plot(p - ph, title="p-ph") df.plot(ph, title="ph") df.plot(p, title="p") df.plot(u, mode="displacement") df.plot(uh, interactive=True, mode="displacement")
def truth_solve(mu_unkown): print("Performing truth solve at mu =", mu_unkown) (mesh, subdomains, boundaries, restrictions) = read_mesh() # (mesh, subdomains, boundaries, restrictions) = create_mesh() dx = Measure('dx', subdomain_data=subdomains) ds = Measure('ds', subdomain_data=boundaries) W = generate_block_function_space(mesh, restrictions) # Test and trial functions block_v = BlockTestFunction(W) v, q = block_split(block_v) block_du = BlockTrialFunction(W) du, dp = block_split(block_du) block_u = BlockFunction(W) u, p = block_split(block_u) # gap # V2 = FunctionSpace(mesh, "CG", 1) # gap = Function(V2, name="Gap") # obstacle R = 0.25 d = 0.15 x_0 = mu_unkown[0] y_0 = mu_unkown[1] obstacle = Expression("-d+(pow(x[0]-x_0,2)+pow(x[1]-y_0, 2))/2/R", d=d, R=R , x_0 = x_0, y_0 = y_0, degree=0) # Constitutive parameters E = Constant(10.0) nu = Constant(0.3) mu, lmbda = Constant(E/(2*(1 + nu))), Constant(E*nu/((1 + nu)*(1 - 2*nu))) B = Constant((0.0, 0.0, 0.0)) # Body force per unit volume T = Constant((0.0, 0.0, 0.0)) # Traction force on the boundary # Kinematics # ----------------------------------------------------------------------------- mesh_dim = mesh.topology().dim() # Spatial dimension I = Identity(mesh_dim) # Identity tensor F = I + grad(u) # Deformation gradient C = F.T*F # Right Cauchy-Green tensor J = det(F) # 3rd invariant of the deformation tensor # Strain function def P(u): # P = dW/dF: return mu*(F - inv(F.T)) + lmbda*ln(J)*inv(F.T) def eps(v): return sym(grad(v)) def sigma(v): return lmbda*tr(eps(v))*Identity(3) + 2.0*mu*eps(v) # Definition of The Mackauley bracket <x>+ def ppos(x): return (x+abs(x))/2. # Define the augmented lagrangian def aug_l(x): return x + pen*(obstacle-u[2]) pen = Constant(1e4) # Boundary conditions # bottom_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 2) # left_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 3) # right_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 4) # front_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 5) # back_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 6) # # sym_x_bc = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 2) # # sym_y_bc = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3) # # bc = BlockDirichletBC([bottom_bc, sym_x_bc, sym_y_bc]) # bc = BlockDirichletBC([bottom_bc, left_bc, right_bc, front_bc, back_bc]) bottom_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 2) left_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 3) left_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3) right_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 4) right_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 4) front_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 5) front_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 5) back_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 6) back_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 6) # sym_x_bc = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 2) # sym_y_bc = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3) # bc = BlockDirichletBC([bottom_bc, sym_x_bc, sym_y_bc]) bc = BlockDirichletBC([bottom_bc, left_bc_x, left_bc_y, \ right_bc_x, right_bc_y, front_bc_x, front_bc_y, \ back_bc_x, back_bc_y]) # Variational forms # F = inner(sigma(u), eps(v))*dx + pen*dot(v[2], ppos(u[2]-obstacle))*ds(1) # F = [inner(sigma(u), eps(v))*dx - aug_l(l)*v[2]*ds(1) + ppos(aug_l(l))*v[2]*ds(1), # (obstacle-u[2])*v*ds(1) - (1/pen)*ppos(aug_l(l))*v*ds(1)] # F_a = inner(sigma(u), eps(v))*dx # F_b = - aug_l(p)*v[2]*ds(1) + ppos(aug_l(p))*v[2]*ds(1) # F_c = (obstacle-u[2])*q*ds(1) # F_d = - (1/pen)*ppos(aug_l(p))*q*ds(1) # # block_F = [[F_a, F_b], # [F_c, F_d]] F_a = inner(P(u), grad(v))*dx - dot(B, v)*dx - dot(T, v)*ds \ - aug_l(p)*v[2]*ds(1) + ppos(aug_l(p))*v[2]*ds(1) F_b = (obstacle-u[2])*q*ds(1) - (1/pen)*ppos(aug_l(p))*q*ds(1) block_F = [F_a, F_b] J = block_derivative(block_F, block_u, block_du) # Setup solver problem = BlockNonlinearProblem(block_F, block_u, bc, J) solver = BlockPETScSNESSolver(problem) solver.parameters.update({ "linear_solver": "mumps", "absolute_tolerance": 1E-4, "relative_tolerance": 1E-4, "maximum_iterations": 50, "report": True, "error_on_nonconvergence": True }) # solver.parameters.update({ # "linear_solver": "cg", # "absolute_tolerance": 1E-4, # "relative_tolerance": 1E-4, # "maximum_iterations": 50, # "report": True, # "error_on_nonconvergence": True # }) # Perform a fake loop over time. Note how up will store the solution at the last time. # Q. for? # A. You can remove it, since your problem is stationary. The template was targeting # a final application which was transient, but in which the ROM should have only # described the final solution (when reaching the steady state). # for _ in range(2): # solver.solve() a1 = solver.solve() print(a1) # save all the solution here as a function of time # Return the solution at the last time # Q. block_u or block # A. I think block_u, it will split split among the components elsewhere return block_u
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 main(traction, outfile='displacement.json'): # Create the Beam geometry # Length L = 10 # Width W = 1 print('Got traction of {} kN'.format(traction)) # Create mesh mesh = dolfin.BoxMesh(dolfin.Point(0, 0, 0), dolfin.Point(L, W, W), 30, 3, 3) # Mark boundary subdomians left = dolfin.CompiledSubDomain("near(x[0], side) && on_boundary", side=0) bottom = dolfin.CompiledSubDomain("near(x[2], side) && on_boundary", side=0) boundary_markers = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) boundary_markers.set_all(0) left_marker = 1 bottom_marker = 2 left.mark(boundary_markers, left_marker) bottom.mark(boundary_markers, bottom_marker) f = dolfin.File('boundary_markers.pvd') f << boundary_markers P2 = dolfin.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = dolfin.FiniteElement("Lagrange", mesh.ufl_cell(), 1) state_space = dolfin.FunctionSpace(mesh, P2 * P1) state = dolfin.Function(state_space) state_test = dolfin.TestFunction(state_space) u, p = dolfin.split(state) v, q = dolfin.split(state_test) # Some mechanical quantities I = dolfin.Identity(3) gradu = dolfin.grad(u) F = dolfin.variable(I + gradu) J = dolfin.det(F) # Material properites mu = dolfin.Constant(100.0) lmbda = dolfin.Constant(1.0) epsilon = 0.5 * (gradu + gradu.T) # Strain energy W = lmbda / 2 * (dolfin.tr(epsilon)**2) \ + mu * dolfin.tr(epsilon * epsilon) internal_energy = W - p * (J - 1) # Neumann BC N = dolfin.FacetNormal(mesh) p_bottom = dolfin.Constant(traction) external_work = dolfin.inner(v, p_bottom * dolfin.cofac(F) * N) \ * dolfin.ds(bottom_marker, subdomain_data=boundary_markers) # Virtual work G = dolfin.derivative(internal_energy * dolfin.dx, state, state_test) + external_work # Anchor the left side bcs = dolfin.DirichletBC(state_space.sub(0), dolfin.Constant((0.0, 0.0, 0.0)), left) # Traction at the bottom of the beam dolfin.solve(G == 0, state, [bcs]) # Get displacement and hydrostatic pressure u, p = state.split(deepcopy=True) point = np.array([10.0, 0.5, 1.0]) disp = np.zeros(3) u.eval(disp, point) print(('Get z-position of point ({}): {:.4f} mm' '').format(', '.join(['{:.1f}'.format(p) for p in point]), point[2] + disp[2])) with open(outfile, 'w') as f: json.dump({ 'point': point.tolist(), 'displacement': disp.tolist() }, f, indent=4) print('Output saved to {}'.format(outfile)) V = dolfin.VectorFunctionSpace(mesh, "CG", 1) u_int = dolfin.interpolate(u, V) moved_mesh = dolfin.Mesh(mesh) dolfin.ALE.move(mesh, u_int) f = dolfin.File('mesh.pvd') f << mesh f = dolfin.File('bending_beam.pvd') f << moved_mesh
def test_separated_parametrized_forms_vector_3(): a3 = inner(det(expr3)*(expr4 + expr3*expr3)*expr1, grad(v))*dx + inner(grad(u)*expr2, v)*dx + expr1*inner(u, v)*dx a3_sep = SeparatedParametrizedForm(a3) log(PROGRESS, "*** ### FORM 3 ### ***") log(PROGRESS, "We try now with a more complex expression of for each coefficient") a3_sep.separate() log(PROGRESS, "\tLen coefficients:\n" + "\t\t" + str(len(a3_sep.coefficients)) + "\n" ) assert 6 == len(a3_sep.coefficients) log(PROGRESS, "\tSublen coefficients:\n" + "\t\t" + str(len(a3_sep.coefficients[0])) + "\n" + "\t\t" + str(len(a3_sep.coefficients[1])) + "\n" + "\t\t" + str(len(a3_sep.coefficients[2])) + "\n" + "\t\t" + str(len(a3_sep.coefficients[3])) + "\n" + "\t\t" + str(len(a3_sep.coefficients[4])) + "\n" + "\t\t" + str(len(a3_sep.coefficients[5])) + "\n" ) assert 1 == len(a3_sep.coefficients[0]) assert 1 == len(a3_sep.coefficients[1]) assert 1 == len(a3_sep.coefficients[2]) assert 1 == len(a3_sep.coefficients[3]) assert 1 == len(a3_sep.coefficients[4]) assert 1 == len(a3_sep.coefficients[5]) log(PROGRESS, "\tCoefficients:\n" + "\t\t" + str(a3_sep.coefficients[0][0]) + "\n" + "\t\t" + str(a3_sep.coefficients[1][0]) + "\n" + "\t\t" + str(a3_sep.coefficients[2][0]) + "\n" + "\t\t" + str(a3_sep.coefficients[3][0]) + "\n" + "\t\t" + str(a3_sep.coefficients[4][0]) + "\n" + "\t\t" + str(a3_sep.coefficients[5][0]) + "\n" ) assert "{ A | A_{i_{34}, i_{35}} = ({ A | A_{i_{32}, i_{33}} = ({ A | A_{i_{29}, i_{30}} = sum_{i_{31}} f_7[i_{29}, i_{31}] * f_7[i_{31}, i_{30}] })[i_{32}, i_{33}] * f_7[0, 0] * f_7[1, 1] })[i_{34}, i_{35}] * f_5 }" == str(a3_sep.coefficients[0][0]) assert "{ A | A_{i_{34}, i_{35}} = ({ A | A_{i_{32}, i_{33}} = f_8[i_{32}, i_{33}] * f_7[1, 0] * -1 * f_7[0, 1] })[i_{34}, i_{35}] * f_5 }" == str(a3_sep.coefficients[1][0]) assert "{ A | A_{i_{34}, i_{35}} = ({ A | A_{i_{32}, i_{33}} = f_8[i_{32}, i_{33}] * f_7[0, 0] * f_7[1, 1] })[i_{34}, i_{35}] * f_5 }" == str(a3_sep.coefficients[2][0]) assert "{ A | A_{i_{34}, i_{35}} = ({ A | A_{i_{32}, i_{33}} = ({ A | A_{i_{29}, i_{30}} = sum_{i_{31}} f_7[i_{29}, i_{31}] * f_7[i_{31}, i_{30}] })[i_{32}, i_{33}] * f_7[1, 0] * -1 * f_7[0, 1] })[i_{34}, i_{35}] * f_5 }" == str(a3_sep.coefficients[3][0]) assert "f_6" == str(a3_sep.coefficients[4][0]) assert "f_5" == str(a3_sep.coefficients[5][0]) log(PROGRESS, "\tPlaceholders:\n" + "\t\t" + str(a3_sep._placeholders[0][0]) + "\n" + "\t\t" + str(a3_sep._placeholders[1][0]) + "\n" + "\t\t" + str(a3_sep._placeholders[2][0]) + "\n" + "\t\t" + str(a3_sep._placeholders[3][0]) + "\n" + "\t\t" + str(a3_sep._placeholders[4][0]) + "\n" + "\t\t" + str(a3_sep._placeholders[5][0]) + "\n" ) assert "f_42" == str(a3_sep._placeholders[0][0]) assert "f_43" == str(a3_sep._placeholders[1][0]) assert "f_44" == str(a3_sep._placeholders[2][0]) assert "f_45" == str(a3_sep._placeholders[3][0]) assert "f_46" == str(a3_sep._placeholders[4][0]) assert "f_47" == str(a3_sep._placeholders[5][0]) log(PROGRESS, "\tForms with placeholders:\n" + "\t\t" + str(a3_sep._form_with_placeholders[0].integrals()[0].integrand()) + "\n" + "\t\t" + str(a3_sep._form_with_placeholders[1].integrals()[0].integrand()) + "\n" + "\t\t" + str(a3_sep._form_with_placeholders[2].integrals()[0].integrand()) + "\n" + "\t\t" + str(a3_sep._form_with_placeholders[3].integrals()[0].integrand()) + "\n" + "\t\t" + str(a3_sep._form_with_placeholders[4].integrals()[0].integrand()) + "\n" + "\t\t" + str(a3_sep._form_with_placeholders[5].integrals()[0].integrand()) + "\n" ) assert "sum_{i_{39}} sum_{i_{38}} f_42[i_{38}, i_{39}] * (grad(v_0))[i_{38}, i_{39}] " == str(a3_sep._form_with_placeholders[0].integrals()[0].integrand()) assert "sum_{i_{39}} sum_{i_{38}} f_43[i_{38}, i_{39}] * (grad(v_0))[i_{38}, i_{39}] " == str(a3_sep._form_with_placeholders[1].integrals()[0].integrand()) assert "sum_{i_{39}} sum_{i_{38}} f_44[i_{38}, i_{39}] * (grad(v_0))[i_{38}, i_{39}] " == str(a3_sep._form_with_placeholders[2].integrals()[0].integrand()) assert "sum_{i_{39}} sum_{i_{38}} f_45[i_{38}, i_{39}] * (grad(v_0))[i_{38}, i_{39}] " == str(a3_sep._form_with_placeholders[3].integrals()[0].integrand()) assert "sum_{i_{40}} ({ A | A_{i_{36}} = sum_{i_{37}} f_46[i_{37}] * (grad(v_1))[i_{36}, i_{37}] })[i_{40}] * v_0[i_{40}] " == str(a3_sep._form_with_placeholders[4].integrals()[0].integrand()) assert "f_47 * (sum_{i_{41}} v_0[i_{41}] * v_1[i_{41}] )" == str(a3_sep._form_with_placeholders[5].integrals()[0].integrand()) log(PROGRESS, "\tLen unchanged forms:\n" + "\t\t" + str(len(a3_sep._form_unchanged)) + "\n" ) assert 0 == len(a3_sep._form_unchanged)
def J_(U): return det(F_(U))
E = Constant(1000.0) # Young's modulus nu = Constant(0.3) # Poisson's ratio # 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