From 64240405932ab0128a0c92963fc83dfb15001dd3 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:17:37 -0400 Subject: [PATCH 01/19] added a enforce_weakly argument to DirichletBCBase --- src/festim/boundary_conditions/dirichlet_bc.py | 10 +++++++++- src/festim/problem.py | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/festim/boundary_conditions/dirichlet_bc.py b/src/festim/boundary_conditions/dirichlet_bc.py index 4ae5604cd..8d3e9bafe 100644 --- a/src/festim/boundary_conditions/dirichlet_bc.py +++ b/src/festim/boundary_conditions/dirichlet_bc.py @@ -45,9 +45,13 @@ def __init__( self, subdomain: _subdomain.SurfaceSubdomain, value: np.ndarray | fem.Constant | int | float | Callable, + enforce_weakly: bool = False, + penalty: float | None = None, ): self.subdomain = subdomain self.value = value + self.enforce_weakly = enforce_weakly + self.penalty = penalty self.value_fenics = None self.bc_expr = None @@ -180,9 +184,13 @@ def __init__( subdomain: _subdomain.SurfaceSubdomain, value: np.ndarray | fem.Constant | int | float | Callable, species: Species, + enforce_weakly: bool = False, + penalty: float | None = None, ): self.species = species - super().__init__(subdomain, value) + super().__init__( + subdomain, value, enforce_weakly=enforce_weakly, penalty=penalty + ) @property def temperature_dependent(self): diff --git a/src/festim/problem.py b/src/festim/problem.py index 675ef7474..70c87c988 100644 --- a/src/festim/problem.py +++ b/src/festim/problem.py @@ -123,8 +123,9 @@ def define_boundary_conditions(self): """Defines the dirichlet boundary conditions of the model.""" for bc in self.boundary_conditions: if isinstance(bc, F.DirichletBCBase): - form = self.create_dirichletbc_form(bc) - self.bc_forms.append(form) + if not bc.enforce_weakly: + form = self.create_dirichletbc_form(bc) + self.bc_forms.append(form) def get_petsc_options(self) -> dict[str, Any]: """Gets the PETSc options to pass to the NewtonProblem solver. Default options From dec3499a44a674c8e4c4198d09c07cc49f0ca7f3 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:30:56 -0400 Subject: [PATCH 02/19] calculate the form everytime --- src/festim/problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/festim/problem.py b/src/festim/problem.py index 70c87c988..7ee91e070 100644 --- a/src/festim/problem.py +++ b/src/festim/problem.py @@ -123,8 +123,8 @@ def define_boundary_conditions(self): """Defines the dirichlet boundary conditions of the model.""" for bc in self.boundary_conditions: if isinstance(bc, F.DirichletBCBase): + form = self.create_dirichletbc_form(bc) if not bc.enforce_weakly: - form = self.create_dirichletbc_form(bc) self.bc_forms.append(form) def get_petsc_options(self) -> dict[str, Any]: From 2fbb91289bbff3e0e503b272c5e17d3c5b0017ed Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:35:08 -0400 Subject: [PATCH 03/19] add formulation in HydrogenTransportProblem --- src/festim/hydrogen_transport_problem.py | 32 +++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/festim/hydrogen_transport_problem.py b/src/festim/hydrogen_transport_problem.py index 7b181366e..ce82e09ee 100644 --- a/src/festim/hydrogen_transport_problem.py +++ b/src/festim/hydrogen_transport_problem.py @@ -878,7 +878,7 @@ def create_formulation(self): * self.dx(source.volume.id) ) - # add fluxes + # add boundary conditions (fluxes and weak dirichlet) for bc in self.boundary_conditions: if isinstance(bc, boundary_conditions.ParticleFluxBC): self.formulation -= ( @@ -894,6 +894,36 @@ def create_formulation(self): * self.ds(flux_bc.subdomain.id) ) + if isinstance(bc, boundary_conditions.FixedConcentrationBC): + if bc.enforce_weakly: + n = ufl.FacetNormal(self.mesh.mesh) + h = ufl.Circumradius( + self.mesh.mesh + ) # FIXME this doesn't work for rectangles + alpha = bc.penalty + assert alpha is not None, ( + "Penalty parameter must be given for weakly enforced Dirichlet BCs" + ) + assert bc.value_fenics is not None, ( + "value_fenics must be defined for weakly enforced Dirichlet BCs" + ) + + self.formulation += ( + -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) + ) + + self.formulation += ( + +ufl.inner(n, ufl.grad(v)) + * (u - bc.value_fenics) + * self.ds(bc.subdomain.id) + ) + self.formulation += ( + -alpha + / h + * ufl.inner((u - bc.value_fenics), v) + * self.ds(bc.subdomain.id) + ) + for adv_term in self.advection_terms: # create vector functionspace based on the elements in the mesh From 6f5b24f805d3ba2c2900dbc80bc81cbc89bab365 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:37:22 -0400 Subject: [PATCH 04/19] fixed u, v for loop --- src/festim/hydrogen_transport_problem.py | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/festim/hydrogen_transport_problem.py b/src/festim/hydrogen_transport_problem.py index ce82e09ee..7e48871b6 100644 --- a/src/festim/hydrogen_transport_problem.py +++ b/src/festim/hydrogen_transport_problem.py @@ -896,6 +896,8 @@ def create_formulation(self): if isinstance(bc, boundary_conditions.FixedConcentrationBC): if bc.enforce_weakly: + u = bc.species.solution + v = bc.species.test_function n = ufl.FacetNormal(self.mesh.mesh) h = ufl.Circumradius( self.mesh.mesh @@ -1579,7 +1581,35 @@ def create_subdomain_formulation(self, subdomain: _subdomain.VolumeSubdomain): if subdomain == self.surface_to_volume[bc.subdomain]: v = bc.species.subdomain_to_test_function[subdomain] form -= bc.value_fenics * v * self.ds(bc.subdomain.id) + if isinstance(bc, boundary_conditions.FixedConcentrationBC): + if bc.enforce_weakly: + n = ufl.FacetNormal(self.mesh.mesh) + h = ufl.Circumradius( + self.mesh.mesh + ) # FIXME this doesn't work for rectangles + alpha = bc.penalty + assert alpha is not None, ( + "Penalty parameter must be given for weakly enforced Dirichlet BCs" + ) + assert bc.value_fenics is not None, ( + "value_fenics must be defined for weakly enforced Dirichlet BCs" + ) + + self.formulation += ( + -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) + ) + self.formulation += ( + +ufl.inner(n, ufl.grad(v)) + * (u - bc.value_fenics) + * self.ds(bc.subdomain.id) + ) + self.formulation += ( + -alpha + / h + * ufl.inner((u - bc.value_fenics), v) + * self.ds(bc.subdomain.id) + ) # add volumetric sources for source in self.sources: v = source.species.subdomain_to_test_function[subdomain] From b8570e07d06e25b9ca4fa008255c5e71728fb9a0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:41:27 -0400 Subject: [PATCH 05/19] propagated change to Discontinuous class --- src/festim/hydrogen_transport_problem.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/festim/hydrogen_transport_problem.py b/src/festim/hydrogen_transport_problem.py index 7e48871b6..e6aa2b7c4 100644 --- a/src/festim/hydrogen_transport_problem.py +++ b/src/festim/hydrogen_transport_problem.py @@ -1583,6 +1583,8 @@ def create_subdomain_formulation(self, subdomain: _subdomain.VolumeSubdomain): form -= bc.value_fenics * v * self.ds(bc.subdomain.id) if isinstance(bc, boundary_conditions.FixedConcentrationBC): if bc.enforce_weakly: + u = bc.species.subdomain_to_solution[subdomain] + v = bc.species.subdomain_to_test_function[subdomain] n = ufl.FacetNormal(self.mesh.mesh) h = ufl.Circumradius( self.mesh.mesh @@ -1595,16 +1597,14 @@ def create_subdomain_formulation(self, subdomain: _subdomain.VolumeSubdomain): "value_fenics must be defined for weakly enforced Dirichlet BCs" ) - self.formulation += ( - -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) - ) + form += -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) - self.formulation += ( + form += ( +ufl.inner(n, ufl.grad(v)) * (u - bc.value_fenics) * self.ds(bc.subdomain.id) ) - self.formulation += ( + form += ( -alpha / h * ufl.inner((u - bc.value_fenics), v) From e9add2b62f58363225f15a30056dc411960a4e13 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 09:54:10 -0400 Subject: [PATCH 06/19] refactoring + documentation --- .../boundary_conditions/dirichlet_bc.py | 43 +++++++++++++++ src/festim/hydrogen_transport_problem.py | 54 +------------------ 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/festim/boundary_conditions/dirichlet_bc.py b/src/festim/boundary_conditions/dirichlet_bc.py index 8d3e9bafe..132d5dc9e 100644 --- a/src/festim/boundary_conditions/dirichlet_bc.py +++ b/src/festim/boundary_conditions/dirichlet_bc.py @@ -3,8 +3,10 @@ import numpy as np import numpy.typing as npt import ufl +import ufl.argument import ufl.core import ufl.core.expr +import ufl.indexed from dolfinx import fem from dolfinx import mesh as _mesh @@ -142,6 +144,47 @@ def update(self, t: float): elif self.bc_expr is not None: self.value_fenics.interpolate(self.bc_expr) + def weak_formulation( + self, + u: fem.Function | ufl.indexed.Indexed, + v: ufl.argument.Argument | ufl.indexed.Indexed, + ds: ufl.Measure, + ) -> ufl.core.expr.Expr: + """ + Returns the Nitsche weak formulation for the BC + This follows the dolfinx tutorial + https://jsdokken.com/dolfinx-tutorial/chapter1/nitsche.html + + Args: + u: the solution function associated to the species for which the BC + is applied + v: the test function + ds: the surface measure + + Returns: + the weak formulation + """ + mesh = ds.ufl_domain() + n = ufl.FacetNormal(mesh) + h = ufl.Circumradius(mesh) # FIXME this doesn't work for rectangles + alpha = self.penalty + assert alpha is not None, ( + "Penalty parameter must be given for weakly enforced Dirichlet BCs" + ) + assert self.value_fenics is not None, ( + "value_fenics must be defined for weakly enforced Dirichlet BCs" + ) + + form = -ufl.inner(n, ufl.grad(u)) * v * ds(self.subdomain.id) + + form += ( + +ufl.inner(n, ufl.grad(v)) * (u - self.value_fenics) * ds(self.subdomain.id) + ) + form += ( + -alpha / h * ufl.inner((u - self.value_fenics), v) * ds(self.subdomain.id) + ) + return form + class FixedConcentrationBC(DirichletBCBase): """ diff --git a/src/festim/hydrogen_transport_problem.py b/src/festim/hydrogen_transport_problem.py index e6aa2b7c4..1e6682ccb 100644 --- a/src/festim/hydrogen_transport_problem.py +++ b/src/festim/hydrogen_transport_problem.py @@ -898,34 +898,7 @@ def create_formulation(self): if bc.enforce_weakly: u = bc.species.solution v = bc.species.test_function - n = ufl.FacetNormal(self.mesh.mesh) - h = ufl.Circumradius( - self.mesh.mesh - ) # FIXME this doesn't work for rectangles - alpha = bc.penalty - assert alpha is not None, ( - "Penalty parameter must be given for weakly enforced Dirichlet BCs" - ) - assert bc.value_fenics is not None, ( - "value_fenics must be defined for weakly enforced Dirichlet BCs" - ) - - self.formulation += ( - -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) - ) - - self.formulation += ( - +ufl.inner(n, ufl.grad(v)) - * (u - bc.value_fenics) - * self.ds(bc.subdomain.id) - ) - self.formulation += ( - -alpha - / h - * ufl.inner((u - bc.value_fenics), v) - * self.ds(bc.subdomain.id) - ) - + self.formulation += bc.weak_formulation(u, v, self.ds) for adv_term in self.advection_terms: # create vector functionspace based on the elements in the mesh @@ -1585,31 +1558,8 @@ def create_subdomain_formulation(self, subdomain: _subdomain.VolumeSubdomain): if bc.enforce_weakly: u = bc.species.subdomain_to_solution[subdomain] v = bc.species.subdomain_to_test_function[subdomain] - n = ufl.FacetNormal(self.mesh.mesh) - h = ufl.Circumradius( - self.mesh.mesh - ) # FIXME this doesn't work for rectangles - alpha = bc.penalty - assert alpha is not None, ( - "Penalty parameter must be given for weakly enforced Dirichlet BCs" - ) - assert bc.value_fenics is not None, ( - "value_fenics must be defined for weakly enforced Dirichlet BCs" - ) - - form += -ufl.inner(n, ufl.grad(u)) * v * self.ds(bc.subdomain.id) + form += bc.weak_formulation(u, v, self.ds) - form += ( - +ufl.inner(n, ufl.grad(v)) - * (u - bc.value_fenics) - * self.ds(bc.subdomain.id) - ) - form += ( - -alpha - / h - * ufl.inner((u - bc.value_fenics), v) - * self.ds(bc.subdomain.id) - ) # add volumetric sources for source in self.sources: v = source.species.subdomain_to_test_function[subdomain] From 8265cd2d335a5e50e19c6daf3f25c0a2e9515ee1 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:00:23 -0400 Subject: [PATCH 07/19] added test --- test/system_tests/test_misc.py | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/system_tests/test_misc.py b/test/system_tests/test_misc.py index 8d678f43f..4dc3ed6d7 100644 --- a/test/system_tests/test_misc.py +++ b/test/system_tests/test_misc.py @@ -1,12 +1,14 @@ from mpi4py import MPI import dolfinx +import ufl import numpy as np import pytest import festim as F from .test_multi_mat_penalty import generate_mesh +from .tools import error_L2 def test_petsc_options(): @@ -389,3 +391,75 @@ def test_sub_temperature_as_function_mixed_domain_not_updated(): my_model.run() assert not np.allclose(avg_surf.data, 4.0) + + +def test_MMS_weak_dirichlet(): + """ + MMS test with one mobile species at steady state, with Dirichlet BCs enforced weakly. + """ + + def u_exact(mod): + return lambda x: 1 + mod.sin(2 * mod.pi * x[0]) + mod.cos(2 * mod.pi * x[1]) + + H_analytical_ufl = u_exact(ufl) + H_analytical_np = u_exact(np) + + mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 50, 50) + + V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1)) + T = dolfinx.fem.Function(V) + + D_0 = 1 + E_D = 0.1 + + def T_expr(x): + return 500 + 100 * x[0] + + T.interpolate(T_expr) + D = D_0 * ufl.exp(-E_D / (F.k_B * T)) + + my_model = F.HydrogenTransportProblem() + my_model.mesh = F.Mesh(mesh=mesh) + + my_mat = F.Material(name="mat", D_0=D_0, E_D=E_D) + vol = F.VolumeSubdomain(id=1, material=my_mat) + left = F.SurfaceSubdomain(id=1, locator=lambda x: np.isclose(x[0], 0)) + right = F.SurfaceSubdomain(id=2, locator=lambda x: np.isclose(x[0], 1)) + my_model.subdomains = [vol, left, right] + + H = F.Species("H") + my_model.species = [H] + + my_model.temperature = T_expr + + my_model.boundary_conditions = [ + F.FixedConcentrationBC( + subdomain=left, + value=H_analytical_ufl, + species=H, + enforce_weakly=True, + penalty=300, + ), + F.FixedConcentrationBC( + subdomain=right, + value=H_analytical_ufl, + species=H, + enforce_weakly=True, + penalty=300, + ), + ] + + x = ufl.SpatialCoordinate(mesh) + f = -ufl.div(D * ufl.grad(H_analytical_ufl(x))) + my_model.sources = [F.ParticleSource(value=f, volume=vol, species=H)] + + my_model.settings = F.Settings(atol=1e-10, rtol=1e-10, transient=False) + + my_model.initialise() + my_model.run() + + H_computed = H.post_processing_solution + + L2_error = error_L2(H_computed, H_analytical_np) + + assert L2_error < 2e-3 From bdd9637919bed86908743ec44f446ee115ddcaf6 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:05:46 -0400 Subject: [PATCH 08/19] ruff --- test/system_tests/test_misc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/system_tests/test_misc.py b/test/system_tests/test_misc.py index 4dc3ed6d7..e2d9e6cdf 100644 --- a/test/system_tests/test_misc.py +++ b/test/system_tests/test_misc.py @@ -1,9 +1,9 @@ from mpi4py import MPI import dolfinx -import ufl import numpy as np import pytest +import ufl import festim as F @@ -395,7 +395,8 @@ def test_sub_temperature_as_function_mixed_domain_not_updated(): def test_MMS_weak_dirichlet(): """ - MMS test with one mobile species at steady state, with Dirichlet BCs enforced weakly. + MMS test with one mobile species at steady state, with Dirichlet BCs enforced + weakly. """ def u_exact(mod): From 90c8bff1f0ba61aeaba13519f08e42e72708e2b2 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:13:07 -0400 Subject: [PATCH 09/19] test for discontinuous --- test/system_tests/test_misc.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/system_tests/test_misc.py b/test/system_tests/test_misc.py index e2d9e6cdf..fb64f6855 100644 --- a/test/system_tests/test_misc.py +++ b/test/system_tests/test_misc.py @@ -393,7 +393,13 @@ def test_sub_temperature_as_function_mixed_domain_not_updated(): assert not np.allclose(avg_surf.data, 4.0) -def test_MMS_weak_dirichlet(): +@pytest.mark.parametrize( + "model_class", [F.HydrogenTransportProblem, F.HydrogenTransportProblemDiscontinuous] +) +def test_MMS_weak_dirichlet( + model_class: type[F.HydrogenTransportProblem] + | type[F.HydrogenTransportProblemDiscontinuous], +): """ MMS test with one mobile species at steady state, with Dirichlet BCs enforced weakly. @@ -419,7 +425,7 @@ def T_expr(x): T.interpolate(T_expr) D = D_0 * ufl.exp(-E_D / (F.k_B * T)) - my_model = F.HydrogenTransportProblem() + my_model = model_class() my_model.mesh = F.Mesh(mesh=mesh) my_mat = F.Material(name="mat", D_0=D_0, E_D=E_D) @@ -431,6 +437,9 @@ def T_expr(x): H = F.Species("H") my_model.species = [H] + if isinstance(my_model, F.HydrogenTransportProblemDiscontinuous): + H.subdomains = [vol] + my_model.temperature = T_expr my_model.boundary_conditions = [ @@ -459,7 +468,10 @@ def T_expr(x): my_model.initialise() my_model.run() - H_computed = H.post_processing_solution + if isinstance(my_model, F.HydrogenTransportProblemDiscontinuous): + H_computed = H.subdomain_to_post_processing_solution[vol] + else: + H_computed = H.post_processing_solution L2_error = error_L2(H_computed, H_analytical_np) From a137992ead3717a3e2cb0f9159a7ab65c4b6d9e1 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:20:03 -0400 Subject: [PATCH 10/19] test with multiple species --- test/system_tests/test_misc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/system_tests/test_misc.py b/test/system_tests/test_misc.py index fb64f6855..40a046c12 100644 --- a/test/system_tests/test_misc.py +++ b/test/system_tests/test_misc.py @@ -435,10 +435,12 @@ def T_expr(x): my_model.subdomains = [vol, left, right] H = F.Species("H") - my_model.species = [H] + H2 = F.Species("D") + my_model.species = [H, H2] if isinstance(my_model, F.HydrogenTransportProblemDiscontinuous): H.subdomains = [vol] + H2.subdomains = [vol] my_model.temperature = T_expr From 48d775f295ea73dc4aed9d96efa8fd3021850d04 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:20:03 -0400 Subject: [PATCH 11/19] test with multiple species --- test/system_tests/test_misc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/system_tests/test_misc.py b/test/system_tests/test_misc.py index fb64f6855..40a046c12 100644 --- a/test/system_tests/test_misc.py +++ b/test/system_tests/test_misc.py @@ -435,10 +435,12 @@ def T_expr(x): my_model.subdomains = [vol, left, right] H = F.Species("H") - my_model.species = [H] + H2 = F.Species("D") + my_model.species = [H, H2] if isinstance(my_model, F.HydrogenTransportProblemDiscontinuous): H.subdomains = [vol] + H2.subdomains = [vol] my_model.temperature = T_expr From 41d10dca904d6b2bf917d0190d8fb7e7d8cf3ee6 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:25:51 -0400 Subject: [PATCH 12/19] add no-build-isolation to pip dependencies --- .github/workflows/ci_docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_docker.yml b/.github/workflows/ci_docker.yml index 7eec50a65..78b3f451c 100644 --- a/.github/workflows/ci_docker.yml +++ b/.github/workflows/ci_docker.yml @@ -20,7 +20,7 @@ jobs: - name: Install local package and dependencies run: | - pip install .[test] + pip install .[test] --no-build-isolation - name: Overload adios4dolfinx if: ${{ matrix.container_version == 'nightly' }} From 5dd570db94e6618e093b1bb2b9ae53f55c8382b3 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:29:59 -0400 Subject: [PATCH 13/19] python -m --- .github/workflows/ci_docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_docker.yml b/.github/workflows/ci_docker.yml index 78b3f451c..9dbcce7d1 100644 --- a/.github/workflows/ci_docker.yml +++ b/.github/workflows/ci_docker.yml @@ -20,7 +20,7 @@ jobs: - name: Install local package and dependencies run: | - pip install .[test] --no-build-isolation + python -m pip install .[test] --no-build-isolation - name: Overload adios4dolfinx if: ${{ matrix.container_version == 'nightly' }} From cf3049478798f903e0c0d6fd010b92465324abfb Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:34:58 -0400 Subject: [PATCH 14/19] try changing the license in pyproject --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fdf0ab022..5982236d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ name = "FESTIM" description = "Finite element simulations of hydrogen transport" readme = "README.md" requires-python = ">=3.9" -license = "Apache-2.0" +license = { text = "Apache-2.0" } dependencies = ["tqdm", "scifem>=0.2.13", "adios4dolfinx"] classifiers = [ "Natural Language :: English", From ac946f0ccb57fe0c70e22c810c8ccf786646abc9 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 10:37:32 -0400 Subject: [PATCH 15/19] upgrade pip --- .github/workflows/ci_docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_docker.yml b/.github/workflows/ci_docker.yml index 9dbcce7d1..4b0899f98 100644 --- a/.github/workflows/ci_docker.yml +++ b/.github/workflows/ci_docker.yml @@ -20,6 +20,7 @@ jobs: - name: Install local package and dependencies run: | + python -m pip install --upgrade pip python -m pip install .[test] --no-build-isolation - name: Overload adios4dolfinx From b80166d8e4a204553ed474202eee9bd93c6ff772 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 11:11:03 -0400 Subject: [PATCH 16/19] revert --- .github/workflows/ci_docker.yml | 3 +-- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_docker.yml b/.github/workflows/ci_docker.yml index 4b0899f98..332a8d231 100644 --- a/.github/workflows/ci_docker.yml +++ b/.github/workflows/ci_docker.yml @@ -20,8 +20,7 @@ jobs: - name: Install local package and dependencies run: | - python -m pip install --upgrade pip - python -m pip install .[test] --no-build-isolation + python -m pip install .[test] - name: Overload adios4dolfinx if: ${{ matrix.container_version == 'nightly' }} diff --git a/pyproject.toml b/pyproject.toml index 5982236d6..fdf0ab022 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ name = "FESTIM" description = "Finite element simulations of hydrogen transport" readme = "README.md" requires-python = ">=3.9" -license = { text = "Apache-2.0" } +license = "Apache-2.0" dependencies = ["tqdm", "scifem>=0.2.13", "adios4dolfinx"] classifiers = [ "Natural Language :: English", From 0294cb1aa001aa0021b9880e2f94df0e733441bb Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 11:32:34 -0400 Subject: [PATCH 17/19] lower bound on setuptools --- pyproject.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fdf0ab022..50046b102 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,9 @@ [build-system] -requires = ["setuptools >= 61", "wheel", "setuptools-scm[toml] >= 7.0.5"] +requires = [ + "setuptools>=77.0.3", # Ensuring license field is correctly parsed + "wheel", + "setuptools-scm[toml] >= 7.0.5", +] build-backend = "setuptools.build_meta" [project] From ad8d19e3fb31f068e9b59b1403beef88873d0a2d Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Mon, 18 May 2026 12:25:49 -0400 Subject: [PATCH 18/19] docstrings --- src/festim/boundary_conditions/dirichlet_bc.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/festim/boundary_conditions/dirichlet_bc.py b/src/festim/boundary_conditions/dirichlet_bc.py index 132d5dc9e..fde8d4527 100644 --- a/src/festim/boundary_conditions/dirichlet_bc.py +++ b/src/festim/boundary_conditions/dirichlet_bc.py @@ -21,6 +21,10 @@ class DirichletBCBase: Args: subdomain: The surface subdomain where the boundary condition is applied value: The value of the boundary condition + enforce_weakly: Whether to enforce the boundary condition weakly using Nitsche's + method. Defaults to False. + penalty: The penalty parameter to use if ``enforce_weakly`` is True. + Defaults to None Attributes: subdomain: The surface subdomain where the boundary condition is applied @@ -28,6 +32,9 @@ class DirichletBCBase: value_fenics: The value of the boundary condition in fenics format bc_expr: The expression of the boundary condition that is used to update the `value_fenics` + enforce_weakly: Whether to enforce the boundary condition weakly using Nitsche's + method. + penalty: The penalty parameter to use if ``enforce_weakly`` is True. """ subdomain: _subdomain.SurfaceSubdomain @@ -194,6 +201,10 @@ class FixedConcentrationBC(DirichletBCBase): value: The value of the boundary condition. It can be a function of space and/or time species: The name of the species + enforce_weakly: Whether to enforce the boundary condition weakly using Nitsche's + method. Defaults to False. + penalty: The penalty parameter to use if ``enforce_weakly`` is True. + Defaults to None Attributes: temperature_dependent (bool): True if the value of the bc is From d2bedae6e9789bf116a1b93771deb529f612954f Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 19 May 2026 12:41:08 -0400 Subject: [PATCH 19/19] pip isntall scipy --- .github/workflows/ci_docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_docker.yml b/.github/workflows/ci_docker.yml index 332a8d231..4dbf7bfd7 100644 --- a/.github/workflows/ci_docker.yml +++ b/.github/workflows/ci_docker.yml @@ -20,6 +20,7 @@ jobs: - name: Install local package and dependencies run: | + python -m pip install scipy # needed in scifem, can be removed when scifem adds it to their dependencies python -m pip install .[test] - name: Overload adios4dolfinx