-
Notifications
You must be signed in to change notification settings - Fork 35
Export average surface temperature #949
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
base: fenicsx
Are you sure you want to change the base?
Changes from all commits
67277fd
be656dc
4e3874c
ffa890d
9ac79df
d3fd8a7
eb5cdd4
77da114
9b20f01
aa813e5
b9f700a
d4a5e9f
773b291
b3f4488
3e70f37
d1b71de
d67fa20
6a52a39
4e5e68b
9a9106d
f03ae7d
aefcdaa
806502a
91f1d5b
1e5e2b0
7b0ea6d
528492c
1971774
7d687de
37d59f6
98167a0
a044ecf
eb486c3
e0b1820
9e2937e
38a6ae1
7e8d843
f414bd1
66ad788
60eb9e7
c1bac95
03148d1
c955d9f
8c2f0bf
f6b5ff6
339a94a
e960b5a
97b3b17
c69e971
134a8ff
e1ed3bd
38d68c7
baa374d
ecf4532
8ef1981
dd3ed99
15fe0ad
3454d35
96bf5dd
78d34ce
e2b7b9a
f0123dc
7ede0ec
b542a18
b774070
fe8f5c6
b1d7ec7
352fb85
7fb1fc1
e531a88
bc9aa19
2b2c38a
2af4b73
a722253
b9795ba
c568c21
d1eeb8b
5b36778
dc51fb6
0bcd616
b331392
d268289
a9e9e20
262a912
b592a68
0e2fa61
c7b5464
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import csv | ||
| from dolfinx import fem | ||
| import ufl | ||
| from .surface_quantity import SurfaceQuantity | ||
| from festim.subdomain.surface_subdomain import SurfaceSubdomain | ||
|
|
||
|
|
||
| class AverageSurfaceTemperature(SurfaceQuantity): | ||
| """Exports the average temperature on a given surface. | ||
|
|
||
| Args: | ||
| surface: the surface subdomain | ||
| filename: name of the file to which the average surface temperature is exported | ||
|
|
||
| Attributes: | ||
| temperature_field: the temperature field | ||
| surface (int or festim.SurfaceSubdomain): the surface subdomain | ||
| filename (str): name of the file to which the surface temperature is exported | ||
| t (list): list of time values | ||
| data (list): list of average temperature values on the surface | ||
| """ | ||
|
|
||
| surface: int | SurfaceSubdomain | ||
| filename: str | None | ||
|
|
||
| temperature_field: fem.Constant | fem.Function | ||
|
|
||
| def __init__(self, surface, filename: str = None) -> None: | ||
| self.surface = surface | ||
| self.filename = filename | ||
|
|
||
| self.temperature_field = None | ||
| self.t = [] | ||
| self.data = [] | ||
| self._first_time_export = True | ||
|
|
||
| @property | ||
| def title(self): | ||
| return f"Temperature surface {self.surface.id}" | ||
|
|
||
| def compute(self, ds): | ||
| """Computes the average temperature on the surface. | ||
|
|
||
| Args: | ||
| ds (ufl.Measure): surface measure of the model | ||
| """ | ||
| temperature_field = self.temperature_field | ||
|
|
||
| self.value = fem.assemble_scalar( | ||
| fem.form(temperature_field * ds(self.surface.id)) | ||
| ) / fem.assemble_scalar( | ||
| fem.form(1 * ds(self.surface.id)) | ||
| ) # integral over surface / surface area | ||
|
|
||
| self.data.append(self.value) | ||
|
Comment on lines
41
to
55
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might not be needed if we inherit from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we still do cause this will fail if field isn't of type F.Species (even setting it to None in init made things fail) |
||
RemDelaporteMathurin marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| import numpy as np | ||
| import ufl | ||
| from dolfinx import fem | ||
| import pytest | ||
| import os | ||
|
|
||
| import festim as F | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "T_function, expected_values", | ||
| [ | ||
| (3, 3), | ||
| (lambda t: t, 3.0), | ||
| (lambda x, t: 1.0 + x[0] + t, 10.0), | ||
| ], | ||
| ) | ||
| def test_surface_temperature_compute_1D(T_function, expected_values): | ||
| """Test that the average surface temperature export computes the correct value.""" | ||
|
|
||
| # BUILD | ||
| L = 6.0 | ||
| my_mesh = F.Mesh1D(np.linspace(0, L, 10000)) | ||
| dummy_surface = F.SurfaceSubdomain1D(id=1, x=L) | ||
| dummy_volume = F.VolumeSubdomain1D( | ||
| id=1, borders=(0.0, L), material=F.Material(D_0=1, E_D=1, name="dummy") | ||
| ) | ||
|
|
||
| facet_meshtags, temp = my_mesh.define_meshtags( | ||
| surface_subdomains=[dummy_surface], volume_subdomains=[dummy_volume] | ||
| ) | ||
| ds = ufl.Measure("ds", domain=my_mesh.mesh, subdomain_data=facet_meshtags) | ||
|
|
||
| dt = F.Stepsize(initial_value=1) | ||
| settings = F.Settings(atol=1e05, rtol=1e-10, stepsize=dt, final_time=10) | ||
| my_model = F.HydrogenTransportProblem( | ||
| mesh=my_mesh, temperature=T_function, settings=settings | ||
| ) | ||
|
|
||
| my_model.species = [F.Species("H")] | ||
| my_model.subdomains = [ | ||
| dummy_surface, | ||
| dummy_volume, | ||
| ] | ||
|
|
||
| my_model.t = fem.Constant(my_mesh.mesh, 0.0) | ||
| dt = fem.Constant(my_mesh.mesh, 1.0) | ||
|
|
||
| my_model.define_temperature() | ||
|
|
||
| my_export = F.AverageSurfaceTemperature(surface=dummy_surface) | ||
| my_export.temperature_field = my_model.temperature_fenics | ||
| my_model.exports = [my_export] | ||
|
|
||
| # RUN | ||
| for _ in range(3): | ||
| my_model.t.value += dt.value | ||
| my_model.update_time_dependent_values() | ||
|
|
||
| my_model.initialise() | ||
| my_model.run() | ||
|
|
||
| # TEST | ||
| assert np.isclose(my_export.value, expected_values) | ||
|
|
||
|
|
||
| def test_title(tmp_path): | ||
| surf_1 = F.SurfaceSubdomain(id=1) | ||
| results = "test.csv" | ||
| temp = 400 | ||
| surface_temp = F.AverageSurfaceTemperature(surface=surf_1, filename=results) | ||
|
|
||
| my_model = F.HydrogenTransportProblem( | ||
| temperature=temp, | ||
| ) | ||
| surface_temp.filename = os.path.join(tmp_path, "test.csv") | ||
| surface_temp.value = 1 | ||
|
|
||
| assert surface_temp.title == "Temperature surface 1" | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("value", ["my_export.csv", "my_export.txt"]) | ||
| def test_title_generation(tmp_path, value): | ||
| """Test that the title is made to be written to the header in a csv or txt file""" | ||
| my_model = F.HydrogenTransportProblem( | ||
| mesh=F.Mesh1D(np.linspace(0, 6.0, 10000)), temperature=500 | ||
| ) | ||
| my_model.define_temperature() | ||
|
|
||
| my_export = F.AverageSurfaceTemperature( | ||
| filename=os.path.join(tmp_path, f"{value}"), | ||
| surface=F.SurfaceSubdomain1D(id=35, x=1), | ||
| ) | ||
| my_export.value = 2.0 | ||
| my_export.write(0) | ||
| title = np.genfromtxt(my_export.filename, delimiter=",", max_rows=1, dtype=str) | ||
|
|
||
| expected_title = "Temperature surface 35" | ||
|
|
||
| assert title[1] == expected_title | ||
|
|
||
|
|
||
| def test_not_implemented_error_raised_with_initialise_exports_multiple_subdomains(): | ||
| """Test that NotImplementedError is raised for problems with multiple volume domains.""" | ||
|
|
||
| # BUILD | ||
| L = 1.0 | ||
| test_mesh = F.Mesh1D(vertices=np.linspace(0, L, num=101)) | ||
|
|
||
| my_mat = F.Material(D_0=1, E_D=1) | ||
| dummy_surface = F.SurfaceSubdomain1D(id=1, x=L) | ||
| vol_1 = F.VolumeSubdomain1D(id=1, borders=[0, 0.5], material=my_mat) | ||
| vol_2 = F.VolumeSubdomain1D(id=1, borders=[0.5, L], material=my_mat) | ||
|
|
||
| H = F.Species("H") | ||
| my_model = F.HydrogenTransportProblemDiscontinuous( | ||
| mesh=test_mesh, | ||
| temperature=10, | ||
| subdomains=[dummy_surface, vol_1, vol_2], | ||
| species=[F.Species("H")], | ||
| ) | ||
|
|
||
| my_model.exports = [F.AverageSurfaceTemperature(surface=dummy_surface)] | ||
|
|
||
| # TEST | ||
| with pytest.raises(NotImplementedError): | ||
| my_model.initialise_exports() |
Uh oh!
There was an error while loading. Please reload this page.