Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Change of var method for interface discontinuities #904

Draft
wants to merge 39 commits into
base: fenicsx
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3507d15
initial commit
RemDelaporteMathurin Oct 29, 2024
672fd39
Merge branch 'discontinuity-generic' into change-of-var-method
RemDelaporteMathurin Oct 29, 2024
50c3798
example file
RemDelaporteMathurin Oct 29, 2024
ec7ba6f
working example!
RemDelaporteMathurin Oct 29, 2024
d23fa1c
DG elements for traps + only remove vol from list if it's in list
RemDelaporteMathurin Oct 29, 2024
009c833
num-cells-per-segment
RemDelaporteMathurin Oct 29, 2024
76b1e19
Merge branch 'discontinuity-generic' into change-of-var-method
RemDelaporteMathurin Oct 29, 2024
ace007c
don't print form
RemDelaporteMathurin Oct 29, 2024
b2b3bfa
added petsc options
RemDelaporteMathurin Oct 29, 2024
9eb98f5
moved convergence rates
RemDelaporteMathurin Oct 30, 2024
56d3fd0
moved to test
RemDelaporteMathurin Oct 30, 2024
a52f06b
Merge remote-tracking branch 'upstream/fenicsx' into change-of-var-me…
RemDelaporteMathurin Oct 30, 2024
ac8b8db
added check for only one mobile species
RemDelaporteMathurin Oct 30, 2024
e1f4fde
DirichletBC are now rescaled inside festim
RemDelaporteMathurin Oct 30, 2024
14c7455
BCs were not updated when only T was changing
RemDelaporteMathurin Oct 30, 2024
ce8cc87
get_K_S_0 and get_E_K_S
RemDelaporteMathurin Oct 30, 2024
309464b
works in multispecies
RemDelaporteMathurin Oct 30, 2024
976a0bd
removed comment
RemDelaporteMathurin Oct 30, 2024
b131d5e
added MMS test
RemDelaporteMathurin Oct 31, 2024
d823337
add a temporary method (correct) for entities
RemDelaporteMathurin Oct 31, 2024
b51b857
correct L2 error
RemDelaporteMathurin Oct 31, 2024
5593aae
fixed imports
RemDelaporteMathurin Oct 31, 2024
9515840
DG element
RemDelaporteMathurin Oct 31, 2024
2b3cbac
added note
RemDelaporteMathurin Oct 31, 2024
016d8c0
Merge branch 'fix-solver-options' into change-of-var-method
RemDelaporteMathurin Oct 31, 2024
ed809f0
added fix for c = 0 trick
RemDelaporteMathurin Oct 31, 2024
dcf5c5e
removed failing test (referenced in issue)
RemDelaporteMathurin Nov 1, 2024
efd9ab2
ruff
RemDelaporteMathurin Nov 1, 2024
92be8a9
Merge remote-tracking branch 'upstream/fenicsx' into change-of-var-me…
RemDelaporteMathurin Nov 12, 2024
beef3b4
Use newest newton solver
jorgensd Nov 19, 2024
5bf396e
Bump scifem release
jorgensd Nov 19, 2024
e7c7876
Remove rtol from steady state
jorgensd Nov 19, 2024
472eaa5
ruff formatting
jorgensd Nov 19, 2024
54063ba
fixed atol=None
RemDelaporteMathurin Nov 19, 2024
582e7e0
Merge remote-tracking branch 'upstream/fenicsx' into dokken/change-of…
RemDelaporteMathurin Nov 19, 2024
f5f4753
Merge remote-tracking branch 'upstream/fenicsx' into change-of-var-me…
RemDelaporteMathurin Nov 19, 2024
99185ab
Merge branch 'change-of-var-method' into dokken/change-of-var
RemDelaporteMathurin Nov 19, 2024
482d920
Apply suggestions from code review
jorgensd Nov 19, 2024
e6ce4bc
Merge pull request #3 from RemDelaporteMathurin/dokken/change-of-var
RemDelaporteMathurin Nov 19, 2024
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description = "Finite element simulations of hydrogen transport"
readme = "README/md"
requires-python = ">=3.9"
license = { file = "LICENSE" }
dependencies = ["tqdm", "scifem>=0.2.8"]
dependencies = ["tqdm", "scifem>=0.2.13"]
classifiers = [
"Natural Language :: English",
"Topic :: Scientific/Engineering",
Expand Down
3 changes: 2 additions & 1 deletion src/festim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
HydrogenTransportProblem,
HTransportProblemPenalty,
)
from .problem_change_of_var import HydrogenTransportProblemDiscontinuousChangeVar
from .initial_condition import InitialCondition, InitialTemperature
from .material import Material
from .mesh.mesh import Mesh
Expand All @@ -51,7 +52,7 @@
from .reaction import Reaction
from .settings import Settings
from .source import HeatSource, ParticleSource, SourceBase
from .species import ImplicitSpecies, Species, find_species_from_name
from .species import ImplicitSpecies, Species, find_species_from_name, SpeciesChangeVar
from .stepsize import Stepsize
from .subdomain.interface import Interface
from .subdomain.surface_subdomain import SurfaceSubdomain, find_surface_from_id
Expand Down
66 changes: 61 additions & 5 deletions src/festim/boundary_conditions/dirichlet_bc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import ufl
from dolfinx import fem
from dolfinx import mesh as _mesh
import ufl.core
import ufl.core.expr

from festim import helpers
from festim import subdomain as _subdomain
from festim.species import Species


class DirichletBCBase:
Expand Down Expand Up @@ -124,14 +127,16 @@
"""Updates the boundary condition value

Args:
t (float): the time
t: the time
"""
if callable(self.value):
arguments = self.value.__code__.co_varnames
if isinstance(self.value_fenics, fem.Constant) and "t" in arguments:
self.value_fenics.value = self.value(t=t)
else:
self.value_fenics.interpolate(self.bc_expr)
elif self.bc_expr is not None:
self.value_fenics.interpolate(self.bc_expr)

Check warning on line 139 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L138-L139

Added lines #L138 - L139 were not covered by tests


class FixedConcentrationBC(DirichletBCBase):
Expand Down Expand Up @@ -163,13 +168,13 @@

"""

species: str
species: Species

def __init__(
self,
subdomain: _subdomain.SurfaceSubdomain,
value: np.ndarray | fem.Constant | int | float | Callable,
species: str,
species: Species,
):
self.species = species
super().__init__(subdomain, value)
Expand All @@ -191,6 +196,7 @@
function_space: fem.FunctionSpace,
temperature: float | fem.Constant,
t: float | fem.Constant,
K_S: fem.Function = None,
):
"""Creates the value of the boundary condition as a fenics object and sets it to
self.value_fenics.
Expand All @@ -200,9 +206,11 @@
expression of the function is stored in `bc_expr`.

Args:
function_space (dolfinx.fem.FunctionSpace): the function space
function_space: the function space
temperature: The temperature
t (dolfinx.fem.Constant): the time
t: the time
K_S: The solubility of the species. If provided, the value of the boundary condition
is divided by K_S (change of variable method).
"""
mesh = function_space.mesh
x = ufl.SpatialCoordinate(mesh)
Expand Down Expand Up @@ -241,6 +249,54 @@
)
self.value_fenics.interpolate(self.bc_expr)

# if K_S is provided, divide the value by K_S (change of variable method)
if K_S is not None:
if isinstance(self.value, (int, float)):
val_as_cst = helpers.as_fenics_constant(mesh=mesh, value=self.value)
self.bc_expr = fem.Expression(
val_as_cst / K_S,
function_space.element.interpolation_points(),
)
self.value_fenics = fem.Function(function_space)
self.value_fenics.interpolate(self.bc_expr)

elif callable(self.value):
arguments = self.value.__code__.co_varnames

if "t" in arguments and "x" not in arguments and "T" not in arguments:
# only t is an argument

# check that value returns a ufl expression
if not isinstance(self.value(t=t), (ufl.core.expr.Expr)):
raise ValueError(

Check warning on line 271 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L270-L271

Added lines #L270 - L271 were not covered by tests
"self.value should return a ufl expression"
+ f"{type(self.value(t=t))} "
)

self.bc_expr = fem.Expression(

Check warning on line 276 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L276

Added line #L276 was not covered by tests
self.value(t=t) / K_S,
function_space.element.interpolation_points(),
)
self.value_fenics = fem.Function(function_space)
self.value_fenics.interpolate(self.bc_expr)

Check warning on line 281 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L280-L281

Added lines #L280 - L281 were not covered by tests
else:
self.value_fenics = fem.Function(function_space)
kwargs = {}
if "t" in arguments:
kwargs["t"] = t

Check warning on line 286 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L286

Added line #L286 was not covered by tests
if "x" in arguments:
kwargs["x"] = x
if "T" in arguments:
kwargs["T"] = temperature

Check warning on line 290 in src/festim/boundary_conditions/dirichlet_bc.py

View check run for this annotation

Codecov / codecov/patch

src/festim/boundary_conditions/dirichlet_bc.py#L290

Added line #L290 was not covered by tests

# store the expression of the boundary condition
# to update the value_fenics later
self.bc_expr = fem.Expression(
self.value(**kwargs) / K_S,
function_space.element.interpolation_points(),
)
self.value_fenics.interpolate(self.bc_expr)


# alias for FixedConcentrationBC
DirichletBC = FixedConcentrationBC
Expand Down
49 changes: 39 additions & 10 deletions src/festim/hydrogen_transport_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import tqdm.autonotebook
import ufl
from dolfinx import fem
from scifem import NewtonSolver
from scifem import BlockedNewtonSolver

import festim.boundary_conditions
import festim.problem
Expand Down Expand Up @@ -167,6 +167,9 @@
self.temperature_fenics = None
self._vtxfiles: list[dolfinx.io.VTXWriter] = []

self._element_for_traps = "DG"
self.petcs_options = petsc_options

@property
def temperature(self):
return self._temperature
Expand Down Expand Up @@ -451,14 +454,25 @@
degree,
basix.LagrangeVariant.equispaced,
)
element_DG = basix.ufl.element(
"DG",
self.mesh.mesh.basix_cell(),
degree,
basix.LagrangeVariant.equispaced,
)

if not self.multispecies:
element = element_CG
else:
elements = []
for spe in self.species:
if isinstance(spe, _species.Species):
elements.append(element_CG)
if spe.mobile:
elements.append(element_CG)
elif self._element_for_traps == "DG":
elements.append(element_DG)
else:
elements.append(element_CG)

Check warning on line 475 in src/festim/hydrogen_transport_problem.py

View check run for this annotation

Codecov / codecov/patch

src/festim/hydrogen_transport_problem.py#L475

Added line #L475 was not covered by tests
element = basix.ufl.mixed_element(elements)

self.function_space = fem.functionspace(self.mesh.mesh, element)
Expand Down Expand Up @@ -718,7 +732,8 @@
# check reactions
for reaction in self.reactions:
if vol == reaction.volume:
not_defined_in_volume.remove(vol)
if vol in not_defined_in_volume:
not_defined_in_volume.remove(vol)

# add c = 0 to formulation where needed
for vol in not_defined_in_volume:
Expand Down Expand Up @@ -1194,18 +1209,32 @@
self.forms = dolfinx.fem.form(
[subdomain.F for subdomain in self.volume_subdomains],
entity_maps=entity_maps,
jit_options={
"cffi_extra_compile_args": ["-O3", "-march=native"],
"cffi_libraries": ["m"],
},
)
self.J = dolfinx.fem.form(
J,
entity_maps=entity_maps,
jit_options={
"cffi_extra_compile_args": ["-O3", "-march=native"],
"cffi_libraries": ["m"],
},
)
self.J = dolfinx.fem.form(J, entity_maps=entity_maps)

def create_solver(self):
self.solver = NewtonSolver(
self.solver = BlockedNewtonSolver(
self.forms,
self.J,
[subdomain.u for subdomain in self.volume_subdomains],
J=self.J,
bcs=self.bc_forms,
max_iterations=self.settings.max_iterations,
petsc_options=self.petsc_options,
)
self.solver.max_iterations = self.settings.max_iterations
self.solver.convergence_criterion = self.settings.convergence_criterion
self.solver.atol = self.settings.atol
self.solver.rtol = self.settings.rtol

def create_flux_values_fenics(self):
"""For each particle flux create the ``value_fenics`` attribute"""
Expand Down Expand Up @@ -1264,8 +1293,8 @@

self.update_time_dependent_values()

# solve main problem
self.solver.solve(self.settings.atol, self.settings.rtol)
# Solve main problem
self.solver.solve()

# post processing
self.post_processing()
Expand Down Expand Up @@ -1293,7 +1322,7 @@
self.progress_bar.refresh() # refresh progress bar to show 100%
else:
# Solve steady-state
self.solver.solve(self.settings.rtol)
self.solver.solve()
self.post_processing()

def __del__(self):
Expand Down
54 changes: 53 additions & 1 deletion src/festim/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,58 @@
else:
raise TypeError("E_D must be either a float, int or a dict")

def get_K_S_0(self, species=None) -> float:
"""Returns the pre-exponential factor of the solubility coefficient
Args:
species: the species we want the pre-exponential
factor of the solubility coefficient of. Only needed if K_S_0 is a dict.
Returns:
the pre-exponential factor of the solubility coefficient
"""

if isinstance(self.K_S_0, (float, int)):
return self.K_S_0

elif isinstance(self.K_S_0, dict):
if species is None:
raise ValueError("species must be provided if K_S_0 is a dict")

Check warning on line 138 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L136-L138

Added lines #L136 - L138 were not covered by tests

if species in self.K_S_0:
return self.K_S_0[species]
elif species.name in self.K_S_0:
return self.K_S_0[species.name]

Check warning on line 143 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L140-L143

Added lines #L140 - L143 were not covered by tests
else:
raise ValueError(f"{species} is not in K_S_0 keys")

Check warning on line 145 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L145

Added line #L145 was not covered by tests

else:
raise TypeError("K_S_0 must be either a float, int or a dict")

Check warning on line 148 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L148

Added line #L148 was not covered by tests

def get_E_K_S(self, species=None) -> float:
"""Returns the activation energy of the solubility coefficient
Args:
species: the species we want the activation
energy of the solubility coefficient of. Only needed if E_K_S is a dict.
Returns:
the activation energy of the solubility coefficient
"""

if isinstance(self.E_K_S, (float, int)):
return self.E_K_S

elif isinstance(self.E_K_S, dict):
if species is None:
raise ValueError("species must be provided if E_K_S is a dict")

Check warning on line 164 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L162-L164

Added lines #L162 - L164 were not covered by tests

if species in self.E_K_S:
return self.E_K_S[species]
elif species.name in self.E_K_S:
return self.E_K_S[species.name]

Check warning on line 169 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L166-L169

Added lines #L166 - L169 were not covered by tests
else:
raise ValueError(f"{species} is not in E_K_S keys")

Check warning on line 171 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L171

Added line #L171 was not covered by tests

else:
raise TypeError("E_K_S must be either a float, int or a dict")

Check warning on line 174 in src/festim/material.py

View check run for this annotation

Codecov / codecov/patch

src/festim/material.py#L174

Added line #L174 was not covered by tests

def get_diffusion_coefficient(self, mesh, temperature, species=None):
"""Defines the diffusion coefficient
Args:
Expand Down Expand Up @@ -184,7 +236,7 @@
Returns:
ufl.algebra.Product: the solubility coefficient
"""
# TODO use get_D_0 and get_E_D to refactore this method, something like:
# TODO use get_K_S0 and get_E_K_S to refactore this method, something like:
# K_S_0 = self.get_K_S_0(species=species)
# E_K_S = self.get_E_K_S(species=species)

Expand Down
Loading
Loading