def _solve(self, z, x=None): # problem variables du = TrialFunction(self.V) # incremental displacement v = TestFunction(self.V) # test function u = Function(self.V) # displacement from previous iteration # kinematics ii = Identity(3) # identity tensor dimension 3 f = ii + grad(u) # deformation gradient c = f.T * f # right Cauchy-Green tensor # invariants of deformation tensors ic = tr(c) j = det(f) # elasticity parameters if type(z) in [list, np.ndarray]: param = self.param_remapper(z[0]) if self.param_remapper is not None else z[0] else: param = self.param_remapper(z) if self.param_remapper is not None else z e_var = variable(Constant(param)) # Young's modulus nu = Constant(.3) # Shear modulus (Lamè's second parameter) mu, lmbda = e_var / (2 * (1 + nu)), e_var * nu / ((1 + nu) * (1 - 2 * nu)) # strain energy density, total potential energy psi = (mu / 2) * (ic - 3) - mu * ln(j) + (lmbda / 2) * (ln(j)) ** 2 pi = psi * dx - self.time * dot(self.f, u) * self.ds(3) ff = derivative(pi, u, v) # compute first variation of pi jj = derivative(ff, u, du) # compute jacobian of f # solving if x is not None: numeric_evals = np.zeros(shape=(x.shape[1], len(self.times))) evals = np.zeros(shape=(x.shape[1], len(self.eval_times))) else: numeric_evals = None evals = None for it, t in enumerate(self.times): self.time.t = t self.solver(ff == 0, u, self.bcs, J=jj, bcs=self.bcs, solver_parameters=self.solver_parameters) if x is not None: numeric_evals[:, it] = np.log(np.array([-u(x_)[2] for x_ in x.T]).T) # time-interpolation if x is not None: for i in range(evals.shape[0]): evals[i, :] = np.interp(self.eval_times, self.times, numeric_evals[i, :]) return (evals, u) if x is not None else u
def psi_aux_Borden(F, mu, kappa): J = fe.det(F) C = F.T * F Jinv = J**(-2 / 3) U = 0.5 * kappa * (0.5 * (J**2 - 1) - fe.ln(J)) Wbar = 0.5 * mu * (Jinv * (fe.tr(C) + 1) - 3) return U, Wbar
def CompressibleNeoHookean(Mu, Lambda, Ic, J): Psi = (Mu/2)*(Ic - 3) - Mu*fe.ln(J) + (Lambda/2)*(fe.ln(J))**2 return Psi
def compute_static_deformation(self): assert self.mesh is not None # now we define subdomains on the mesh bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary') top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary') # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7') # Initialize mesh function for interior domains self.domains = fe.MeshFunction('size_t', self.mesh, 3) self.domains.set_all(0) # middle.mark(self.domains, 1) # Initialize mesh function for boundary domains self.boundaries = fe.MeshFunction('size_t', self.mesh, 2) self.boundaries.set_all(0) bottom.mark(self.boundaries, 1) top.mark(self.boundaries, 2) # Define new measures associated with the interior domains and # exterior boundaries self.dx = fe.Measure('dx', domain=self.mesh, subdomain_data=self.domains) self.ds = fe.Measure('ds', domain=self.mesh, subdomain_data=self.boundaries) # define function spaces V = fe.VectorFunctionSpace(self.mesh, "Lagrange", 1) # now we define subdomains on the mesh bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary') top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary') # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7') d = self.mesh.geometry().dim() # Initialize mesh function for interior domains self.domains = fe.MeshFunction('size_t', self.mesh, d) self.domains.set_all(0) # middle.mark(self.domains, 1) # Initialize mesh function for boundary domains self.boundaries = fe.MeshFunction('size_t', self.mesh, d - 1) self.boundaries.set_all(0) bottom.mark(self.boundaries, 1) top.mark(self.boundaries, 2) # Define new measures associated with the interior domains and # exterior boundaries self.dx = fe.Measure('dx', domain=self.mesh, subdomain_data=self.domains) self.ds = fe.Measure('ds', domain=self.mesh, subdomain_data=self.boundaries) c_zero = fe.Constant((0, 0, 0)) # define boundary conditions bc_bottom = fe.DirichletBC(V, c_zero, bottom) bc_top = fe.DirichletBC(V, c_zero, top) bcs = [bc_bottom] # , bc_top] # define functions du = TrialFunction(V) v = TestFunction(V) u = Function(V) B = fe.Constant((0., 2.0, 0.)) T = fe.Constant((0.0, 0.0, 0.0)) d = u.geometric_dimension() I = fe.Identity(d) F = I + grad(u) C = F.T * F I_1 = tr(C) J = det(F) E, mu = 10., 0.3 mu, lmbda = fe.Constant(E / (2 * (1 + mu))), fe.Constant( E * mu / ((1 + mu) * (1 - 2 * mu))) # stored energy (comp. neo-hookean model) psi = (mu / 2.) * (I_1 - 3) - mu * fe.ln(J) + (lmbda / 2.) * (fe.ln(J))**2 dx = self.dx ds = self.ds Pi = psi * fe.dx - dot(B, u) * fe.dx - dot(T, u) * fe.ds F = fe.derivative(Pi, u, v) J = fe.derivative(F, u, du) fe.solve(F == 0, u, bcs, J=J) # save results self.u = u # write to disk output = fe.File("/tmp/static.pvd") output << u
def Vfunc(U): return -params['beta']*fe.ln(U + params['alpha'])