18
19
# You should have received a copy of the GNU Lesser General Public License
19
20
# along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
21
# Modified by Anders Logg 2008-2011
23
# First added: 2007-11-14
24
# Last changed: 2011-06-28
22
from __future__ import print_function
26
23
from dolfin import *
26
if not has_linear_algebra_backend("PETSc"):
27
print("DOLFIN has not been configured with PETSc. Exiting.")
30
# Set backend to PETSC
31
parameters["linear_algebra_backend"] = "PETSc"
33
def build_nullspace(V, x):
34
"""Function to build null space for 3D elasticity"""
36
# Create list of vectors for null space
37
nullspace_basis = [x.copy() for i in range(6)]
39
# Build translational null space basis
40
V.sub(0).dofmap().set(nullspace_basis[0], 1.0);
41
V.sub(1).dofmap().set(nullspace_basis[1], 1.0);
42
V.sub(2).dofmap().set(nullspace_basis[2], 1.0);
44
# Build rotational null space basis
45
V.sub(0).dofmap().set_x(nullspace_basis[3], -1.0, 1, V.mesh());
46
V.sub(1).dofmap().set_x(nullspace_basis[3], 1.0, 0, V.mesh());
47
V.sub(0).dofmap().set_x(nullspace_basis[4], 1.0, 2, V.mesh());
48
V.sub(2).dofmap().set_x(nullspace_basis[4], -1.0, 0, V.mesh());
49
V.sub(2).dofmap().set_x(nullspace_basis[5], 1.0, 1, V.mesh());
50
V.sub(1).dofmap().set_x(nullspace_basis[5], -1.0, 2, V.mesh());
52
for x in nullspace_basis:
55
return VectorSpaceBasis(nullspace_basis)
28
58
# Load mesh and define function space
29
mesh = Mesh("../gear.xml.gz")
31
V = VectorFunctionSpace(mesh, "CG", 1)
33
# Sub domain for clamp at left end
34
def left(x, on_boundary):
35
return x[0] < 0.5 and on_boundary
37
# Dirichlet boundary condition for rotation at right end
38
class Rotation(Expression):
40
def eval(self, values, x):
46
# Angle of rotation (30 degrees)
50
y = y0 + (x[1] - y0)*cos(theta) - (x[2] - z0)*sin(theta)
51
z = z0 + (x[1] - y0)*sin(theta) + (x[2] - z0)*cos(theta)
58
def value_shape(self):
61
# Sub domain for rotation at right end
62
def right(x, on_boundary):
63
return x[0] > 0.9 and on_boundary
59
mesh = Mesh("../pulley.xml.gz")
61
# Function to mark inner surface of pulley
62
def inner_surface(x, on_boundary):
64
return (x[0]*x[0] + x[1]*x[1]) < r*r and on_boundary
66
# Rotation rate and mass density
70
# Loading due to centripetal acceleration (rho*omega^2*x_i)
71
f = Expression(("rho*omega*omega*x[0]", \
72
"rho*omega*omega*x[1]", \
73
"0.0"), omega=omega, rho=rho)
75
# Elasticity parameters
78
mu = E/(2.0*(1.0 + nu))
79
lmbda = E*nu/((1.0 + nu)*(1.0 - 2.0*nu))
83
gdim = v.geometric_dimension()
84
return 2.0*mu*sym(grad(v)) + lmbda*tr(sym(grad(v)))*Identity(gdim)
86
# Create function space
87
V = VectorFunctionSpace(mesh, "Lagrange", 1)
65
89
# Define variational problem
66
90
u = TrialFunction(V)
67
91
v = TestFunction(V)
68
f = Constant((0.0, 0.0, 0.0))
73
mu = E / (2.0*(1.0 + nu))
74
lmbda = E*nu / ((1.0 + nu)*(1.0 - 2.0*nu))
77
return 2.0*mu*sym(grad(v)) + lmbda*tr(sym(grad(v)))*Identity(v.geometric_dimension())
79
92
a = inner(sigma(u), grad(v))*dx
82
# Set up boundary condition at left end
95
# Set up boundary condition on inner surface
83
96
c = Constant((0.0, 0.0, 0.0))
84
bcl = DirichletBC(V, c, left)
86
# Set up boundary condition at right end
88
bcr = DirichletBC(V, r, right)
90
# Set up boundary conditions
97
bc = DirichletBC(V, c, inner_surface)
99
# Assemble system, applying boundary conditions and preserving
101
A, b = assemble_system(a, L, bc)
103
# Create solution function
106
# Create near null space basis (required for smoothed aggregation
107
# AMG). The solution vector is passed so that it can be copied to
108
# generate compatible vectors for the nullspace.
109
null_space = build_nullspace(V, u.vector())
111
# Create PETSC smoothed aggregation AMG preconditioner and attach near
113
pc = PETScPreconditioner("petsc_amg")
114
pc.set_nullspace(null_space)
116
# Create CG Krylov solver and turn convergence monitoring on
117
solver = PETScKrylovSolver("cg", pc)
118
solver.parameters["monitor_convergence"] = True
120
# Set matrix operator
121
solver.set_operator(A);
93
123
# Compute solution
95
solve(a == L, u, bcs, solver_parameters={"symmetric": True})
124
solver.solve(u.vector(), b);
97
126
# Save solution to VTK format
98
127
File("elasticity.pvd", "compressed") << u