@cdaversin Hi, I am grateful that you pointed out my mistake. Referring to Cohesive zone modelling of debonding and bulk fracture, dS
is used to compute the cohesive force through the jumping displacement of elements.
However, the algorithm in the above example is suitable for using cohesive force models globally, but in practical applications, it usually only needs to be added at some places, otherwise it will damage the overall continuity (so that the Phase Field or other algorithms cannot work) and cause errors. My goal is to compress the model of the above example into the interface
area of my model, and I think that is one of the relatively convenient methods to achieve local addition of cohesive forces using FENICS.
Returning to the topic, it still cannot work after being fixed as you said. So if I don’t consider the impact of dS
as following, the program, which is reduced to a basic elastic stress-strain problem, can work but cannot iterate correctly with lots of nan
. I not sure if matrix and interface displacements of u_m
and u_i
are connected at their boundaries, If not, the ‘u’ value is not transmitted at the boundary between matrix and interface.
Eu_interface_CZM = inner(sigma(u_i), eps(u_i_test)) * dx_i
If I consider ‘dS’, the program will crash, possibly due to the u_i
don’t have the value. Here is the complete example code.
from fenics import * # version: 2019.2.0.64.dev0
import numpy as np
import matplotlib.pyplot as plt
# Generate mesh
mesh = UnitSquareMesh(10, 10)
mesh_dom = MeshFunction('size_t', mesh, mesh.topology().dim())
# SubMesh
class Interface_SubDomain(SubDomain):
def inside(self, x, on_boundary):
return between(x[1], (0.4, 0.6))
mesh_dom.set_all(0)
Interface_SubDomain().mark(mesh_dom, 1)
Matrix_SubMesh = MeshView.create(mesh_dom, 0)
Interface_SubMesh = MeshView.create(mesh_dom, 1)
# Functionspace that 'CG' on matrix and 'DG' on interface
U_matrix = VectorFunctionSpace(Matrix_SubMesh, 'CG', 1)
U_interface = VectorFunctionSpace(Interface_SubMesh, 'DG', 1)
facet_interface = MeshFunction('size_t', Interface_SubMesh, Interface_SubMesh.topology().dim() - 1)
U_Mix = MixedFunctionSpace(U_matrix, U_interface)
# Boundary conditions
def top_boundary(x, on_boundary):
return on_boundary and near(x[1], 1)
def bottom_boundary(x, on_boundary):
return on_boundary and near(x[1], 0)
bc_top = DirichletBC(U_Mix.sub_space(0), (0.0, 0.1), top_boundary)
bc_bottom = DirichletBC(U_Mix.sub_space(0), (0.0, 0.0), bottom_boundary)
bcs = [bc_top, bc_bottom]
dx_m = Measure("dx", domain=Matrix_SubMesh)
dx_i = Measure("dx", domain=Interface_SubMesh)
dS_i = Measure("dS", domain=Interface_SubMesh, subdomain_data=facet_interface, metadata={"quadrature_degree": 2})
# functions
(u_m_test, u_i_test) = TestFunctions(U_Mix)
(u_i_trial, u_i_trial) = TrialFunctions(U_Mix)
u_mix = Function(U_Mix)
u_m, u_i = u_mix.sub(0), u_mix.sub(1)
# Material properties
E = 9.6e6
nu = 0.2
lamda = E*nu/(1+nu)/(1-2*nu)
mu = E/2/(1+nu)
# strain and stress
def eps(u):
return sym(grad(u))
def sigma(u):
return lamda * tr(eps(u)) * Identity(u.geometric_dimension()) + 2 * mu * eps(u)
# Phase-field for the matrix
def Omega_func(d=0):
# Here is the algorithm for the phase-field
return Constant(1.0)
# Cohesive zone modelling for the interface
def T_czm(delta_u):
# Here is the algorithm for the CZM
D, K = 0, 99999
return (1 - D) * K * delta_u
Eu_matrix_PhaseField = inner(Omega_func() * sigma(u_m), eps(u_m_test)) * dx_m
# Eu_interface_CZM = inner(sigma(u_i), eps(u_i_test)) * dx_i + inner(T_czm(jump(u_i)), jump(u_i_test)) * dS_i
Eu_interface_CZM = inner(sigma(u_i), eps(u_i_test)) * dx_i
Eu = Eu_matrix_PhaseField + Eu_interface_CZM
Jacobian = []
Eu_blocks = extract_blocks(Eu)
for Li in Eu_blocks:
for ui in u_mix.split():
block_d = derivative(Li, ui)
Jacobian.append(block_d)
problem_u = MixedNonlinearVariationalProblem(Eu_blocks, u_mix.split(), bcs, J=Jacobian)
solver_u = MixedNonlinearVariationalSolver(problem_u)
solver_u.solve()
Thanks for your help.
Regards.