Good evening, excuse me, I am an engineering student who wants to learn more about finite elements. To do this, I set out to create a small Python code in Colab. The program will solve a Plane Stress problem (2D). I have a formulation, but I am having trouble finding the solution, I can’t use LinearProblem(a, l, bcs=[bc])
. Here’s part of the code:
# Define the function space
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 2, (mesh.geometry.dim,)))
# Create the zero vertical displacement constraint at the interface
zero = dolfinx.fem.Function(V)
with zero.vector.localForm() as loc:
loc.set(0.0)
# Define trial and test functions
u = TrialFunction(V)
v = TestFunction(V)
# Define stress and strain
def eps(v):
return sym(grad(v))
def sigma(v, lmbda, mu):
return lmbda * tr(eps(v)) * Identity(2) + 2 * mu * eps(v)
# Material properties
E_presa = 24000000 # kN/m^2
nu_presa = 0.2
rho_presa = 22 # kN/m^3
E_suelo = 24000000 # kN/m^2
nu_suelo = 0.2
rho_suelo = 26 # kN/m^3
# Define constants for constitutive relations
lmbda_presa = E_presa * nu_presa / ((1 + nu_presa) * (1 - 2 * nu_presa))
mu_presa = E_presa / (2 * (1 + nu_presa))
lmbda_suelo = E_suelo * nu_suelo / ((1 + nu_suelo) * (1 - 2 * nu_suelo))
mu_suelo = E_suelo / (2 * (1 + nu_suelo))
# Boundary conditions for sliding at the dam-soil interface
def interface_pres_suelo(x):
return np.isclose(x[1], 0) & (x[0] >= 0) & (x[0] <= 40)
# Zero vertical displacement boundary condition
dofs_y = dolfinx.fem.locate_dofs_geometrical((V.sub(1), V), interface_pres_suelo) # Locate dofs in the y direction
bc_vertical = dolfinx.fem.dirichletbc(zero, dofs_y, V.sub(1))
# Clamped boundary conditions on the lateral edges and bottom of the soil
def empotrado(x):
return np.isclose(x[0], -ancho_suelo) | np.isclose(x[0], 40 + ancho_suelo) | np.isclose(x[1], -profundidad_suelo)
# Clamped boundary conditions on the lateral edges and bottom of the soil
dofs_suelo = dolfinx.fem.locate_dofs_geometrical(V, empotrado) # Locate the dofs for clamping
bc_suelo = dolfinx.fem.dirichletbc(zero, dofs_suelo)
# Boundary conditions for hydrostatic pressure on the left face of the dam
x = SpatialCoordinate(mesh)
presion_hidrost = 1000 * 9.81 * (50 - x[1]) # Hydrostatic pressure distribution
# Define the measure ds for boundary terms
ds = Measure('ds', domain=mesh)
# External forces (self-weight of the dam and water)
f_presa = dolfinx.fem.Constant(mesh, (0, -rho_presa * 9.81))
f_suelo = dolfinx.fem.Constant(mesh, (0, -rho_suelo * 9.81))
n = FacetNormal(mesh)
# Variational formulation with boundary conditions
a = inner(sigma(u, lmbda_presa, mu_presa), eps(v)) * dx + inner(sigma(u, lmbda_suelo, mu_suelo), eps(v)) * dx
l = inner(f_presa, v) * dx + inner(f_suelo, v) * dx + dot(presion_hidrost * n, v) * ds
# Solve the problem
problem = dolfinx.fem.LinearProblem(a, l, bcs=[bc])
u_sol = problem.solve()
Seeking an alternative solution, I used another method, but it does not run directly; instead, it restarts the environment. Code:
# Define the function space
V = fem.functionspace(mesh, ("Lagrange", 2, (mesh.geometry.dim,)))
# Create the zero vertical displacement constraint at the interface
zero = fem.Function(V)
with zero.vector.localForm() as loc:
loc.set(0.0)
# Define trial and test functions
u = TrialFunction(V)
v = TestFunction(V)
# Define stress and strain
def eps(v):
return sym(grad(v))
def sigma(v, lmbda, mu):
return lmbda * tr(eps(v)) * Identity(2) + 2 * mu * eps(v)
# Material properties
E_presa = 24000000 # kN/m^2
nu_presa = 0.2
rho_presa = 22 # kN/m^3
E_suelo = 24000000 # kN/m^2
nu_suelo = 0.2
rho_suelo = 26 # kN/m^3
# Define constants for constitutive relations
lmbda_presa = E_presa * nu_presa / ((1 + nu_presa) * (1 - 2 * nu_presa))
mu_presa = E_presa / (2 * (1 + nu_presa))
lmbda_suelo = E_suelo * nu_suelo / ((1 + nu_suelo) * (1 - 2 * nu_suelo))
mu_suelo = E_suelo / (2 * (1 + nu_suelo))
# Boundary conditions for sliding at the dam-soil interface
def interface_pres_suelo(x):
return np.isclose(x[1], 0) & (x[0] >= 0) & (x[0] <= 40)
# Locate DOFs at the interface to set vertical displacement (y direction)
dofs_y = fem.locate_dofs_geometrical(V, interface_pres_suelo)
# Create Dirichlet condition for vertical displacement (y = 0) at the dam-soil interface
bc_vertical = fem.dirichletbc(PETSc.ScalarType((0.0, 0.0)), dofs_y, V)
# Clamped boundary conditions on the lateral edges and bottom of the soil
ancho_suelo = 80 # Extension of the soil on both sides of the dam
profundidad_suelo = 150 # Depth of the soil
def empotrado(x):
return np.isclose(x[0], -ancho_suelo) | np.isclose(x[0], 40 + ancho_suelo) | np.isclose(x[1], -profundidad_suelo)
dofs_suelo = fem.locate_dofs_geometrical(V, empotrado) # Locate the dofs for clamping
bc_suelo = fem.dirichletbc(zero, dofs_suelo)
# Boundary conditions for hydrostatic pressure on the left face of the dam
x = SpatialCoordinate(mesh)
presion_hidrost = 1000 * 9.81 * (50 - x[1]) # Hydrostatic pressure distribution
# Define the measure ds for boundary terms
ds = Measure('ds', domain=mesh)
# Define the normal vector for boundary integration
n = FacetNormal(mesh)
# External forces (self-weight of the dam and water)
f_presa = fem.Constant(mesh, PETSc.ScalarType((0, -rho_presa * 9.81)))
f_suelo = fem.Constant(mesh, PETSc.ScalarType((0, -rho_suelo * 9.81)))
# Variational formulation with boundary conditions
a = inner(sigma(u, lmbda_presa, mu_presa), eps(v)) * dx + inner(sigma(u, lmbda_suelo, mu_suelo), eps(v)) * dx
l = inner(f_presa, v) * dx + inner(f_suelo, v) * dx + dot(presion_hidrost * n, v) * ds
# Create matrices and vectors for the linear system
A = fem.assemble_matrix(fem.form(a), bcs=[bc_vertical, bc_suelo])
b = fem.assemble_vector(fem.form(l))
# Define the initial solution before applying lifting
u_sol = fem.Function(V)
# Convert `b` to a numpy ndarray for apply_lifting
b_array = b.array
# Apply lifting to the matrix and vector of the system
fem.apply_lifting(b_array, [fem.form(a)], bcs=[[bc_vertical, bc_suelo]], x0=[u_sol.vector.array], scale=1.0,
constants=[], coeffs=[])
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
fem.set_bc(b, [bc_vertical, bc_suelo])
# Solve the linear system using PETSc
solver = PETSc.KSP().create(mesh.comm)
solver.setOperators(A)
solver.setType(PETSc.KSP.Type.PREONLY)
solver.getPC().setType(PETSc.PC.Type.LU)
solver.solve(b, u_sol.vector)
I know it’s a conceptual error. Could you help me with documentation to better understand the problem I’m having and the best way to approach it? Thanks in advance, greetings from Bolivia.
link Colab: Google Colab