Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7c0a43d
Create .gitignore
chemiskyy Feb 10, 2026
44d6be7
Update __init__.py
chemiskyy Feb 10, 2026
bc94ff0
Add IPC contact assembly and CCD support
chemiskyy Feb 10, 2026
d3a7f81
Update pyproject.toml
chemiskyy Feb 10, 2026
b310847
Docs: Add IPC contact docs and install notes
chemiskyy Feb 10, 2026
7e5dd56
Add contact comparison examples; scale penalty
chemiskyy Feb 11, 2026
3060cbb
Apply 2πr weighting for axisymmetric contact
chemiskyy Feb 11, 2026
f25fd27
Update ipc_contact.py
chemiskyy Feb 11, 2026
733952d
Update importmesh.py
chemiskyy Feb 11, 2026
fe04426
Update non_linear.py
chemiskyy Feb 11, 2026
b7d1561
Update Install.rst
chemiskyy Feb 11, 2026
b34d33c
Preserve Dirichlet BC when scaling steps
chemiskyy Feb 12, 2026
720fae6
Ensure min NR iter and freeze t_fact per increment
chemiskyy Feb 12, 2026
5b96ceb
Update ipc_contact.py
chemiskyy Feb 12, 2026
d68bc40
Update non_linear.py
chemiskyy Feb 12, 2026
95fb81e
Update self_contact.py
chemiskyy Feb 12, 2026
e6a013e
Update ipc_contact.py
chemiskyy Feb 12, 2026
7908769
Improve IPC contact docs and examples
chemiskyy Feb 13, 2026
a1f47f1
Update ipc_contact.py
chemiskyy Feb 13, 2026
3981c53
Add ipctk broad-phase contact search
chemiskyy Feb 13, 2026
38c0e07
Delete gyroid_compression.py
chemiskyy Feb 13, 2026
ae3e512
Update ipc_contact.py
chemiskyy Feb 13, 2026
efc3987
refactor contact pair search
chemiskyy Feb 14, 2026
610bfb7
Update mesh path and add IPC plastic example
chemiskyy Feb 14, 2026
14c9ff1
Add Hertz and Westergaard contact benchmarks
chemiskyy Feb 15, 2026
b125657
CRITICAL: correct an important error for in Problem.get_ext_forces.
pruliere Feb 25, 2026
7650d76
Improve error criterion for nonlinear problems.
pruliere Feb 25, 2026
6368748
remove old commented code and update docstrings
pruliere Feb 25, 2026
e8b19c5
ruff format to pass pre-commit
pruliere Feb 25, 2026
e0a91ed
fix tests that failed after the nr criterion update
pruliere Feb 25, 2026
d327e26
Merge branch 'master' into feature/ICP_contact
pruliere Mar 4, 2026
ed9ccda
ruff format
pruliere Mar 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
93 changes: 72 additions & 21 deletions docs/Install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,80 @@ Minimal installation with pip:

$ pip install fedoo

Full installation with pip with all dependencies:

.. code-block:: none

$ pip install fedoo[all]


The required dependencies that are automatically installed with fedoo are:

* `Numpy <https://numpy.org/>`_

* `Scipy <https://scipy.org/>`_ mainly for sparse matrices.

In addition, the conda package also includes some recommanded dependencies:
* `Scipy <https://scipy.org/>`_ mainly for sparse matrices.

* `Simcoon <https://simcoon.readthedocs.io/en/latest/>`_
In addition, the conda package also includes some recommended dependencies:

* `Simcoon <https://simcoon.readthedocs.io/en/latest/>`_
brings a lot of features (finite strain, non-linear constitutive
laws, ...). Simcoon can be installed using conda or pip.

* `PyVista <https://docs.pyvista.org/version/stable/>`_
for results visulisation and mesh utils.
* `PyVista <https://docs.pyvista.org/version/stable/>`_
for results visualization and mesh utils.

* An efficient sparse matrix solver (pypardiso or petsc4py) depending
on the processor as described below.


It is highly recommanded to also install a fast direct sparse matrix solver
Full pip install
----------------

It is also possible to install fedoo with all recommended dependencies
(sparse solver, plotting, IPC contact) in one line:

.. code-block:: none

$ pip install fedoo[all]

This installs the following optional groups: ``solver``, ``plot``,
``simcoon``, ``test`` and ``ipc``.

``pyvistaqt``, which is required for the viewer, is not included in the all
group. This allows you to choose your preferred Qt binding (``pyqt5``,
``pyqt6`` or ``pyside6``). We recommend installing only one of these to avoid
potential library conflicts.

To enable the viewer, you can install the dependencies explicitly:

.. code-block:: none

$ pip install fedoo[all] pyvistaqt pyqt5

Alternatively, use the ``gui`` install group that includes ``pyvistaqt``
and ``pyside6``:

.. code-block:: none

$ pip install fedoo[all, gui]


Individual optional groups
--------------------------

You can also install optional groups individually:

.. code-block:: none

$ pip install fedoo[solver] # fast sparse solver (pypardiso or umfpack)
$ pip install fedoo[plot] # matplotlib + pyvista
$ pip install fedoo[simcoon] # simcoon
$ pip install fedoo[ipc] # IPC contact (ipctk)
$ pip install fedoo[gui] # pyvistaqt + pyside6


Sparse solvers
--------------

It is highly recommended to install a fast direct sparse matrix solver
to improve performances:

* `Pypardiso <https://pypi.org/project/pypardiso/>`_
* `Pypardiso <https://pypi.org/project/pypardiso/>`_
for intel processors (binding to the pardiso solver)

* `Petsc4Py <https://pypi.org/project/petsc4py/>`_
mainly compatible with linux or macos including the MUMPS solver.

Expand All @@ -53,11 +95,20 @@ to improve performances:
To be able to launch the fedoo viewer, the module
`pyvistaqt <https://qtdocs.pyvista.org/>`_ is also required.

As mentioned earlier, a lot of features (finite strain, non-linear
constitutive laws, ...) requires the installation of simcoon. Simcoon can
be installed from pip or conda. To install simcoon using conda:

Simcoon
-------

Many features (such as finite strain and non-linear constitutive laws) require
Simcoon to be installed. Simcoon is available via both pip and conda.
To install Simcoon individually, use either:

.. code-block:: none

$ conda install -c conda-forge -c set3mah simcoon


Or:

.. code-block:: none

$ pip install simcoon
177 changes: 161 additions & 16 deletions docs/boundary_conditions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,16 @@ fedoo. They can be created and add to the problem with the pb.bc.add method.
Contact
==============================

A first implementation of the contact is proposed for 2D problems. Contact
is still in development and subject to slight change in future versions.
Fedoo provides two contact approaches: a **penalty-based** method and an
**IPC (Incremental Potential Contact)** method. Both are implemented as
assembly objects and can be combined with other assemblies using
:py:meth:`fedoo.Assembly.sum`.

For now, only frictionless contact is implemented.
Penalty-based contact
______________________

The penalty method uses a node-to-surface formulation. It is available for
2D problems and supports frictionless contact.

.. autosummary::
:toctree: generated/
Expand All @@ -153,10 +159,70 @@ to a problem, we need first to create the contact assembly (using the class
assembly with :py:meth:`fedoo.Assembly.sum`.


Example
--------------
IPC contact
______________________

The IPC (Incremental Potential Contact) method uses barrier potentials from
the `ipctk <https://ipctk.xyz/>`_ library to guarantee intersection-free
configurations. It supports both 2D and 3D problems, friction, and optional
CCD (Continuous Collision Detection) line search.

Unlike the penalty method, IPC does **not** require tuning a penalty
parameter. The barrier stiffness :math:`\kappa` is automatically computed
and adaptively updated to balance the elastic and contact forces. The only
physical parameter is ``dhat`` — the barrier activation distance that
controls the minimum gap between surfaces (default: 0.1% of the bounding
box diagonal).

**Choosing dhat** --- The default ``dhat=1e-3`` (relative) means the
barrier activates when surfaces are within 0.1 % of the bounding-box
diagonal. For problems with a very small initial gap, increase ``dhat``
(e.g. ``1e-2``) so the barrier catches contact early. For tight-fitting
assemblies where a visible gap is unacceptable, decrease it (e.g.
``1e-4``), but expect more Newton–Raphson iterations.

**CCD line search** --- Enabling ``use_ccd=True`` is recommended for
problems where first contact occurs suddenly (e.g. a punch hitting a
plate) or where self-contact can cause rapid topology changes.

**Energy-based backtracking** --- When ``use_ccd=True``, an
energy-based backtracking phase is automatically enabled after CCD
filtering: the step is halved until total energy (exact barrier +
quadratic elastic approximation) decreases. This matches the
reference IPC algorithm and improves convergence robustness. Set
``line_search_energy=False`` to disable (faster but may degrade
convergence for difficult contact scenarios).

**Convergence criterion** --- The ``'Force'`` convergence criterion
is recommended for IPC contact problems. It measures the relative
decrease of the force residual, matching the gradient-norm convergence
used by reference IPC implementations::

pb.set_nr_criterion('Force', tol=5e-3, max_subiter=15)

The ``'Displacement'`` criterion may become unreliable as contact
stiffness grows.

The ``ipctk`` package is required and can be installed with:

.. code-block:: bash

pip install ipctk
# or
pip install fedoo[ipc]

.. autosummary::
:toctree: generated/
:template: custom-class-template.rst

fedoo.constraint.IPCContact
fedoo.constraint.IPCSelfContact

Here an example of a contact between a square and a disk.

Penalty contact example
__________________________

Here an example of a contact between a square and a disk using the penalty method.

.. code-block:: python

Expand Down Expand Up @@ -195,13 +261,13 @@ Here an example of a contact between a square and a disk.
contact.contact_search_once = True
contact.eps_n = 5e5

#---- Material properties --------------
#---- Material properties --------------
props = np.array([200e3, 0.3, 1e-5, 300, 1000, 0.3])
# E, nu, alpha (non used), Re, k, m
material_rect = fd.constitutivelaw.Simcoon("EPICP", props)
# E, nu, alpha (non used), Re, k, m
material_rect = fd.constitutivelaw.Simcoon("EPICP", props)
material_disk = fd.constitutivelaw.ElasticIsotrop(50e3, 0.3) #E, nu
material = fd.constitutivelaw.Heterogeneous(
(material_rect, material_disk),
(material_rect, material_disk),
('rect', 'disk')
)

Expand Down Expand Up @@ -245,13 +311,92 @@ Here an example of a contact between a square and a disk.
# Write movie with default options
# ------------------------------------
results.write_movie(filename,
'Stress',
component = 'XX',
data_type = 'Node',
framerate = 24,
quality = 5,
'Stress',
component = 'XX',
data_type = 'Node',
framerate = 24,
quality = 5,
clim = [-3e3, 3e3]
)

Video of results:
Video of results:
:download:`contact video <./_static/examples/disk_rectangle_contact.mp4>`


IPC contact example
__________________________

The same disk-rectangle contact problem can be solved with the IPC method.
The IPC method does not require choosing slave/master nodes or tuning a
penalty parameter. The barrier stiffness is automatically computed and
adapted.

.. code-block:: python

import fedoo as fd
import numpy as np

fd.ModelingSpace("2D")

#---- Create geometries (same as penalty example) --------------
mesh_rect = fd.mesh.rectangle_mesh(nx=11, ny=21,
x_min=0, x_max=1, y_min=0, y_max=1,
elm_type='quad4', name='Domain')
mesh_disk = fd.mesh.disk_mesh(radius=0.5, nr=6, nt=6, elm_type='quad4')
mesh_disk.nodes += np.array([1.5, 0.48])
mesh = fd.Mesh.stack(mesh_rect, mesh_disk)

#---- Define IPC contact --------------
surf = fd.mesh.extract_surface(mesh)
ipc_contact = fd.constraint.IPCContact(
mesh, surface_mesh=surf,
friction_coefficient=0.3, # Coulomb friction coefficient
use_ccd=True, # enable CCD line search for robustness
)
# barrier_stiffness is auto-computed; dhat defaults to 1e-3 * bbox_diag

#---- Material and problem setup --------------
material = fd.constitutivelaw.ElasticIsotrop(200e3, 0.3)
wf = fd.weakform.StressEquilibrium(material, nlgeom=True)
solid_assembly = fd.Assembly.create(wf, mesh)
assembly = fd.Assembly.sum(solid_assembly, ipc_contact)

pb = fd.problem.NonLinear(assembly)
res = pb.add_output('results', solid_assembly, ['Disp', 'Stress'])
# ... add BCs ...
pb.nlsolve(dt=0.005, tmax=1)

.. note::

When using ``add_output``, pass the **solid assembly** (not the sum).
``AssemblySum`` objects cannot be used directly for output extraction.


IPC self-contact example
__________________________

For self-contact problems, use :py:class:`~fedoo.constraint.IPCSelfContact`
which automatically extracts the surface from the volumetric mesh.

.. code-block:: python

import fedoo as fd
import numpy as np

fd.ModelingSpace("3D")

mesh = fd.Mesh.read("gyroid.vtk")
material = fd.constitutivelaw.ElasticIsotrop(1e5, 0.3)

# Self-contact: auto surface extraction, auto barrier stiffness
# Add line_search_energy=True for extra robustness (slower)
contact = fd.constraint.IPCSelfContact(mesh, use_ccd=True)

wf = fd.weakform.StressEquilibrium(material, nlgeom="UL")
solid = fd.Assembly.create(wf, mesh)
assembly = fd.Assembly.sum(solid, contact)

pb = fd.problem.NonLinear(assembly)
res = pb.add_output("results", solid, ["Disp", "Stress"])
# ... add BCs ...
pb.nlsolve(dt=0.05, tmax=1, update_dt=True)
2 changes: 1 addition & 1 deletion examples/03-advanced/tube_compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

# contact parameters
contact.contact_search_once = True
contact.eps_n = 1e6 # contact penalty
contact.eps_n = 1e6 / (2 * np.pi * 24) # contact penalty (scaled for 2πr weighting)
contact.max_dist = 1.5 # max distance for the contact search

###############################################################################
Expand Down
Loading
Loading