Skip to content

Commit ac60724

Browse files
committed
Rename to Value, work with temperature only classes
1 parent 06b1dab commit ac60724

11 files changed

+447
-374
lines changed

src/festim/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@
3636
from .exports.vtx import VTXSpeciesExport, VTXTemperatureExport
3737
from .exports.xdmf import XDMFExport
3838
from .heat_transfer_problem import HeatTransferProblem
39-
from .helpers import as_fenics_constant, ConvertToFenicsObject
39+
from .helpers import (
40+
as_fenics_constant,
41+
as_mapped_function,
42+
as_fenics_interpolation_expression,
43+
as_fenics_interp_expr_and_function,
44+
Value,
45+
)
4046
from .hydrogen_transport_problem import (
4147
HTransportProblemDiscontinuous,
4248
HydrogenTransportProblem,

src/festim/boundary_conditions/dirichlet_bc.py

Lines changed: 48 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -49,38 +49,22 @@ def __init__(
4949
self.subdomain = subdomain
5050
self.value = value
5151

52-
self.value_fenics = helpers.ConvertToFenicsObject(value)
53-
# self.bc_expr = None
54-
55-
# @property
56-
# def value_fenics(self):
57-
# return self._value_fenics
58-
59-
# @value_fenics.setter
60-
# def value_fenics(self, value: None | fem.Function | fem.Constant | np.ndarray):
61-
# if value is None:
62-
# self._value_fenics = value
63-
# return
64-
# if not isinstance(value, (fem.Function, fem.Constant, np.ndarray)):
65-
# # FIXME: Should we allow sending in a callable here?
66-
# raise TypeError(
67-
# "Value must be a dolfinx.fem.Function, dolfinx.fem.Constant, or a np.ndarray not"
68-
# + f"{type(value)}"
69-
# )
70-
# self._value_fenics = value
71-
72-
# @property
73-
# def time_dependent(self) -> bool:
74-
# """Returns true if the value of the boundary condition is time dependent"""
75-
# if self.value is None:
76-
# return False
77-
# if isinstance(self.value, fem.Constant):
78-
# return False
79-
# if callable(self.value):
80-
# arguments = self.value.__code__.co_varnames
81-
# return "t" in arguments
82-
# else:
83-
# return False
52+
@property
53+
def value(self):
54+
return self._value
55+
56+
@value.setter
57+
def value(self, value):
58+
if value is None:
59+
self._value = value
60+
elif isinstance(value, (float, int, fem.Constant, fem.Function)):
61+
self._value = helpers.Value(value)
62+
elif callable(value):
63+
self._value = helpers.Value(value)
64+
else:
65+
raise TypeError(
66+
"Value must be a float, int, fem.Constant, fem.Function, or callable"
67+
)
8468

8569
def define_surface_subdomain_dofs(
8670
self,
@@ -120,19 +104,6 @@ def define_surface_subdomain_dofs(
120104

121105
return bc_dofs
122106

123-
# def update(self, t: float):
124-
# """Updates the boundary condition value
125-
126-
# Args:
127-
# t (float): the time
128-
# """
129-
# if callable(self.value):
130-
# arguments = self.value.__code__.co_varnames
131-
# if isinstance(self.value_fenics, fem.Constant) and "t" in arguments:
132-
# self.value_fenics.value = self.value(t=t)
133-
# else:
134-
# self.value_fenics.interpolate(self.bc_expr)
135-
136107

137108
class FixedConcentrationBC(DirichletBCBase):
138109
"""
@@ -174,122 +145,42 @@ def __init__(
174145
self.species = species
175146
super().__init__(subdomain, value)
176147

177-
# @property
178-
# def temperature_dependent(self):
179-
# if self.value is None:
180-
# return False
181-
# if isinstance(self.value, fem.Constant):
182-
# return False
183-
# if callable(self.value):
184-
# arguments = self.value.__code__.co_varnames
185-
# return "T" in arguments
186-
# else:
187-
# return False
188-
189-
# def create_value(
190-
# self,
191-
# function_space: fem.FunctionSpace,
192-
# temperature: float | fem.Constant,
193-
# t: float | fem.Constant,
194-
# ):
195-
# """Creates the value of the boundary condition as a fenics object and sets it to
196-
# self.value_fenics.
197-
# If the value is a constant, it is converted to a `dolfinx.fem.Constant`.
198-
# If the value is a function of t, it is converted to `dolfinx.fem.Constant`.
199-
# Otherwise, it is converted to a `dolfinx.fem.Function`.Function and the
200-
# expression of the function is stored in `bc_expr`.
201-
202-
# Args:
203-
# function_space (dolfinx.fem.FunctionSpace): the function space
204-
# temperature: The temperature
205-
# t (dolfinx.fem.Constant): the time
206-
# """
207-
# mesh = function_space.mesh
208-
# x = ufl.SpatialCoordinate(mesh)
209-
210-
# if isinstance(self.value, (int, float)):
211-
# self.value_fenics = helpers.as_fenics_constant(mesh=mesh, value=self.value)
212-
213-
# elif callable(self.value):
214-
# arguments = self.value.__code__.co_varnames
215-
216-
# if "t" in arguments and "x" not in arguments and "T" not in arguments:
217-
# # only t is an argument
218-
# if not isinstance(self.value(t=float(t)), (float, int)):
219-
# raise ValueError(
220-
# "self.value should return a float or an int, not "
221-
# + f"{type(self.value(t=float(t)))} "
222-
# )
223-
# self.value_fenics = helpers.as_fenics_constant(
224-
# mesh=mesh, value=self.value(t=float(t))
225-
# )
226-
# else:
227-
# self.value_fenics = fem.Function(function_space)
228-
# kwargs = {}
229-
# if "t" in arguments:
230-
# kwargs["t"] = t
231-
# if "x" in arguments:
232-
# kwargs["x"] = x
233-
# if "T" in arguments:
234-
# kwargs["T"] = temperature
235-
236-
# # store the expression of the boundary condition
237-
# # to update the value_fenics later
238-
# self.bc_expr = fem.Expression(
239-
# self.value(**kwargs),
240-
# function_space.element.interpolation_points(),
241-
# )
242-
# self.value_fenics.interpolate(self.bc_expr)
243-
244148

245149
# alias for FixedConcentrationBC
246150
DirichletBC = FixedConcentrationBC
247151

248152

249153
class FixedTemperatureBC(DirichletBCBase):
250-
def create_value(self, function_space: fem.FunctionSpace, t: fem.Constant):
251-
"""Creates the value of the boundary condition as a fenics object and sets it to
252-
self.value_fenics.
253-
If the value is a constant, it is converted to a `dolfinx.fem.Constant`.
254-
If the value is a function of t, it is converted to a `dolfinx.fem.Constant`.
255-
Otherwise, it is converted to a` dolfinx.fem.Function` and the
256-
expression of the function is stored in `bc_expr`.
154+
"""
155+
Args:
156+
subdomain (festim.Subdomain): the surface subdomain where the boundary
157+
condition is applied
158+
value: The value of the boundary condition. It can be a function of space and/or time
257159
258-
Args:
259-
function_space: the function space
260-
t: the time
261-
"""
262-
mesh = function_space.mesh
263-
x = ufl.SpatialCoordinate(mesh)
264-
265-
if isinstance(self.value, (int, float)):
266-
self.value_fenics = helpers.as_fenics_constant(mesh=mesh, value=self.value)
267-
268-
elif callable(self.value):
269-
arguments = self.value.__code__.co_varnames
270-
271-
if "t" in arguments and "x" not in arguments:
272-
# only t is an argument
273-
if not isinstance(self.value(t=float(t)), (float, int)):
274-
raise ValueError(
275-
"self.value should return a float or an int, not "
276-
+ f"{type(self.value(t=float(t)))} "
277-
)
278-
self.value_fenics = helpers.as_fenics_constant(
279-
mesh=mesh, value=self.value(t=float(t))
280-
)
281-
else:
282-
self.value_fenics = fem.Function(function_space)
283-
kwargs = {}
284-
if "t" in arguments:
285-
kwargs["t"] = t
286-
if "x" in arguments:
287-
kwargs["x"] = x
288-
289-
# store the expression of the boundary condition
290-
# to update the value_fenics later
291-
self.bc_expr = fem.Expression(
292-
self.value(**kwargs),
293-
function_space.element.interpolation_points(),
294-
)
295-
self.value_fenics.interpolate(self.bc_expr)
160+
Examples:
161+
162+
.. highlight:: python
163+
.. code-block:: python
164+
165+
from festim import FixedTemperatureBC
166+
FixedTemperatureBC(subdomain=my_subdomain, value=1)
167+
FixedTemperatureBC(subdomain=my_subdomain,
168+
value=lambda x: 1 + x[0])
169+
FixedTemperatureBC(subdomain=my_subdomain,
170+
value=lambda t: 1 + t)
171+
FixedTemperatureBC(subdomain=my_subdomain,
172+
value=lambda x, t: 1 + x[0] + t)
173+
174+
"""
175+
176+
def __init__(
177+
self,
178+
subdomain: _subdomain.SurfaceSubdomain,
179+
value: np.ndarray | fem.Constant | int | float | Callable,
180+
):
181+
super().__init__(subdomain, value)
182+
183+
if self.value.temperature_dependent:
184+
raise ValueError(
185+
"Temperature dependent boundary conditions are not supported for FixedTemperatureBC"
186+
)

src/festim/boundary_conditions/flux_bc.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import numpy as np
2-
import ufl
31
from dolfinx import fem
42

53
import festim as F
@@ -34,7 +32,22 @@ def __init__(self, subdomain, value):
3432
self.subdomain = subdomain
3533
self.value = value
3634

37-
self.value_fenics = F.ConvertToFenicsObject(value)
35+
@property
36+
def value(self):
37+
return self._value
38+
39+
@value.setter
40+
def value(self, value):
41+
if value is None:
42+
self._value = value
43+
elif isinstance(value, (float, int, fem.Constant, fem.Function)):
44+
self._value = F.Value(value)
45+
elif callable(value):
46+
self._value = F.Value(value)
47+
else:
48+
raise TypeError(
49+
"Value must be a float, int, fem.Constant, fem.Function, or callable"
50+
)
3851

3952

4053
class ParticleFluxBC(FluxBCBase):
@@ -118,3 +131,6 @@ class HeatFluxBC(FluxBCBase):
118131

119132
def __init__(self, subdomain, value):
120133
super().__init__(subdomain=subdomain, value=value)
134+
135+
if self.value.temperature_dependent:
136+
raise ValueError("Heat flux cannot be temperature dependent")

0 commit comments

Comments
 (0)