Skip to content
1 change: 0 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
# Add the directory containing your Python script to the Python path
sys.path.insert(0, os.path.abspath("."))

import map

m = map.generate_map()
current_dir = os.path.dirname(__file__)
Expand Down
9 changes: 4 additions & 5 deletions examples/advection_diffusion_multi_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def half(x):
)

# Split domain in half and set an interface tag of 5
gdim = mesh.geometry.dim
tdim = mesh.topology.dim
fdim = tdim - 1
top_facets = dolfinx.mesh.locate_entities_boundary(mesh, fdim, top_boundary)
Expand Down Expand Up @@ -80,10 +79,10 @@ def velocity_func(x):
values[1] = 0 # Second component remains zero
return values

mesh2, mt2, ct2 = generate_mesh(n=10)
submesh, cell_map, v_map = dolfinx.mesh.create_submesh(mesh2, ct2.dim, ct2.find(4))[
0:3
]
mesh2, _mt2, ct2 = generate_mesh(n=10)
submesh, _cell_map, _v_map = dolfinx.mesh.create_submesh(
mesh2, ct2.dim, ct2.find(4)
)[0:3]
v_cg = basix.ufl.element(
"Lagrange", submesh.topology.cell_name(), 2, shape=(submesh.geometry.dim,)
)
Expand Down
7 changes: 5 additions & 2 deletions examples/convergence_rates.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ def mms_source(x, t):
my_problem.settings = F.Settings(
atol=1e-8,
rtol=1e-10,
final_time=1, # final time shouldn't be too long so that a potential error at the initial timestep is not negligible
# final time shouldn't be too long so that a potential error at the
# initial timestep is not negligible
final_time=1,
)

# Forward euler isn't great so dt should be small
Expand All @@ -127,7 +129,8 @@ def mms_source(x, t):
my_problem.run()

computed_solution = my_problem.u
# we use the exact final time of the simulation which may differ from the one specified in the settings
# we use the exact final time of the simulation which may differ from
# the one specified in the settings
final_time_sim = my_problem.t.value

def exact_solution_end(x):
Expand Down
3 changes: 2 additions & 1 deletion examples/multi_material_1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
left_surface = F.SurfaceSubdomain1D(id=1, x=vertices[0])
right_surface = F.SurfaceSubdomain1D(id=2, x=vertices[-1])

# the ids here are arbitrary in 1D, you can put anything as long as it's not the same as the surfaces
# the ids here are arbitrary in 1D, you can put anything as long as it's
# not the same as the surfaces
my_model.interfaces = [
F.Interface(6, (left_domain, middle_domain)),
F.Interface(7, (middle_domain, right_domain)),
Expand Down
11 changes: 8 additions & 3 deletions examples/multi_material_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def half(x):
)

# Split domain in half and set an interface tag of 5
gdim = mesh.geometry.dim
tdim = mesh.topology.dim
fdim = tdim - 1
top_facets = dolfinx.mesh.locate_entities_boundary(mesh, fdim, top_boundary)
Expand Down Expand Up @@ -125,11 +124,17 @@ def half(x):
from dolfinx.mesh import EntityMap # noqa: F401

legacy_entity_map = False
entity_map_wrapper = lambda e_map: list(e_map.values())

def entity_map_wrapper(e_map):
return list(e_map.values())

entity_maps = [sd.cell_map for sd in my_model.volume_subdomains]
except ImportError:
legacy_entity_map = True
entity_map_wrapper = lambda e_map: e_map

def entity_map_wrapper(e_map):
return e_map

entity_maps = {
sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains
}
Expand Down
9 changes: 6 additions & 3 deletions examples/multi_material_2d_bis.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def half(x):
)

# Split domain in half and set an interface tag of 5
gdim = mesh.geometry.dim
tdim = mesh.topology.dim
fdim = tdim - 1
top_facets = dolfinx.mesh.locate_entities_boundary(mesh, fdim, top_boundary)
Expand Down Expand Up @@ -168,10 +167,14 @@ def half(x):
from dolfinx.mesh import EntityMap # noqa: F401

legacy_entity_map = False
entity_map_wrapper = lambda e_map: list(e_map.values())

def entity_map_wrapper(e_map):
return list(e_map.values())
except ImportError:
legacy_entity_map = True
entity_map_wrapper = lambda e_map: e_map

def entity_map_wrapper(e_map):
return e_map


form = dolfinx.fem.form(
Expand Down
4 changes: 2 additions & 2 deletions examples/multi_material_transient.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
left_surface = F.SurfaceSubdomain1D(id=1, x=vertices[0])
right_surface = F.SurfaceSubdomain1D(id=2, x=vertices[-1])

# the ids here are arbitrary in 1D, you can put anything as long as it's not the same as the surfaces
# TODO remove mesh and meshtags from these arguments
# the ids here are arbitrary in 1D, you can put anything as long as it's not the same
# as the surfaces
my_model.interfaces = [
F.Interface(6, (left_domain, middle_domain)),
F.Interface(7, (middle_domain, right_domain)),
Expand Down
2 changes: 1 addition & 1 deletion examples/surface_reaction_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dolfinx.fem as fem
import matplotlib.pyplot as plt
import numpy as np
import ufl

Expand Down Expand Up @@ -98,7 +99,6 @@ def compute(self, ds):
my_model.initialise()
my_model.run()

import matplotlib.pyplot as plt

plt.stackplot(
H_flux_left.t,
Expand Down
1 change: 1 addition & 0 deletions src/festim/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# ruff: noqa: F401, E402
from importlib import metadata

try:
Expand Down
13 changes: 5 additions & 8 deletions src/festim/advection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@


class AdvectionTerm:
"""
Advection term class
"""Advection term class.

args:
velocity: the velocity field or function
Expand All @@ -22,7 +21,6 @@ class AdvectionTerm:
velocity: the velocity field or function
subdomain: the volume subdomain where the velocity is to be applied
species: the species to which the velocity field is acting on

"""

velocity: fem.Function
Expand Down Expand Up @@ -94,9 +92,8 @@ def species(self, value):


class VelocityField(Value):
"""
A class to handle input values of velocity fields from users and convert them to a
relevent fenics object
"""A class to handle input values of velocity fields from users and convert them to
a relevent fenics object.

Args:
input_value: The value of the user input
Expand Down Expand Up @@ -124,7 +121,7 @@ def convert_input_value(
function_space: fem.FunctionSpace,
t: fem.Constant | None = None,
):
"""Converts a user given value to a relevent fenics object
"""Converts a user given value to a relevent fenics object.

Args:
function_space: the function space of the fenics object
Expand Down Expand Up @@ -165,7 +162,7 @@ def convert_input_value(
nmm_interpolate(self.fenics_object, vel)

def update(self, t: fem.Constant):
"""Updates the velocity field
"""Updates the velocity field.

Args:
t: the time
Expand Down
52 changes: 27 additions & 25 deletions src/festim/boundary_conditions/dirichlet_bc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@


class DirichletBCBase:
"""
Dirichlet boundary condition class
u = value
"""Dirichlet boundary condition class u = value.

Args:
subdomain: The surface subdomain where the boundary condition is applied
Expand All @@ -28,7 +26,6 @@ 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`

"""

subdomain: _subdomain.SurfaceSubdomain
Expand Down Expand Up @@ -67,14 +64,14 @@ def value_fenics(self, value: None | fem.Function | fem.Constant | np.ndarray):
if not isinstance(value, (fem.Function, fem.Constant, np.ndarray)):
# FIXME: Should we allow sending in a callable here?
raise TypeError(
"Value must be a dolfinx.fem.Function, dolfinx.fem.Constant, or a np.ndarray not"
"Value must be a dolfinx.fem.Function, dolfinx.fem.Constant, or a np.ndarray not" # noqa: E501
+ f"{type(value)}"
)
self._value_fenics = value

@property
def time_dependent(self) -> bool:
"""Returns true if the value of the boundary condition is time dependent"""
"""Returns true if the value of the boundary condition is time dependent."""
if self.value is None:
return False
if isinstance(self.value, fem.Constant):
Expand All @@ -92,17 +89,20 @@ def define_surface_subdomain_dofs(
) -> npt.NDArray[np.int32] | tuple[npt.NDArray[np.int32], npt.NDArray[np.int32]]:
"""Defines the facets and the degrees of freedom of the boundary condition.

Given the input meshtags, find all facets matching the boundary condition subdomain ID,
Given the input meshtags, find all facets matching the boundary
condition subdomain ID,
and locate all DOFs associated with the input function space(s).

Note:
For sub-spaces, a tuple of sub-spaces are expected as input, and a tuple of arrays
For sub-spaces, a tuple of sub-spaces are expected as input, and a
tuple of arrays
associated to each of the function spaces are returned.

Args:
facet_meshtags: MeshTags describing some facets in the domain
mesh:
function_space: The function space or a tuple of function spaces: (sub, collapsed)
function_space: The function space or a tuple of function spaces:
(sub, collapsed)
"""
mesh = (
function_space[0].mesh
Expand All @@ -111,11 +111,11 @@ def define_surface_subdomain_dofs(
)
if facet_meshtags.topology != mesh.topology._cpp_object:
raise ValueError(
"Mesh of function-space is not the same as the one used for the meshtags"
"Mesh of function-space is not the same as the one used for the meshtags" # noqa: E501
)
if mesh.topology.dim - 1 != facet_meshtags.dim:
raise ValueError(
f"Meshtags of dimension {facet_meshtags.dim}, expected {mesh.topology.dim - 1}"
f"Meshtags of dimension {facet_meshtags.dim}, expected {mesh.topology.dim - 1}" # noqa: E501
)
bc_dofs = fem.locate_dofs_topological(
function_space, facet_meshtags.dim, facet_meshtags.find(self.subdomain.id)
Expand All @@ -124,7 +124,7 @@ def define_surface_subdomain_dofs(
return bc_dofs

def update(self, t: float):
"""Updates the boundary condition value
"""Updates the boundary condition value.

Args:
t: the time
Expand All @@ -144,11 +144,13 @@ class FixedConcentrationBC(DirichletBCBase):
Args:
subdomain (festim.Subdomain): the surface subdomain where the boundary
condition is applied
value: The value of the boundary condition. It can be a function of space and/or time
value: The value of the boundary condition. It can be a function of
space and/or time
species: The name of the species

Attributes:
temperature_dependent (bool): True if the value of the bc is temperature dependent
temperature_dependent (bool): True if the value of the bc is
temperature dependent

Examples:

Expand Down Expand Up @@ -202,17 +204,18 @@ def create_value(
K_S: fem.Function = None,
):
"""Creates the value of the boundary condition as a fenics object and sets it to
self.value_fenics.
If the value is a constant, it is converted to a `dolfinx.fem.Constant`.
If the value is a function of t, it is converted to `dolfinx.fem.Constant`.
Otherwise, it is converted to a `dolfinx.fem.Function`.Function and the
expression of the function is stored in `bc_expr`.
self.value_fenics. If the value is a constant, it is converted to a
`dolfinx.fem.Constant`. If the value is a function of t, it is converted to
`dolfinx.fem.Constant`. Otherwise, it is converted to a
`dolfinx.fem.Function`.Function and the expression of the function is stored in
`bc_expr`.

Args:
function_space: the function space
temperature: The temperature
t: the time
K_S: The solubility of the species. If provided, the value of the boundary condition
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
Expand Down Expand Up @@ -313,11 +316,10 @@ def create_value(
class FixedTemperatureBC(DirichletBCBase):
def create_value(self, function_space: fem.FunctionSpace, t: fem.Constant):
"""Creates the value of the boundary condition as a fenics object and sets it to
self.value_fenics.
If the value is a constant, it is converted to a `dolfinx.fem.Constant`.
If the value is a function of t, it is converted to a `dolfinx.fem.Constant`.
Otherwise, it is converted to a` dolfinx.fem.Function` and the
expression of the function is stored in `bc_expr`.
self.value_fenics. If the value is a constant, it is converted to a
`dolfinx.fem.Constant`. If the value is a function of t, it is converted to a
`dolfinx.fem.Constant`. Otherwise, it is converted to a` dolfinx.fem.Function`
and the expression of the function is stored in `bc_expr`.

Args:
function_space: the function space
Expand Down
Loading
Loading