123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- #!/usr/bin/env python3
- """An initial circle is stretched by means of a variable force into its final shape.
- Colored lines are the trajectories of a few initial points."""
- from dolfin import *
- from mshr import *
- import numpy as np
- import vedo
- from vedo.dolfin import plot
- set_log_level(30)
- class AllBoundaries(SubDomain):
- def inside(self, x, on_boundary):
- return on_boundary and x[0]<-10
- def solve_problem(mesh, mfunc, force):
- V = VectorFunctionSpace(mesh, "CG", 1)
- u = TrialFunction(V)
- v = TestFunction(V)
- displacement = Function(V)
- bc = [DirichletBC(V, Constant((0,0)), mfunc, 1)]
- F = Constant(force)
- E = Constant(5000)
- nu = Constant(0.3)
- mu = E / (2.0*(1+nu))
- lmbda = E * nu / ((1.0+nu) * (1.0-2*nu))
- sigma = 2.0 * mu * sym(grad(u)) + lmbda * tr( sym(grad(u)) ) * Identity(2)
- solve(inner(sigma, grad(v)) * dx == inner(F, v) * dx, displacement, bc)
- displacement.set_allow_extrapolation(True)
- return displacement
- def update(mesh, displacement):
- new_mesh = Mesh(mesh)
- ALE.move(new_mesh, displacement)
- return new_mesh
- def remesh(mesh, res=50):
- if isinstance(mesh, vedo.Mesh):
- vmesh = mesh
- else:
- vmesh = vedo.Mesh([mesh.coordinates(), mesh.cells()])
- bpts = vmesh.computeNormals(cells=True).boundaries().join(reset=1) #extract boundary
- vz = vmesh.celldata["Normals"][0][2] # check z component of normals at first point
- bpts.generate_mesh(invert=vz<0).smooth().write('tmpmesh.xml') #vedo REMESHING + smoothing
- return Mesh("tmpmesh.xml")
- #################################################################################
- N = 40 # number of iterations of stretching
- res = 15 # resolution of meshes
- do_remesh = False # grab the boundary and remesh the interior at each iteration
- vedo.settings.use_parallel_projection = True # avoid perspective parallax
- circle = Circle(Point(0, 0), 50)
- mesh = generate_mesh(circle, res)
- meshes = [mesh]
- displacements = []
- for i in range(N):
- mfunc = MeshFunction('size_t', mesh, 1, mesh.domains())
- mfunc.set_all(0)
- allb = AllBoundaries()
- allb.mark(mfunc, 1)
- F = np.array([2, (i-N/2)/N]) # some variable force
- displacement = solve_problem(mesh, mfunc, F)
- new_mesh = update(mesh, displacement)
- if do_remesh:
- mesh = remesh(new_mesh)
- else:
- mesh = new_mesh
- meshes.append(mesh)
- displacements.append(displacement)
- dmesh_i = meshes[0] # initial mesh
- dmesh_f = meshes[-1] # final mesh
- vmesh_i = vedo.Mesh([dmesh_i.coordinates(), dmesh_i.cells()], c='grey5').z(-1)
- vmesh_f = vedo.Mesh([dmesh_f.coordinates(), dmesh_f.cells()], c='grey3').wireframe()
- plt = vedo.Plotter()
- # move a few points along the deformation of the circle
- seeds = vedo.Circle(r=50, res=res).vertices[:,(0,1)] # make points 2d with [:,(0,1)]
- endpoints = []
- for i, p in enumerate(seeds):
- line = [p]
- for u in displacements:
- p = p + u(p)
- line.append(p)
- plt += vedo.Line(line, c=i, lw=4).z(1)
- endpoints.append(p)
- plt += [vmesh_i, vmesh_f, __doc__]
- plt.show(axes=1)
- # to invert everything and move the end points back in place, check out discussion:
- #https://fenicsproject.discourse.group/t/precision-in-hyperelastic-model/6824/3
|