Hello everyone!
I’m quite new to getfem and the field of FEM simulation in general, so sorry in advance if my question is obvious.
I have a problem, where I want to inflate an object inside of another object, say a ball inside a hollow box. The ball shall not be able to penetrate the box, I want to implement a contact problem. I’ve put together this little test script:
import getfem as gf
import numpy as np
VOL = True
mo_sphere = gf.MesherObject('ball', [0.0, 0.0, 1.0], 1.0)
mo_bigbox = gf.MesherObject('rectangle', [-2.0, -2.0, -0.5], [2.0, 2.0, 2.5])
mo_smallbox = gf.MesherObject('rectangle', [-1.0, -1.0, 0.0], [1.0, 1.0, 2.0])
mo_box = gf.MesherObject('set minus', mo_bigbox, mo_smallbox)
m_slave = gf.Mesh('generate', mo_sphere, 0.5)
if VOL:
m_master = gf.Mesh('generate', mo_box, 0.5)
else:
m_master = gf.Mesh('empty', 3)
pts = np.array([
[-2.0, -2.0, -0.5], # 0: Links-Vorne-Unten
[ 2.0, -2.0, -0.5], # 1: Rechts-Vorne-Unten
[ 2.0, 2.0, -0.5], # 2: Rechts-Hinten-Unten
[-2.0, 2.0, -0.5], # 3: Links-Hinten-Unten
[-2.0, -2.0, 2.5], # 4: Links-Vorne-Oben
[ 2.0, -2.0, 2.5], # 5: Rechts-Vorne-Oben
[ 2.0, 2.0, 2.5], # 6: Rechts-Hinten-Oben
[-2.0, 2.0, 2.5] # 7: Links-Hinten-Oben
]).T
triangles = np.array([
[0, 2, 1], [0, 3, 2], # Boden
[4, 5, 6], [4, 6, 7], # Deckel
[0, 1, 5], [0, 5, 4], # Vorne
[1, 2, 6], [1, 6, 5], # Rechts
[2, 3, 7], [2, 7, 6], # Hinten
[3, 0, 4], [3, 4, 7] # Links
], dtype=np.int32)
m_master.add_point(pts)
for t in triangles:
m_master.add_convex(gf.GeoTrans("GT_PK(2,1)"), pts[:, t])
if VOL:
m_master.set_region(MASTER_CONTACT := 1, m_master.outer_faces_in_box([-1.1, -1.1, -0.1], [1.1, 1.1, 2.1]))
else:
m_master.set_region(MASTER_CONTACT := 1, np.vstack([m_master.cvid(), np.full_like(m_master.cvid(), -1)]))
m_slave.set_region(SLAVE_CONTACT := 2, m_slave.outer_faces())
m_slave.set_region(SLAVE_DIRICHLET := 3, m_slave.outer_faces_with_direction([-0.1, -0.1, -0.1], 100))
print(f"MASTER_REGION: {m_master.region(MASTER_CONTACT).shape}")
print(f"SLAVE_REGION: {m_slave.region(SLAVE_CONTACT).shape}")
print(f"SLAVE_DIRICHLET: {m_slave.region(SLAVE_DIRICHLET).shape}")
mim_slave = gf.MeshIm(m_slave, 4)
mim_master = gf.MeshIm(m_master, 4)
mf_slave = gf.MeshFem(m_slave, 3)
mf_master = gf.MeshFem(m_master, 3)
mf_slave.set_classical_fem(1)
mf_master.set_classical_fem(1)
mf_debug = gf.MeshFem(m_master, 1)
mf_debug.set_classical_fem(1)
region_mask = np.zeros(mf_debug.nb_basic_dof())
dofs_on_box = mf_debug.basic_dof_on_region(MASTER_CONTACT)
region_mask[dofs_on_box] = 1.0
mf_master.export_to_vtk("master_mesh.vtk", mf_debug, region_mask, "RegionMarker")
mf_debug = gf.MeshFem(m_slave, 1)
mf_debug.set_classical_fem(1)
region_mask = np.zeros(mf_debug.nb_basic_dof())
dofs_on_box = mf_debug.basic_dof_on_region(SLAVE_CONTACT)
region_mask[dofs_on_box] = 1.0
mf_debug2 = gf.MeshFem(m_slave, 1)
mf_debug2.set_classical_fem(1)
region_mask2 = np.zeros(mf_debug2.nb_basic_dof())
dofs_on_box2 = mf_debug2.basic_dof_on_region(SLAVE_DIRICHLET)
region_mask2[dofs_on_box2] = 1.0
mf_slave.export_to_vtk("slave_mesh.vtk", mf_debug, region_mask, "RegionMarker", mf_debug2, region_mask2, "DirichletMarker")
md = gf.Model("real")
md.add_initialized_data("pressure", 3.0)
md.add_initialized_data("lambda", [1])
md.add_initialized_data("mu", [1])
md.add_initialized_data("r", 1)
md.add_initialized_data("alpha", 1)
md.add_initialized_data("f", 0)
md.add_fem_variable("ub", mf_slave)
md.add_filtered_fem_variable("uq", mf_master, MASTER_CONTACT)
md.add_filtered_fem_variable("egkdsfhgldfskjghlambda", mf_slave, SLAVE_CONTACT)
md.add_isotropic_linearized_elasticity_brick(mim_slave, "ub", "lambda", "mu")
md.add_source_term_brick(mim_slave, "ub", f"pressure * Normal", SLAVE_CONTACT)
md.add_Dirichlet_condition_with_multipliers(mim_slave, "ub", 1, SLAVE_DIRICHLET)
md.add_Dirichlet_condition_with_multipliers(mim_master, "uq", 1, MASTER_CONTACT)
ind = md.add_integral_large_sliding_contact_brick_raytracing("r", 5, "f", "alpha", 0)
md.add_master_contact_boundary_to_large_sliding_contact_brick(ind, mim_master, MASTER_CONTACT, "uq")
md.add_slave_contact_boundary_to_large_sliding_contact_brick(ind, mim_slave, SLAVE_CONTACT, "ub", "egkdsfhgldfskjghlambda")
md.solve("noisy", "max_iter", 500, "max_res", 1E-8)
ub = md.variable("ub")
mf_slave.export_to_vtk("displacement.vtk", ub, "ub")
This works, as long as VOL is set to True. With VOL set to true, the box containing the ball is volumetric, and I use only the inner box surface for the contact problem, found by outer_faces_in_box(). However, in the original problem, my outer boundary is a surface mesh. It is inconvenient to volumetrize the surface, just to able to find an inner surface with outer_faces_in_box(). I figured, it thought be possible to do the contact problem surface mesh directly. However this fails:
Trace 2 in getfem_models.cc, line 4399: Mass term assembly for Dirichlet condition
Trace 2 in getfem_models.cc, line 4399: Mass term assembly for Dirichlet condition
Trace 2 in getfem_models.cc, line 6051: Linearized isotropic elasticity: generic matrix assembly
Trace 2 in getfem_models.cc, line 3308: Generic source term assembly
Trace 2 in getfem_models.cc, line 3319: Source term: generic source term assembly
Trace 2 in getfem_models.cc, line 4399: Mass term assembly for Dirichlet condition
Trace 2 in getfem_models.cc, line 4399: Mass term assembly for Dirichlet condition
Trace 2 in getfem_models.cc, line 2652: Global generic assembly RHS
[1] 16857 segmentation fault (core dumped) python ./problem_demo.py
My question is now: Am I doing something wrong? If yes, what? Or is the contact brick not build for this application, is it not even possible?
Thanks in advance, I appreciate every help!
P.S.:
I’m aware of the fact that the Lame constants for my material don’t make any sense, this was simply not my focus yet.
P.P.S:
The mesh generation for the volumetric mesh sometimes fails and sometimes works, with different error messages, either:
QH6019 qhull input error (qh_scalelast): can not scale last coordinate to [ 0, 0]. Input is cocircular or cospherical. Use option ‘Qz’ to add a point at infinity.
While executing: | qhull QJ d Qbb Pp T0
Options selected for Qhull 2020.2.r 2020/08/31:
run-id 2054137973 delaunay Qbbound-last Pprecision-ignore Pgood _run 1
QJoggle 6e-11 _joggle-seed 16807 _maxoutside 0
logic_error exception caught
Traceback (most recent call last):
File “/home/..././problem_demo.py”, line 13, in
m_master = gf.Mesh(‘generate’, mo_box, 0.5)
File “/home/.../getfem-5.4.4/.venv/lib/python3.13/site-packages/getfem/getfem.py”, line 1164, in init
generic_constructor(self,‘mesh’,*args)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
File “/home/.../getfem-5.4.4/.venv/lib/python3.13/site-packages/getfem/getfem.py”, line 65, in generic_constructor
self.id = getfem_from_constructor(clname,*args)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
RuntimeError: (Getfem::InterfaceError) – Error in gmm/gmm_dense_qr.h, line 786 void gmm::symmetric_qr_algorithm(const MAT1&, const VECT&, const MAT2&, typename number_traits<typename linalg_traits::value_type>::magnitude_type, bool) [with MAT1 = dense_matrix; VECT = std::vector; MAT2 = dense_matrix; typename number_traits<typename linalg_traits::value_type>::magnitude_type = double; typename linalg_traits::value_type = double]:
QR algorithm failed.
or:
python: bgeot_kdtree.cc:115: std::unique_ptr<bgeot::kdtree_elt_base> bgeot::build_tree_(ITER, ITER, unsigned int): Assertion `(itmedian).n[dir] >= median && median >= ((itmedian-1)).n[dir]’ failed.
[1] 18907 IOT instruction (core dumped) python ./problem_demo.py
I don’t know if I have done something wrong or whether this is an issue. But as it succeeds sometimes, I can test, and I don’t have to use the mesh generator later, so it’s not a concern for me now.
