Repository navigation
Add left and right surface properties to VolumeSubdomain1D - #1282
user-name-owen wants to merge 11 commits into
Conversation
Remove misplaced file
Remove misplaced file
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1282 +/- ##
=======================================
Coverage 96.07% 96.07%
=======================================
Files 57 57
Lines 5069 5075 +6
=======================================
+ Hits 4870 4876 +6
Misses 199 199
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Hi @user-name-owen , welcome to FESTIM and congrats on your first PR request (I was in your shoes not too long ago!). Thanks for adding this. I can review soon. |
ee-nn
left a comment
There was a problem hiding this comment.
@user-name-owen thanks for this and congrats on your first PR! I've left some review comments. The biggest issue is that the current changes don't run when I test them locally.
Also, adding a few tweaks to the documentation to reflect these changes could be great.
| Returns: | ||
| festim.SurfaceSubdomain1D: the left surface subdomain | ||
| """ | ||
| return SurfaceSubdomain1D(id=-1, x=self.borders[0]) |
There was a problem hiding this comment.
Negative integers shouldn't be used here, (-1) will index all SurfaceSubdomain objects when being used in integration terms (i.e. ds(-1) will grab all domains.) The current changes also fail outright with (-2), since DOLFINx can't accept negative ids:
import numpy as np
import festim as F
model = F.HydrogenTransportProblem()
model.mesh = F.Mesh1D(np.linspace(0, 1e-3, 1001))
steel = F.Material(D_0=1e-7, E_D=0.2)
bulk = F.VolumeSubdomain1D(1, borders=[0, 1e-3], material=steel)
left = bulk.left
right = bulk.right
model.subdomains = [bulk, left, right]
T = F.Species("T")
model.species = [T]
model.temperature = 600
model.boundary_conditions = [
F.FixedConcentrationBC(left, value=1e20, species=T),
F.FixedConcentrationBC(right, value=0, species=T),
]
model.exports = [F.SurfaceFlux(field=T, surface=right)]
model.settings = F.Settings(atol=1e-10, rtol=1e-10, transient=False)
model.initialise()
model.run()ValueError: Integral subdomain IDs must be non-negative.
There was a problem hiding this comment.
Thanks for the review! For the ids, I'd like to propose following the same convention as _allocate_manifold_side_ids: auto-generated surfaces get id=None on creation, and ids are allocated in define_meshtags_and_measures (before facet tagging) starting from max(declared ids) + 1, so they can never collide with user-declared surfaces, interfaces or volumes. Happy to hear if you'd prefer a different scheme.
There was a problem hiding this comment.
Hi @user-name-owen sorry for the delayed response on this, yes this sounds like a much better scheme! Let me know when you have made the corresponding updates.
There was a problem hiding this comment.
Both fixed:
- Switched to
@cached_property, sobulk.left/bulk.rightnow always return the same object. - Auto-generated surfaces carry
id=Noneon creation; ids are allocated indefine_meshtags_and_measuresabove every declared id (following the_allocate_manifold_side_idsconvention), so they are always non-negative and cannot clash with user-declared ones. The reproducer from your review now runs to completion.
| ) | ||
| self.borders = borders | ||
|
|
||
| @property |
There was a problem hiding this comment.
Using @property here will create a new instance of SurfaceSubdomain1D on every direct access. Therefore, if the user calls bulk.left in one instance and then tries to call it again in another, they will not be accessing the same object, even though this is the expected behavior. You can used @cached_property (from functools import cached_property) to get around this
There was a problem hiding this comment.
Also fixed — see my reply in the thread above: the properties now use @cached_property.
| ) | ||
|
|
||
|
|
||
| def test_left_and_right_surfaces(): |
There was a problem hiding this comment.
Test will need to updated accordingly, see above comments
There was a problem hiding this comment.
Updated accordingly — the test no longer asserts specific ids, and a new test_left_and_right_surfaces_get_auto_ids checks that ids are allocated above user-declared ones after initialisation.
|
All points are addressed and pushed:
Also updated the branch with the latest main. Ready for re-review when you have time. Thanks! |
| @cached_property | ||
| def left(self): | ||
| """The left surface of the 1D volume subdomain. | ||
|
|
||
| Returns: | ||
| festim.SurfaceSubdomain1D: the left surface subdomain | ||
| festim.SurfaceSubdomain1D: the left surface subdomain. Its id is | ||
| automatically allocated when the model is initialised | ||
| """ | ||
| return SurfaceSubdomain1D(id=-1, x=self.borders[0]) | ||
| return SurfaceSubdomain1D(id=None, x=self.borders[0]) | ||
|
|
||
| @property | ||
| @cached_property | ||
| def right(self): | ||
| """The right surface of the 1D volume subdomain. | ||
|
|
||
| Returns: | ||
| festim.SurfaceSubdomain1D: the right surface subdomain | ||
| festim.SurfaceSubdomain1D: the right surface subdomain. Its id is | ||
| automatically allocated when the model is initialised | ||
| """ | ||
| return SurfaceSubdomain1D(id=-2, x=self.borders[1]) | ||
| return SurfaceSubdomain1D(id=None, x=self.borders[1]) |
There was a problem hiding this comment.
@user-name-owen @ee-nn how does it work if right is cached but in the meantime self.borders change? say
vol = F.VolumeSubdomain1D(..., borders=[1, 2])
print(vol.right.x) # output: 2
vol.borders = [2, 3]
print(vol.right.x) # output: ????There was a problem hiding this comment.
maybe this is an edge case we don't have to consider at all. I've never seen anyone change the borders of a domain programmatically like this
Description
Summary
For 1D problems,
VolumeSubdomain1Dalready knows itsborders, so manuallydefining the left/right
SurfaceSubdomain1Dobjects is redundant. This addsleftandrightproperties that build them automatically:Related Issues
Fixes #1280
Motivation and Context
The generated surfaces use ids -1 (left) and -2 (right), which cannot collide
with user-defined positive ids.