def get_residual_form(u, v, rho_e, 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: #RAMP stiffness = rho_e / (1 + 8. * (1. - rho_e)) # print('the value of stiffness is:', rho_e.vector().get_local()) # Kinematics k = 3e1 E = k * stiffness nu = 0.3 mu, lmbda = (E / (2 * (1 + nu))), (E * nu / ((1 + nu) * (1 - 2 * nu))) d = len(u) I = df.Identity(d) # Identity tensor F = I + df.grad(u) # Deformation gradient C = F.T * F # Right Cauchy-Green tensor E_ = 0.5 * (C - I) # Green--Lagrange strain S = 2.0 * mu * E_ + lmbda * df.tr(E_) * df.Identity( d) # stress tensor (C:eps) psi = 0.5 * df.inner(S, E_) # 0.5*eps:C:eps # Total potential energy Pi = psi * df.dx # Solve weak problem obtained by differentiating Pi: res = df.derivative(Pi, u, v) return res
def get_residual_form(u, v, rho_e, T, T_hat, KAPPA, k, alpha, mode='plane_stress', method='RAMP', T_r=df.Constant(20.)): if method=='RAMP': p =8 C = rho_e/(1 + p * (1. - rho_e)) else: C = rho_e**3 E = k * C # C is the design variable, its values is from 0 to 1 nu = 0.3 # Poisson's ratio lambda_ = E * nu/(1. + nu)/(1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters if mode == 'plane_stress': lambda_ = 2*mu*lambda_/(lambda_+2*mu) # Th = df.Constant(7) I = df.Identity(len(u)) T_0 = df.Constant(20.) w_ij = 0.5 * (df.grad(u) + df.grad(u).T) - C * alpha * I * (T-T_0) v_ij = 0.5 * (df.grad(v) + df.grad(v).T) d = len(u) sigm = lambda_*df.div(u)*df.Identity(d) + 2*mu*w_ij a = df.inner(sigm, v_ij) * df.dx + \ df.dot(C*KAPPA* df.grad(T), df.grad(T_hat)) * df.dx print("get a-------") return a
def Fa(self): if self.model == ActiveModels.active_stress: return dolfin.Identity(self.dim) f0 = self.f0 f0f0 = dolfin.outer(f0, f0) Id = dolfin.Identity(self.dim) mgamma = 1 - self.activation_field Fa = mgamma * f0f0 + pow(mgamma, -1.0 / float(self.dim - 1)) * (Id - f0f0) return Fa
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 __init__( self, mesh, field, strain_tensor="E", dmu=None, approx="original", F_ref=None, isochoric=True, displacement_space="CG_2", interpolation_space="CG_1", description="", ): ModelObservation.__init__(self, mesh, target_space="R_0", description=description) # Check that the given field is a vector of the same dim as the mesh dim = mesh.geometry().dim() # assert isinstance(field, (dolfin.Function, dolfin.Constant) assert field.ufl_shape[0] == dim approxs = ["project", "interpolate", "original"] msg = 'Expected "approx" for be one of {}, got {}'.format( approxs, approx) self.field = field assert approx in approxs, msg self._approx = approx self._F_ref = F_ref if F_ref is not None else dolfin.Identity(dim) self._isochoric = isochoric tensors = ["gradu", "E", "almansi"] msg = "Expected strain tensor to be one of {}, got {}".format( tensors, strain_tensor) assert strain_tensor in tensors, msg self._tensor = strain_tensor if dmu is None: dmu = dolfin.dx(domain=mesh) assert isinstance(dmu, dolfin.Measure) self._dmu = dmu self._vol = dolfin_adjoint.Constant( dolfin.assemble(dolfin.Constant(1.0) * dmu)) # These spaces are only used if you want to project # or interpolate the displacement before assigning it # Space for interpolating the displacement if needed family, degree = interpolation_space.split("_") self._interpolation_space = dolfin.VectorFunctionSpace( mesh, family, int(degree)) # Displacement space family, degree = displacement_space.split("_") self._displacement_space = dolfin.VectorFunctionSpace( mesh, family, int(degree))
def get_residual_form(u, v, rho_e, E = 1, method='SIMP'): if method =='SIMP': C = rho_e**3 else: C = rho_e/(1 + 8. * (1. - rho_e)) E = 1. * C # C is the design variable, its values is from 0 to 1 nu = 0.3 # Poisson's ratio lambda_ = E * nu/(1. + nu)/(1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters w_ij = 0.5 * (df.grad(u) + df.grad(u).T) v_ij = 0.5 * (df.grad(v) + df.grad(v).T) d = len(u) sigm = lambda_*df.div(u)*df.Identity(d) + 2*mu*w_ij a = df.inner(sigm, v_ij) * df.dx return a
def get_residual_form(u, v, rho_e, Th, k=199.5e9, alpha=15.4e-6): C = rho_e / (1 + 8. * (1. - rho_e)) E = k * C # C is the design variable, its values is from 0 to 1 nu = 0.3 # Poisson's ratio Th = Th - df.Constant(20.) Th = 0. lambda_ = E * nu / (1. + nu) / (1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters # Th = df.Constant(7) w_ij = 0.5 * (df.grad(u) + df.grad(u).T) v_ij = 0.5 * (df.grad(v) + df.grad(v).T) d = len(u) sigm = (lambda_ * df.tr(w_ij) - alpha * (3. * lambda_ + 2. * mu) * Th) * df.Identity(d) + 2 * mu * w_ij a = df.inner(sigm, v_ij) * df.dx return a
def normal_stresses(self): k = self.bc_dict["obstacle"] n = df.FacetNormal(self.mesh) tau = (self.mu * (df.grad(self.u_) + df.grad(self.u_).T) - self.p_ * df.Identity(2)) normal_stresses_x = -df.assemble(df.dot(tau, n)[0] * self.ds_(k)) normal_stresses_y = df.assemble(df.dot(tau, n)[1] * self.ds_(k)) return np.array([normal_stresses_x, normal_stresses_y])
def stf3d3(rank3_3d): r""" Return the symmetric and trace-free part of a 3D 3-tensor. Return the symmetric and trace-free part of a 3D 3-tensor. (dev(sym(.))) Returns the STF part :math:`A_{\langle i j k\rangle}` of a rank-3 tensor :math:`A \in \mathbb{R}^{3 \times 3 \times 3}` [TOR2018]_. .. math:: A_{\langle i j k\rangle}=A_{(i j k)}-\frac{1}{5}\left[A_{(i l l)} \delta_{j k}+A_{(l j l)} \delta_{i k}+A_{(l l k)} \delta_{i j}\right] A gradient :math:`\frac{\partial S_{\langle i j}}{\partial x_{k \rangle}}` of a symmetric 2-tensor :math:`S \in \mathbb{R}^{3 \times 3}` has the deviator [STR2005]_: .. math:: \frac{\partial S_{\langle i j}}{\partial x_{k \rangle}} =& \frac{1}{3}\left( \frac{\partial S_{i j}}{\partial x_{k}} +\frac{\partial S_{i k}}{\partial x_{j}} +\frac{\partial S_{j k}}{\partial x_{i}} \right) -\frac{1}{15} \biggl[ \left( \frac{\partial S_{i r}}{\partial x_{r}} +\frac{\partial S_{i r}}{\partial x_{r}} +\frac{\partial S_{r r}}{\partial x_{i}} \right) \delta_{j k} \\ &+ \left( \frac{\partial S_{j r}}{\partial x_{r}} +\frac{\partial S_{j r}}{\partial x_{r}} +\frac{\partial S_{r r}}{\partial x_{j}} \right) \delta_{i k} +\left( \frac{\partial S_{k r}}{\partial x_{r}} +\frac{\partial S_{k r}}{\partial x_{r}} +\frac{\partial S_{r r}}{\partial x_{k}} \right) \delta_{i j} \biggr] """ i, j, k, L = ufl.indices(4) delta = df.Identity(3) sym_ijk = sym3d3(rank3_3d)[i, j, k] traces_ijk = 1 / 5 * (+sym3d3(rank3_3d)[i, L, L] * delta[j, k] + sym3d3(rank3_3d)[L, j, L] * delta[i, k] + sym3d3(rank3_3d)[L, L, k] * delta[i, j]) tracefree_ijk = sym_ijk - traces_ijk return ufl.as_tensor(tracefree_ijk, (i, j, k))
def molecular_stress_tensor(self, u, p): r"""Define the molecular stress tensor: .. math:: \bar{\pi} = 2\mu\bar{\epsilon}-p\bar{I} :param u: The velocity field. :param p: The pressure field. :return: The molecular stress tensor. """ mu = self._mu.magnitude return 2 * mu * self.strain_rate_tensor(u) - p * dolfin.Identity(3)
def update_vector_field( f0, new_mesh, u=None, name="fiber", normalize=True, regen_fibers=False ): df.parameters["form_compiler"]["representation"] = "quadrature" df.parameters["form_compiler"]["quadrature_degree"] = 4 ufl_elem = f0.function_space().ufl_element() f0_new = df.Function(df.FunctionSpace(new_mesh, ufl_elem), name=name) mpi_size = df.mpi_comm_world().getSize() if regen_fibers and mpi_size == 1: from mesh_generation.generate_mesh import setup_fiber_parameters from mesh_generation.mesh_utils import load_geometry_from_h5, generate_fibers fiber_params = setup_fiber_parameters() fields = generate_fibers(new_mesh, fiber_params) f0_new = fields[0] else: if regen_fibers: msg = ( "Warning fibers can only be regenerated in serial. " + "Use Piola transformation instead.\n" ) logger.warning(msg) if u is not None: f0_mesh = f0.function_space().mesh() u_elm = u.function_space().ufl_element() V = df.FunctionSpace(f0_mesh, u_elm) u0 = df.Function(V) arr = gather_broadcast(u.vector().array()) assign_to_vector(u0.vector(), arr) F = df.grad(u0) + df.Identity(3) f0_updated = df.project(F * f0, f0.function_space()) if normalize: f0_updated = normalize_vector_field(f0_updated) f0_arr = gather_broadcast(f0_updated.vector().array()) assign_to_vector(f0_new.vector(), f0_arr) else: f0_arr = gather_broadcast(f0.vector().array()) assign_to_vector(f0_new.vector(), f0_arr) return f0_new
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 set_parameters(self, mesh, elastic_ratio): assert isinstance(mesh, dlfn.Mesh) self._mesh = mesh self._space_dim = self._mesh.geometry().dim() self._I = dlfn.Identity(self._space_dim) assert isinstance(elastic_ratio, (dlfn.Constant, float)) assert float(elastic_ratio) > 0. self._elastic_ratio = elastic_ratio
def strain_energy(self, F_): F = self.Fe(F_) dim = get_dimesion(F) gradu = F - dolfin.Identity(dim) epsilon = 0.5 * (gradu + gradu.T) W = self.lmbda / 2 * (dolfin.tr(epsilon)**2) + self.mu * dolfin.tr( epsilon * epsilon, ) # Active stress Wactive = self.Wactive(F, diff=0) return W + Wactive
def get_residual_form(u, v, rho_e, T, T_hat, KAPPA, k, alpha, mode='plane_stress', method='RAMP'): if method=='RAMP': C = rho_e/(1 + 8. * (1. - rho_e)) else: C = rho_e**3 E = k * C # C is the design variable, its values is from 0 to 1 nu = 0.3 # Poisson's ratio lambda_ = E * nu/(1. + nu)/(1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters if mode == 'plane_stress': lambda_ = 2*mu*lambda_/(lambda_+2*mu) # Th = df.Constant(7) I = df.Identity(len(u)) # w_ij = 0.5 * (df.grad(u) + df.grad(u).T) - alpha * I * T # change May 23 penalize on alpha T_0 = df.Constant(20) w_ij = 0.5 * (df.grad(u) + df.grad(u).T) - C*alpha * I * (T-T_0) v_ij = 0.5 * (df.grad(v) + df.grad(v).T) d = len(u) # kappa = alpha*(2*mu + 3*lambda_) sigm = lambda_*df.div(u)*df.Identity(d) + 2*mu*w_ij # eps_u = df.sym(df.grad(u)) # sigm = (lambda_*df.tr(eps_u)-kappa*T)*df.Identity(d) + 2*mu*eps_u a = df.inner(sigm, v_ij) * df.dx + \ df.dot(C*KAPPA* df.grad(T-T_0), df.grad(T_hat)) * df.dx print("get a-------") return a
def get_residual_form(u, v, rho_e, phi_angle, k, alpha, method='RAMP', Th=df.Constant(1.)): if method == 'SIMP': C = rho_e**3 else: C = rho_e / (1 + 8. * (1. - rho_e)) E = k # C is the design variable, its values is from 0 to 1 nu = 0.49 # Poisson's ratio lambda_ = E * nu / (1. + nu) / (1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters # Th = df.Constant(5e1) # Th = df.Constant(1.) # Th = df.Constant(5e0) w_ij = 0.5 * (df.grad(u) + df.grad(u).T) v_ij = 0.5 * (df.grad(v) + df.grad(v).T) S = df.as_matrix([[-2., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) L = df.as_matrix([[df.cos(phi_angle), df.sin(phi_angle), 0.], [-df.sin(phi_angle), df.cos(phi_angle), 0.], [0., 0., 1.]]) alpha_e = alpha * C eps = w_ij - alpha_e * Th * L.T * S * L d = len(u) sigm = lambda_ * df.div(u) * df.Identity(d) + 2 * mu * eps a = df.inner(sigm, v_ij) * df.dx return a
def stress_tensor(self, L, p): """ Return the Cauchy stress tensor for an incompressible Newtonian fluid, namely .. math:: \mathbf{T} = -p\mathbf{I} + 2\mu\\text{Sym}(\mathbf{L}), where :math:`\mathbf{L} = \\text{grad}(\mathbf{v})`, :math:`\mathbf{I}` is the identity tensor, :math:`p` is the hydrostatic pressure, and :math:`\mu` is the dynamic viscosity. Parameters ---------- L : ufl.differentiation.Grad The velocity gradient. p : dolfin.Function, ufl.indexed.Indexed The hydrostatic pressure. Returns ------- T : ufl.algebra.Sum The Cauchy stress tensor defined above. """ params = self._parameters dim = ufl.domain.find_geometric_dimension(L) mu = dlf.Constant(params['mu'], name='mu') I = dlf.Identity(dim) D = dlf.sym(L) return -p * I + dlf.Constant(2.0) * mu * D
def stress_strain(eps, lambda_, mu): I = dolfin.Identity(DIM) return lambda_ * dolfin.tr(eps) * I + 2 * mu * eps
def sigma(self, uu): return 2.*self.mu*self.epsilon(uu) + self.ll*dolfin.tr(self.epsilon(uu))*dolfin.Identity(self.basedim)
h = d/16. atol = 1.e-8 mesh = dolfin.RectangleMesh(dolfin.Point(0., -0.5*d), dolfin.Point(ell, 0.5*d), int(ell/h), int(d/h)) left = dolfin.CompiledSubDomain('on_boundary && x[0] <= atol', atol=atol)#dolfin.plot(mesh) #plt.savefig("mesh.png") # Variational formulation degree = 1 element = dolfin.VectorElement('P', cell="triangle", degree=degree, dim=mesh.geometric_dimension()) V = dolfin.FunctionSpace(mesh, element) u = dolfin.Function(V,name="displacement") u_trial = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) E = 1.0 nu = 0.3 I2 = dolfin.Identity(mesh.geometric_dimension()) mu = dolfin.Constant(E/2./(1.+nu)) lambda_ = dolfin.Constant(E*nu/(1.+nu)/(1.-2.*nu)) def strain_displacement(u): return dolfin.sym(dolfin.grad(u)) def stress_strain(eps): return lambda_*dolfin.tr(eps)*I2+2*mu*eps bilinear_form = dolfin.inner(stress_strain(strain_displacement(u_trial)), strain_displacement(v))*dolfin.dx traction = dolfin.Expression(('x[0] < x_right ? 0.0 : -12.*M/d/d/d*x[1]', '0.0'), x_right=ell-atol, M=1.0, d=d, degree=degree)
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)
def __init__(self, domain, *args, **kwargs): self._domain = domain self.geometric_dimension = self.domain.mesh.ufl_cell( ).geometric_dimension() self.identity_tensor = dolf.Identity(self.geometric_dimension) self._complex_forms_flag = "real"
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
'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)
def sigma(u, p, mu): # Define stress tensor return 2 * mu * epsilon(u) - p * dolfin.Identity(len(u))
bcs.append(DirichletBC(Vx, zero, boundary_markers, id_subdomain_fix)) bcs.append(DirichletBC(Vx, uxD_msr, boundary_markers, id_subdomain_msr)) 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)
def numerical_test( user_parameters ): time_data = [] time_data_pd = [] spacetime = [] lmbda_min_prev = 1e-6 bifurcated = False bifurcation_loads = [] save_current_bifurcation = False bifurcation_loads = [] comm = MPI.comm_world default_parameters = getDefaultParameters() default_parameters.update(user_parameters) parameters = default_parameters parameters['code']['script'] = __file__ signature = hashlib.md5(str(parameters).encode('utf-8')).hexdigest() outdir = '../output/traction/{}-{}CPU'.format(signature, size) Path(outdir).mkdir(parents=True, exist_ok=True) log(LogLevel.INFO, 'Outdir is: '+outdir) BASE_DIR = os.path.dirname(os.path.realpath(__file__)) print(parameters['geometry']) d={'Lx': parameters['geometry']['Lx'],'Ly': parameters['geometry']['Ly'], 'h': parameters['material']['ell']/parameters['geometry']['n']} geom_signature = hashlib.md5(str(d).encode('utf-8')).hexdigest() Lx = parameters['geometry']['Lx'] Ly = parameters['geometry']['Ly'] n = parameters['geometry']['n'] ell = parameters['material']['ell'] fname = os.path.join('../meshes', 'strip-{}'.format(geom_signature)) resolution = max(parameters['geometry']['n'] * Lx / ell, 5/(Ly*10)) resolution = 3 geom = mshr.Rectangle(dolfin.Point(-Lx/2., -Ly/2.), dolfin.Point(Lx/2., Ly/2.)) mesh = mshr.generate_mesh(geom, resolution) log(LogLevel.INFO, 'Number of dofs: {}'.format(mesh.num_vertices()*(1+parameters['general']['dim']))) if size == 1: meshf = dolfin.File(os.path.join(outdir, "mesh.xml")) plot(mesh) plt.savefig(os.path.join(outdir, "mesh.pdf"), bbox_inches='tight') with open(os.path.join(outdir, 'parameters.yaml'), "w") as f: yaml.dump(parameters, f, default_flow_style=False) Lx = parameters['geometry']['Lx'] ell = parameters['material']['ell'] savelag = 1 # Function Spaces V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1) V_alpha = dolfin.FunctionSpace(mesh, "CG", 1) L2 = dolfin.FunctionSpace(mesh, "DG", 0) u = dolfin.Function(V_u, name="Total displacement") u.rename('u', 'u') alpha = Function(V_alpha) alpha_old = dolfin.Function(alpha.function_space()) alpha.rename('alpha', 'alpha') dalpha = TrialFunction(V_alpha) alpha_bif = dolfin.Function(V_alpha) alpha_bif_old = dolfin.Function(V_alpha) state = {'u': u, 'alpha': alpha} Z = dolfin.FunctionSpace(mesh, dolfin.MixedElement([u.ufl_element(),alpha.ufl_element()])) z = dolfin.Function(Z) v, beta = dolfin.split(z) left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx) right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx) bottom = dolfin.CompiledSubDomain("near(x[1],-Ly/2.)", Ly=Ly) top = dolfin.CompiledSubDomain("near(x[1],Ly/2.)", Ly=Ly) left_bottom_pt = dolfin.CompiledSubDomain("near(x[0],-Lx/2.) && near(x[1],-Ly/2.)", Lx=Lx, Ly=Ly) mf = dolfin.MeshFunction("size_t", mesh, 1, 0) right.mark(mf, 1) left.mark(mf, 2) bottom.mark(mf, 3) ut = dolfin.Expression("t", t=0.0, degree=0) bcs_u = [dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left), dolfin.DirichletBC(V_u.sub(0), ut, right), dolfin.DirichletBC(V_u, (0, 0), left_bottom_pt, method="pointwise")] bcs_alpha = [] bcs = {"damage": bcs_alpha, "elastic": bcs_u} ds = dolfin.Measure("ds", subdomain_data=mf) dx = dolfin.Measure("dx", metadata=parameters['compiler'], domain=mesh) ell = parameters['material']['ell'] # ----------------------- # Problem definition k_res = parameters['material']['k_res'] a = (1 - alpha) ** 2. + k_res w_1 = parameters['material']['sigma_D0'] ** 2 / parameters['material']['E'] w = w_1 * alpha eps = sym(grad(u)) eps0t=Expression([['t', 0.],[0.,'t']], t=0., degree=0) lmbda0 = parameters['material']['E'] * parameters['material']['nu'] /(1. - parameters['material']['nu'])**2. mu0 = parameters['material']['E']/ 2. / (1.0 + parameters['material']['nu']) nu = parameters['material']['nu'] sigma0 = lmbda0 * tr(eps)*dolfin.Identity(parameters['general']['dim']) + 2*mu0*eps e1 = Constant((1., 0)) _sigma = ((1 - alpha) ** 2. + k_res)*sigma0 _snn = dolfin.dot(dolfin.dot(_sigma, e1), e1) # ------------------- ell = parameters['material']['ell'] E = parameters['material']['E'] def elastic_energy(u,alpha, E=E, nu=nu, eps0t=eps0t, k_res=k_res): a = (1 - alpha) ** 2. + k_res eps = sym(grad(u)) Wt = a*E*nu/(2*(1-nu**2.)) * tr(eps)**2. \ + a*E/(2.*(1+nu))*(inner(eps, eps)) return Wt * dx def dissipated_energy(alpha,w_1=w_1,ell=ell): return w_1 *( alpha + ell** 2.*inner(grad(alpha), grad(alpha)))*dx def total_energy(u, alpha, k_res=k_res, w_1=w_1, E=E, nu=nu, ell=ell, eps0t=eps0t): elastic_energy_ = elastic_energy(u,alpha, E=E, nu=nu, eps0t=eps0t, k_res=k_res) dissipated_energy_ = dissipated_energy(alpha,w_1=w_1,ell=ell) return elastic_energy_ + dissipated_energy_ def energy_1d(h, perturbation_v=Function(u.function_space()), perturbation_beta=Function(alpha.function_space())): return assemble(total_energy(u + float(h) * perturbation_v, alpha + float(h) * perturbation_beta)) energy = total_energy(u,alpha) def create_output(outdir): file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf")) file_out.parameters["functions_share_mesh"] = True file_out.parameters["flush_output"] = True file_postproc = dolfin.XDMFFile(os.path.join(outdir, "postprocess.xdmf")) file_postproc.parameters["functions_share_mesh"] = True file_postproc.parameters["flush_output"] = True file_eig = dolfin.XDMFFile(os.path.join(outdir, "perturbations.xdmf")) file_eig.parameters["functions_share_mesh"] = True file_eig.parameters["flush_output"] = True file_bif = dolfin.XDMFFile(os.path.join(outdir, "bifurcation.xdmf")) file_bif.parameters["functions_share_mesh"] = True file_bif.parameters["flush_output"] = True file_bif_postproc = dolfin.XDMFFile(os.path.join(outdir, "bifurcation_postproc.xdmf")) file_bif_postproc.parameters["functions_share_mesh"] = True file_bif_postproc.parameters["flush_output"] = True file_ealpha = dolfin.XDMFFile(os.path.join(outdir, "elapha.xdmf")) file_ealpha.parameters["functions_share_mesh"] = True file_ealpha.parameters["flush_output"] = True files = {'output': file_out, 'postproc': file_postproc, 'eigen': file_eig, 'bifurcation': file_bif, 'ealpha': file_ealpha} return files files = create_output(outdir) solver = EquilibriumAM(energy, state, bcs, parameters=parameters) stability = StabilitySolver(energy, state, bcs, parameters = parameters) linesearch = LineSearch(energy, state) load_steps = np.linspace(parameters['loading']['load_min'], parameters['loading']['load_max'], parameters['loading']['n_steps']) tc = (parameters['material']['sigma_D0']/parameters['material']['E'])**(.5) _eps = 1e-3 load_steps = [0., tc-_eps, tc+_eps] time_data = [] time_data_pd = [] bifurcation_loads = [] save_current_bifurcation = False alpha_bif = dolfin.Function(V_alpha) alpha_bif_old = dolfin.Function(V_alpha) bifurcation_loads = [] save_bifurcation = 1 log(LogLevel.INFO, '{}'.format(parameters)) for step, load in enumerate(load_steps): plt.clf() mineigs = [] exhaust_modes = [] log(LogLevel.CRITICAL, '====================== STEPPING ==========================') log(LogLevel.CRITICAL, 'Solving load t = {:.2f}'.format(load)) alpha_old.assign(alpha) ut.t = load (time_data_i, am_iter) = solver.solve() # Second order stability (stable, negev) = stability.solve(solver.damage.problem.lb) log(LogLevel.CRITICAL, 'Current state is{}stable'.format(' ' if stable else ' un')) if stable: solver.update() else: log(LogLevel.INFO, 'About to bifurcate load {:.3f} step {}'.format(load, step)) iteration = 1 mineigs.append(stability.mineig) while stable == False: log(LogLevel.INFO, 'Continuation iteration {}'.format(iteration)) iteration += 1 # plotstep() cont_data_pre = compile_continuation_data(state, energy) opt_mode = 0 perturbation_v = stability.perturbations_v[opt_mode] perturbation_beta = stability.perturbations_beta[opt_mode] (hmin, hmax) = linesearch.admissible_interval(alpha, alpha_old, perturbation_beta) hs = np.linspace(hmin, hmax, 20) energy_vals = np.array([energy_1d(h, perturbation_v, perturbation_beta) for h in hs]) h_opt = hs[np.argmin(energy_vals)] log(LogLevel.INFO, 'Computed h_opt {}'.format(h_opt)) perturbation = {'v': stability.perturbations_v[opt_mode], 'beta': stability.perturbations_beta[opt_mode], 'h': h_opt} perturbState(state, perturbation) (time_data_i, am_iter) = solver.solve(outdir) (stable, negev) = stability.solve(solver.damage.problem.lb) mineigs.append(stability.mineig) log(LogLevel.INFO, 'Continuation iteration {}, current state is{}stable'.format(iteration, ' ' if stable else ' un')) cont_data_post = compile_continuation_data(state, energy) # continuation criterion if abs(np.diff(mineigs)[-1]) > parameters['stability']['cont_rtol']: log(LogLevel.INFO, 'Continuing perturbations') else: log(LogLevel.CRITICAL, 'We are stuck in the matrix') log(LogLevel.WARNING, 'Continuing load program') break solver.update() if save_current_bifurcation: plotPerturbationData() savePerturbationData() save_current_bifurcation = False def compileTimeData(time_data_i, load): time_data_i["load"] = load time_data_i["alpha_max"] = max(alpha.vector()[:]) time_data_i["elastic_energy"] = dolfin.assemble(elastic_energy( u,alpha, E=E, nu=nu, eps0t=eps0t, k_res=k_res)) time_data_i["dissipated_energy"] = dolfin.assemble( (w + w_1 * parameters['material']['ell'] ** 2. * inner(grad(alpha), grad(alpha)))*dx) time_data_i["stable"] = stability.stable time_data_i["# neg ev"] = stability.negev time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf time_data_i["sigma"] = 1/Ly * dolfin.assemble(_snn*ds(1)) log(LogLevel.INFO, "Load/time step {:.4g}: converged in iterations: {:3d}, err_alpha={:.4e}".format( time_data_i["load"], time_data_i["iterations"][0], time_data_i["alpha_error"][0])) return time_data_i time_data.append(compileTimeData(time_data_i, load)) time_data_pd = pd.DataFrame(time_data) def outputData(): np.save(os.path.join(outdir, 'bifurcation_loads'), bifurcation_loads, allow_pickle=True, fix_imports=True) with files['output'] as file: file.write(alpha, load) file.write(u, load) with files['postproc'] as file: file.write_checkpoint(alpha, "alpha-{}".format(step), step, append = True) file.write_checkpoint(u, "u-{}".format(step), step, append = True) log(LogLevel.INFO, 'Written postprocessing step {}'.format(step)) time_data_pd.to_json(os.path.join(outdir, "time_data.json")) outputData() return time_data_pd, outdir
#Define HDG element and function space element_cls = geopart.stokes.incompressible.HDG2() W = element_cls.function_space(mesh) ds = dolfin.Measure('ds', domain=mesh, subdomain_data=boundaries) n = dolfin.FacetNormal(mesh) #Define boundary condition U = element_cls.create_solution_variable(W) p_in = dolfin.Constant(1.0) # pressure inlet p_out = dolfin.Constant(0.0) # pressure outlet noslip = dolfin.Constant([0.0] * mesh.geometry().dim()) # no-slip wall #Boundary conditions gN1 = (-p_out * dolfin.Identity(mesh.geometry().dim())) * n Neumann_outlet = dg.DGNeumannBC(ds(mark["outlet"]), gN1) gN2 = (-p_in * dolfin.Identity(mesh.geometry().dim())) * n Neumann_inlet = dg.DGNeumannBC(ds(mark["inlet"]), gN2) Dirichlet_wall = dg.DGDirichletBC(ds(mark["wall"]), noslip) weak_bcs = [Dirichlet_wall, Neumann_inlet, Neumann_outlet] #Body force term f = dolfin.Constant([0.0] * mesh.geometry().dim()) model = geopart.stokes.StokesModel(eta=mu, f=f) #Form and solve Stokes A, b = dolfin.PETScMatrix(), dolfin.PETScVector() element_cls.solve_stokes(W, U, (A, b), weak_bcs, model) uh, ph = element_cls.get_velocity(U), element_cls.get_pressure(U)
print("Add output-compliance-------") # Add output-compliance to the PDE problem: C = density_function / (1 + 8. * (1. - density_function)) E = K * C # C is the design variable, its values is from 0 to 1 nu = 0.3 # Poisson's ratio # Th = Th - df.Constant(20.) lambda_ = E * nu / (1. + nu) / (1 - 2 * nu) mu = E / 2 / (1 + nu) #lame's parameters lambda_ = 2 * mu * lambda_ / (lambda_ + 2 * mu) # Th = df.Constant(7) I = df.Identity(len(displacements_function)) # w_ij = 0.5 * (df.grad(displacements_function) + df.grad(displacements_function).T) - ALPHA * I * temperature_function # sigm = lambda_*df.div(displacements_function)* I + 2*mu*w_ij # s = sigm - (1./3)*df.tr(sigm)*I # von_Mises = df.sqrt(3./2*df.inner(s, s)) # von_Mises_form = (1/df.CellVolume(mesh)) * von_Mises * df.TestFunction(density_function_space) * df.dx # T = df.TensorFunctionSpace(mesh, "CG", 1) # T.vector.set_local() T_00 = df.Constant(20) w_ij = 0.5 * (df.grad(displacements_function) + df.grad( displacements_function).T) - C * ALPHA * I * (temperature_function - T_00) sigm = lambda_ * df.div(displacements_function) * I + 2 * mu * w_ij s = sigm - (1. / 3) * df.tr(sigm) * I scalar_ = 5e8
def stress(u, p, mu): return 2 * mu * epsilon(u) - p * df.Identity(len(u))