Following bending-of-the-simply-supported-beam I renewed efforts to adapt compute_cell_contributions to my FEniCSx 1D cantilever beam under point load.
Thank you for this already.
Now there is this error I don’t manage to get through :
cells, basis_values = compute_cell_contributions(V, point_load_position)
says :
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-26-03019a981a3c> in <cell line: 13>()
11
12 # Compute the contributions to the right-hand side from the point source
---> 13 cells, basis_values = compute_cell_contributions(V, point_load_position)
14 for cell, basis_value in zip(cells, basis_values):
15 dofs = V.dofmap.cell_dofs(cell)
<ipython-input-6-eb0dc5d80503> in compute_cell_contributions(V, points)
13 """
14 mesh = V.mesh
---> 15 _, _, owning_points, cells = dolfinx.cpp.geometry.determine_point_ownership(
16 mesh._cpp_object, points, 1e-6)
17 owning_points = np.asarray(owning_points).reshape(-1, 3)
TypeError: cannot unpack non-iterable PointOwnershipData_float64 object
Could you please help me through ?
The full code goes like :
# From :
# Create a point source for Poisson problem
# Author: Jørgen S. Dokken
# SPDX-License-Identifier: MIT
import os
arch = os.getenv("ARGS", "real")
try:
import google.colab # noqa: F401
except ImportError:
import ufl
import dolfinx
else:
try:
import ufl
import dolfinx
except ImportError:
if arch != "complex":
!wget "https://fem-on-colab.github.io/releases/fenicsx-install-real.sh" -O "/tmp/fenicsx-install.sh" && bash "/tmp/fenicsx-install.sh"
else:
!wget "https://fem-on-colab.github.io/releases/fenicsx-install-complex.sh" -O "/tmp/fenicsx-install.sh" && bash "/tmp/fenicsx-install.sh"
import ufl
import dolfinx
# Install meshio for mesh handling
!pip install meshio
import numpy as np
from mpi4py import MPI
from petsc4py import PETSc
import dolfinx
import dolfinx.fem.petsc
import dolfinx.io
import ufl
import meshio
from dolfinx import fem
def compute_cell_contributions(V, points):
"""
Determine the cells that contain the specified points and compute the basis
function values at those points.
Args:
V (FunctionSpace): The finite element function space.
points (np.array): Array of points to be evaluated.
Returns:
cells (np.array): Array of cell indices containing the points.
basis_values (np.array): Array of basis function values at the points.
"""
mesh = V.mesh
_, _, owning_points, cells = dolfinx.cpp.geometry.determine_point_ownership(
mesh._cpp_object, points, 1e-6)
owning_points = np.asarray(owning_points).reshape(-1, 3)
mesh_nodes = mesh.geometry.x
cmap = mesh.geometry.cmaps[0]
ref_x = np.zeros((len(cells), mesh.geometry.dim), dtype=mesh.geometry.x.dtype)
for i, (point, cell) in enumerate(zip(owning_points, cells)):
geom_dofs = mesh.geometry.dofmap[cell]
ref_x[i] = cmap.pull_back(point.reshape(-1, 3), mesh_nodes[geom_dofs])
u = ufl.TrialFunction(V)
num_dofs = V.dofmap.dof_layout.num_dofs * V.dofmap.bs
if len(cells) > 0:
expr = dolfinx.fem.Expression(u, ref_x, comm=MPI.COMM_SELF)
values = expr.eval(mesh, np.asarray(cells, dtype=np.int32))
basis_values = values[:num_dofs:num_dofs*len(cells)]
else:
basis_values = np.zeros((0, num_dofs), dtype=dolfinx.default_scalar_type)
return cells, basis_values
# Create a 1D mesh for the cantilever beam in 3D space using meshio
length = 10.0
N = 10 # Number of elements
points = np.zeros((N+1, 3)) # N+1 array of zeros in 3D space
points[:, 0] = np.linspace(0, length, N+1) # Distribute points along x from 0 to 'length'
cells = np.array([[i, i+1] for i in range(N)]) # Line elements connectivity
meshio.write("mesh.xdmf", meshio.Mesh(points, {"line": cells})) # Write XDMF mesh file
# Reading the mesh from the XDMF file
with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mesh.xdmf", "r") as xdmf:
domain = xdmf.read_mesh(name="Grid")
# Get the geometrical and topological dimensions of the mesh from the 'domain' object.
gdim = domain.geometry.dim # = 3
tdim = domain.topology.dim # = 1
# Define the function space
# V = dolfinx.fem.FunctionSpace(domain, ("Lagrange", 1))
V = fem.functionspace(domain,
("Lagrange",
1, # polynomial degree
(gdim,))) # function space dimension
# Define the variational problem
u = ufl.TrialFunction(V) # Displacement (unknown)
v = ufl.TestFunction(V) # Test function
E = 1e7 # Young's modulus
I = 1e-4 # Moment of inertia
A = 1e-2 # Cross-sectional area
# Define the stiffness matrix for a beam in 3D
a = E * I * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx + A * ufl.inner(u, v) * ufl.dx
a_compiled = dolfinx.fem.form(a)
# Apply boundary condition (fixed at the left end)
dofs = dolfinx.fem.locate_dofs_geometrical(V, lambda x: np.isclose(x[0], 0))
zero = dolfinx.fem.Function(V)
zero.x.array[:] = 0
bc = dolfinx.fem.dirichletbc(zero, dofs)
# Initialize the right-hand side vector
b = dolfinx.fem.Function(V)
b.x.array[:] = 0
# Apply the point load at the free end of the beam
if domain.comm.rank == 0:
point_load_position = np.array([[length, 0, 0]],
dtype=domain.geometry.x.dtype)
else:
point_load_position = np.zeros((0, 3), dtype=domain.geometry.x.dtype)
# Compute the contributions to the right-hand side from the point source
cells, basis_values = compute_cell_contributions(V, point_load_position)
#####################
# not tested after this point
for cell, basis_value in zip(cells, basis_values):
dofs = V.dofmap.cell_dofs(cell)
b.x.array[dofs] += basis_value * -1.0 # Applying a negative load
# Apply the boundary conditions to the right-hand side vector
dolfinx.fem.petsc.apply_lifting(b.vector, [a_compiled], [[bc]])
b.x.scatter_reverse(dolfinx.la.InsertMode.add)
dolfinx.fem.petsc.set_bc(b.vector, [bc])
b.x.scatter_forward()
# Assemble the system matrix
A = dolfinx.fem.petsc.assemble_matrix(a_compiled, bcs=[bc])
A.assemble()
# Set up the linear solver
ksp = PETSc.KSP().create(domain.comm)
ksp.setOperators(A)
ksp.setType(PETSc.KSP.Type.PREONLY)
ksp.getPC().setType(PETSc.PC.Type.LU)
ksp.getPC().setFactorSolverType("mumps")
# Solve the linear system
uh = dolfinx.fem.Function(V)
ksp.solve(b.vector, uh.vector)
uh.x.scatter_forward()
# Write the solution to file in VTK format for visualization
with dolfinx.io.VTXWriter(domain.comm, "uh.pvd", [uh], engine="BP4") as bp:
bp.write(0.0)