Thank you for the help! Here is the code I’m running now, straight from the tutorial but modified so that u
is a 2nd order Lagrange space:
# Scaled variable
import pyvista
from dolfinx import mesh, fem, plot, io, default_scalar_type
from dolfinx.fem.petsc import LinearProblem
from mpi4py import MPI
import ufl
import numpy as np
L = 1
W = 0.2
mu = 1
rho = 1
delta = W / L
gamma = 0.4 * delta**2
beta = 1.25
lambda_ = beta
g = gamma
domain = mesh.create_box(MPI.COMM_WORLD, [np.array([0, 0, 0]), np.array([L, W, W])],
[20, 6, 6], cell_type=mesh.CellType.hexahedron)
# The 2 here is important!
V = fem.functionspace(domain, ("Lagrange", 2, (domain.geometry.dim, )))
# Boundary Conditions
def clamped_boundary(x):
return np.isclose(x[0], 0)
fdim = domain.topology.dim - 1
boundary_facets = mesh.locate_entities_boundary(domain, fdim, clamped_boundary)
u_D = np.array([0, 0, 0], dtype=default_scalar_type)
bc = fem.dirichletbc(u_D, fem.locate_dofs_topological(
V, fdim, boundary_facets), V)
T = fem.Constant(domain, default_scalar_type((0, 0, 0)))
ds = ufl.Measure("ds", domain=domain)
# Variational formulation
def epsilon(u):
# Equivalent to 0.5*(ufl.nabla_grad(u) + ufl.nabla_grad(u).T)
return ufl.sym(ufl.grad(u))
def sigma(u):
return lambda_ * ufl.nabla_div(u) * ufl.Identity(len(u)) + 2 * mu * epsilon(u)
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
f = fem.Constant(domain, default_scalar_type((0, 0, -rho * g)))
a = ufl.inner(sigma(u), epsilon(v)) * ufl.dx
L = ufl.dot(f, v) * ufl.dx + ufl.dot(T, v) * ds
# Solve
problem = LinearProblem(a, L, bcs=[bc], petsc_options={
"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()
# Visualize the deformation
# pyvista.start_xvfb() Doesn't work when running from terminal on mac
p = pyvista.Plotter()
topology, cell_types, geometry = plot.vtk_mesh(V)
grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
# Attach vector values to grid and warp grid by vector
grid["u"] = uh.x.array.reshape((geometry.shape[0], 3))
actor_0 = p.add_mesh(grid, style="wireframe", color="k")
warped = grid.warp_by_vector("u", factor=1.5)
actor_1 = p.add_mesh(warped, show_edges=True)
p.show_axes()
if not pyvista.OFF_SCREEN:
p.show()
else:
figure_as_array = p.screenshot("deflection.png")
# Stress Computation
s = sigma(uh) - 1. / 3 * ufl.tr(sigma(uh)) * ufl.Identity(len(uh))
von_Mises = ufl.sqrt(3. / 2 * ufl.inner(s, s))
V_von_mises = fem.functionspace(domain, ("DG", 0))
stress_expr = fem.Expression(
von_Mises, V_von_mises.element.interpolation_points())
stresses = fem.Function(V_von_mises)
stresses.interpolate(stress_expr)
# Visualize the stresses
warped.cell_data["VonMises"] = stresses.x.petsc_vec.array
warped.set_active_scalars("VonMises")
p = pyvista.Plotter()
p.add_mesh(warped, show_edges=True)
p.show_axes()
if not pyvista.OFF_SCREEN:
p.show()
else:
stress_figure = p.screenshot(f"stresses.png")
The von mises visualization then looks like this:
Where I added a red square around one of the 2nd order hex elements.
I have tried using V_von_mises = fem.functionspace(domain, ("DG", 1))
but that yields:
Traceback (most recent call last):
File "/Users/matthewferraro/Documents/git/project/backend/linear_elasticity.py", line 91, in <module>
warped.cell_data["VonMises"] = stresses.x.petsc_vec.array
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 247, in __setitem__
self.set_array(value, name=key)
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 609, in set_array
vtk_arr = self._prepare_array(data, name, deep_copy)
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 773, in _prepare_array
raise ValueError(
ValueError: data length of (5760) != required length (720)
And if I try with higher orders in the “DG” family I get the same error but with larger numbers on the left side of the error.
If I try with V_von_mises = fem.functionspace(domain, ("Lagrange", 1))
:
Traceback (most recent call last):
File "/Users/matthewferraro/Documents/git/project/backend/linear_elasticity.py", line 93, in <module>
warped.cell_data["VonMises"] = stresses.x.petsc_vec.array
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 247, in __setitem__
self.set_array(value, name=key)
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 609, in set_array
vtk_arr = self._prepare_array(data, name, deep_copy)
File "/Users/matthewferraro/miniconda3/envs/project/lib/python3.10/site-packages/pyvista/core/datasetattributes.py", line 773, in _prepare_array
raise ValueError(
ValueError: data length of (1029) != required length (720)
You mention that the gradient of u
which is computed in epsilon
may be to blame. How should I modify epsilon
(and/or sigma
) to make it possible to have von mises live in a continuous function space?