Okay, that all seems to work. Thank you.
So if I was to have a more complex geometry of varying H, this expression would no longer be correct for the full beam as the out of plane width would also change and hence, couldn’t simply divide by H. How would I adjust his model for a varying H?
For example,
sparinner = Rectangle(Point(0, 0), Point(5000, 50))
sparouter = Rectangle(Point(5000, 0), Point(10000, 30))
So H0 = 50 and H1 = 30. I’m assuming there must be a way to incorporate this into the traction expression.
And I’ve already adjusted the boundary to,
# Define top boundary for traction
def top(x, on_boundary):
return between(x[1], (25,50)) and on_boundary
facets = MeshFunction('size_t', mesh, 1)
facets.set_all(0)
AutoSubDomain(top).mark(facets, 1)
ds = Measure('ds', subdomain_data = facets)
t = Expression(('0.0', 'x[0] <= 5000 + tol ? ((-5*x[0]+50e3))/H0 : ((-5*x[0]+50e3))/H1'), H0=H0, H1=H1, tol=tol, element = el)
Does this seem correct?
Full code for 2 materials and 2 widths
from dolfin import *
from mshr import *
from ufl import nabla_div
import numpy as np
import matplotlib.pyplot as plt
# Material properties
Le = 10000 # Length mm
H = 50 # Length mm
nu = 0.3 # Poisson's ratio = 0 for plane-stress conditions
model = 'plane_stress'
# Generate spar
sparinner = Rectangle(Point(0, 0), Point(5000, 50))
sparouter = Rectangle(Point(5000, 10), Point(10000, 40))
spar = sparinner + sparouter
mesh = generate_mesh(spar, 10)
# Create finite element function space, V (P2 Elements)
V = VectorFunctionSpace(mesh, 'CG', 2)
# Create two materials of different Young's modulus throughout the beam using expressions
E = [100e9, 50e9]
mu_list = []
for x in E:
mu_list.append(x/2/(1+nu))
lmbda_list = []
for x in E:
lmbda_list.append(x*nu/(1+nu)/(1-2*nu))
lmbdaplane_list = []
for lmbda_value, mu_value in zip(lmbda_list, mu_list):
lmbdaplane_list.append(2*mu_value*lmbda_value/(lmbda_value+2*mu_value))
if model == 'plane_stress':
lmbda_list = lmbdaplane_list
tol = 1E-14
mu0 = mu_list[0]
mu1 = mu_list[1]
mu = Expression('x[0] <= 5000 + tol ? mu0 : mu1' , degree = 0, tol=tol, mu0=mu0, mu1=mu1)
tol = 1E-14
lmbda0 = lmbda_list[0]
lmbda1 = lmbda_list[1]
lmbda = Expression('x[0] <= 5000 + tol ? lmbda0 : lmbda1' , degree = 0, tol=tol, lmbda0=lmbda0, lmbda1=lmbda1)
# Define root boundary condition
def root_boundary(x, on_boundary):
tol = 1e-14
return on_boundary and x[0] < tol
bc = DirichletBC(V, Constant((0, 0)), root_boundary)
# Define top boundary for traction
def top(x, on_boundary):
return between(x[1], (25,50)) and on_boundary
facets = MeshFunction('size_t', mesh, 1)
facets.set_all(0)
AutoSubDomain(top).mark(facets, 1)
ds = Measure('ds', subdomain_data = facets)
# Strain tensor
def eps(v):
return sym(grad(v))
# Stress tensor
def sigma(v):
return lmbda*tr(eps(v))*Identity(2) + 2.0*mu*eps(v)
# Define force distribution
el = V.ufl_element()
H0 = 50
H1 = 30
t = Expression(('0.0', 'x[0] <= 5000 + tol ? ((-5*x[0]+50e3))/H0 : ((-5*x[0]+50e3))/H1'), H0=H0, H1=H1, tol=tol, element = el) # Equation for triangular distributed load with root kN/mm = 50
# Divide by H as traction assumes 3D model
# Define variational problem
u = TrialFunction(V)
d = u.geometric_dimension()
v = TestFunction(V)
f = Constant((0, 0))
a = inner(sigma(u), eps(v))*dx
L = dot(f, v)*dx + dot(t, v)*ds(1)
# Compute solution
u = Function(V)
solve(a == L, u, bc)
plot(u, title='Displacement', mode='displacement')
# Compute magnitude of displacement
V = FunctionSpace(mesh, 'CG', 2)
u_magnitude = sqrt(dot(u, u))
u_magnitude = project(u_magnitude, V)
plot(u_magnitude, 'Displacement magnitude')
print('min/max u:',
u_magnitude.vector().get_local().min(),
u_magnitude.vector().get_local().max())
I’m now considering creating a model with several (say 10) point loads along the beam to represent the force distribution rather than have the expression. Do you have any guidance on where to start with this?
I’ve attempted to use,
# Apply point load at x = L
A, b = assemble_system(a, L, bc)
ps = PointSource(V, Point(10000, 50), 100e3)
ps.apply(b)
to apply a point load of 100kN at the end of the beam. But the resultant deflection is incorrect (for some reason out by a factor of exactly 50). And upon investigation, the point load also needs to be divided by H, does this also assume 3D?