dolfinx 0.8.0…
beam_mock.py:
import numpy as np
from mpi4py import MPI
import ufl
from dolfinx import mesh, fem, io, default_scalar_type
from dolfinx.fem.petsc import LinearProblem
L = 120.0 # Beam length in inches
W = 4.0 # Cross-sectional width (and height here; for a square beam)
E = 2e6 # Young's modulus in psi
nu = 0.3 # Poisson's ratio
mu = E / (2 * (1 + nu))
lambda_ = (E * nu) / ((1 + nu) * (1 - 2 * nu))
rho = 30.0 / 12**3 # Density in lb/in^3 (converted from 30 lb/ft^3)
domain = mesh.create_box(MPI.COMM_WORLD,
[np.array([0, 0, 0]), np.array([L, W, W])],
[121, 5, 5],
cell_type=mesh.CellType.hexahedron)
with io.XDMFFile(domain.comm, "beam_mesh.xdmf", "w") as xdmf_file:
xdmf_file.write_mesh(domain)
w = -0.50
w_load = w * L
num_nodes = domain.topology.index_map(domain.topology.dim).size_local
load_per_node = w_load / num_nodes
domain = mesh.create_box(MPI.COMM_WORLD,
[np.array([0, 0, 0]), np.array([L, W, W])],
[121, 5, 5],
cell_type=mesh.CellType.hexahedron)
V = fem.functionspace(domain, ("Lagrange", 1, (domain.geometry.dim, )))
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)
def epsilon(u):
return ufl.sym(ufl.grad(u))
def sigma(u):
return lambda_ * ufl.nabla_div(u) * ufl.Identity(len(u)) + 2 * mu * epsilon(u)
def distribute_load(load_per_node, V):
f = fem.Function(V)
f.x.array[:] = 0.0 # Initialize to zero
for i in range(num_nodes):
f.x.array[i*3 + 2] = load_per_node # Apply load in z-direction, accounting for 3 components per node
return f
f = distribute_load(load_per_node*4, V)
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
a = ufl.inner(sigma(u), epsilon(v)) * ufl.dx
L = ufl.dot(f, v) * ufl.dx + ufl.dot(T, v) * ds
problem = LinearProblem(a, L, bcs=[bc],
petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()
np.savetxt('U.csv', uh.x.array, delimiter=',') # Save only the known DOFs
I=4*4**3/12
max_M = w*120.0**2/2
d_max = (w*120.0**4)/(8*E*I)
print(f'd_max:{d_max}')
print(f'minima: {min(uh.x.array)}')
print(f'max moment:{max_M}')
d_max:-0.30375
minima: -0.27241218582494253
max moment:-3600.0
mesh_dolfinxintegrate.py:
import numpy as np
from mpi4py import MPI
import ufl
from dolfinx import mesh, fem
# Define beam parameters
L = 120.0 # Beam length in inches
W = 4.0 # Cross-sectional width (and height)
E = 2000000.0 # Young's modulus in psi
nu = 0.3 # Poisson's ratio
mu = E / (2 * (1 + nu))
lambda_ = (E * nu) / ((1 + nu) * (1 - 2 * nu))
rho = 30.0 / 12**3 # Density in lb/in^3
domain = mesh.create_box(MPI.COMM_WORLD,
[np.array([0, 0, 0]), np.array([L, W, W])],
[121, 5, 5],
cell_type=mesh.CellType.hexahedron)
V = fem.functionspace(domain, ("Lagrange", 1, (domain.geometry.dim, )))
U_array = np.loadtxt('U.csv', delimiter=',')
u = fem.Function(V)
u.x.array[:] = U_array
def strain(u):
return 0.5 * (ufl.grad(u) + ufl.grad(u).T)
epsilon = strain(u)
def stress(epsilon, mu, lambda_):
return 2 * mu * epsilon + lambda_ * ufl.tr(epsilon) * ufl.Identity(3)
sigma = stress(epsilon, mu, lambda_)
# M_z = - ∫_A y σ_xx dA,
tol = 1e-8
def on_right(x):
return np.isclose(x[0], L, atol=tol)
facet_indices = mesh.locate_entities_boundary(domain, domain.topology.dim - 1, on_right)
num_facets = len(facet_indices)
tags = np.full(num_facets, 1, dtype=np.int32)
facet_tags = mesh.meshtags(domain, domain.topology.dim - 1, facet_indices, tags)
ds = ufl.Measure("ds", domain=domain, subdomain_data=facet_tags)
x_coord = ufl.SpatialCoordinate(domain)
sigma_xx = sigma[0, 0]
Mz_expr = - (x_coord[1] - 2.0) * sigma_xx * ds(1)
Mz = fem.assemble_scalar(fem.form(Mz_expr))
if MPI.COMM_WORLD.rank == 0:
print("Bending moment M_z at x = L is:", Mz)
Bending moment M_z at x = L is: 1.4755737098196857e-11
OK… So far M_z is much to small we should be -3500± inch/lbs of moment…I looked in ParaView to make sure that facet_indices are showing up and they are, so those entail the free end…
Why is M_z so miniscule? Can we get things to more accurately interpolate the situation?