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

Export average surface temperature #949

Open
wants to merge 70 commits into
base: fenicsx
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
67277fd
update rtol to make callable in problem
kaelyndunnell Jan 27, 2025
be656dc
adjust default rtol
kaelyndunnell Jan 27, 2025
4e3874c
adjust default rtol
kaelyndunnell Jan 27, 2025
ffa890d
update atol to make callable in problem.py
kaelyndunnell Feb 10, 2025
9ac79df
fix bug
kaelyndunnell Feb 10, 2025
d3fd8a7
add temp export
kaelyndunnell Feb 22, 2025
eb5cdd4
surface temperature export class
kaelyndunnell Feb 23, 2025
77da114
add surfacetemp to festim attribute
kaelyndunnell Feb 23, 2025
9b20f01
update surfacetemperature class
kaelyndunnell Feb 23, 2025
aa813e5
circular import
kaelyndunnell Feb 23, 2025
b9f700a
fix circular import
kaelyndunnell Feb 23, 2025
d4a5e9f
fix surface temperature export
kaelyndunnell Feb 23, 2025
773b291
add post processing surfacetemp update
kaelyndunnell Feb 23, 2025
b3f4488
update compute method for surface temp
kaelyndunnell Feb 23, 2025
3e70f37
fix double count surface temp
kaelyndunnell Feb 24, 2025
d1b71de
typos
kaelyndunnell Feb 24, 2025
d67fa20
Merge branch 'festim-dev:fenicsx' into fenicsx
kaelyndunnell Feb 24, 2025
6a52a39
add surface temperature export class
kaelyndunnell Feb 24, 2025
4e5e68b
add surface temp to derived quantities test
kaelyndunnell Feb 25, 2025
9a9106d
add better doc, add surface temp test
kaelyndunnell Feb 25, 2025
f03ae7d
add pytest to import
kaelyndunnell Feb 25, 2025
aefcdaa
add my_export quantity
kaelyndunnell Feb 25, 2025
806502a
delete extra line
kaelyndunnell Feb 25, 2025
91f1d5b
fix exported value comparison
kaelyndunnell Feb 25, 2025
1e5e2b0
add temp field value to surface temp
kaelyndunnell Feb 25, 2025
7b0ea6d
add temp field setter
kaelyndunnell Feb 25, 2025
528492c
initialise exports
kaelyndunnell Feb 25, 2025
1971774
remove surface temp from derived quantities
kaelyndunnell Feb 25, 2025
7d687de
change func name, add float and int to temp types
kaelyndunnell Feb 26, 2025
37d59f6
test if test or definition problem
kaelyndunnell Feb 26, 2025
98167a0
fix test
kaelyndunnell Feb 26, 2025
a044ecf
fix test
kaelyndunnell Feb 26, 2025
eb486c3
fix temp field setter
kaelyndunnell Feb 26, 2025
e0b1820
fix setter
kaelyndunnell Feb 26, 2025
9e2937e
simplify setter
kaelyndunnell Feb 26, 2025
38a6ae1
testing export.value
kaelyndunnell Feb 26, 2025
7e8d843
update test
kaelyndunnell Feb 26, 2025
f414bd1
update test
kaelyndunnell Feb 26, 2025
66ad788
uodate test
kaelyndunnell Feb 26, 2025
60eb9e7
update test
kaelyndunnell Feb 26, 2025
c1bac95
update test
kaelyndunnell Feb 26, 2025
03148d1
add test
kaelyndunnell Feb 26, 2025
c955d9f
black formatted
kaelyndunnell Feb 26, 2025
8c2f0bf
add test for title
kaelyndunnell Feb 26, 2025
f6b5ff6
black formatted
kaelyndunnell Feb 26, 2025
339a94a
additional tests
kaelyndunnell Feb 26, 2025
e960b5a
black formatted
kaelyndunnell Feb 26, 2025
97b3b17
add mesh, fix temp_field name
kaelyndunnell Feb 26, 2025
c69e971
fix failing tests
kaelyndunnell Feb 26, 2025
134a8ff
temperature cannot be a string
kaelyndunnell Feb 26, 2025
e1ed3bd
Update src/festim/exports/surface_temperature.py
kaelyndunnell Mar 2, 2025
38d68c7
delete unneeded lines when inherit from F.SurfaceQuantity
kaelyndunnell Mar 2, 2025
baa374d
also inherited now
kaelyndunnell Mar 2, 2025
ecf4532
also inherited
kaelyndunnell Mar 2, 2025
8ef1981
remove old line
kaelyndunnell Mar 2, 2025
dd3ed99
rename to AverageSurfaceTemperature
kaelyndunnell Mar 2, 2025
15fe0ad
set temp field as an attribute
kaelyndunnell Mar 2, 2025
3454d35
fix surfacequantity inheritance
kaelyndunnell Mar 2, 2025
96bf5dd
truncate computation of AverageSurfaceTemperature in hydrogentranspor…
kaelyndunnell Mar 2, 2025
78d34ce
fix festim init
kaelyndunnell Mar 2, 2025
e2b7b9a
renamed class
kaelyndunnell Mar 2, 2025
f0123dc
remove temp field from arguments
kaelyndunnell Mar 2, 2025
7ede0ec
remove unneeded test
kaelyndunnell Mar 2, 2025
b542a18
fix if statement
kaelyndunnell Mar 2, 2025
b774070
add line
kaelyndunnell Mar 2, 2025
fe8f5c6
add test line, simply HTP
kaelyndunnell Mar 2, 2025
b1d7ec7
fix test
kaelyndunnell Mar 2, 2025
352fb85
fix temp line
kaelyndunnell Mar 2, 2025
7fb1fc1
simplify HTP
kaelyndunnell Mar 2, 2025
e531a88
ruff formatted
kaelyndunnell Mar 2, 2025
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
1 change: 1 addition & 0 deletions src/festim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from .exports.minimum_volume import MinimumVolume
from .exports.surface_flux import SurfaceFlux
from .exports.surface_quantity import SurfaceQuantity
from .exports.surface_temperature import AverageSurfaceTemperature
from .exports.total_surface import TotalSurface
from .exports.total_volume import TotalVolume
from .exports.volume_quantity import VolumeQuantity
Expand Down
2 changes: 2 additions & 0 deletions src/festim/exports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
"AverageSurface",
"AverageVolume",
"TotalVolume",
"AverageSurfaceTemperature",
]

from .average_surface import AverageSurface
from .average_volume import AverageVolume
from .surface_flux import SurfaceFlux
from .surface_quantity import SurfaceQuantity
from .surface_temperature import AverageSurfaceTemperature
from .total_surface import TotalSurface
from .total_volume import TotalVolume
from .volume_quantity import VolumeQuantity
Expand Down
51 changes: 51 additions & 0 deletions src/festim/exports/surface_temperature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import csv
from dolfinx import fem
import ufl
from .surface_quantity import SurfaceQuantity


class AverageSurfaceTemperature(SurfaceQuantity):
"""Exports the average temperature on a given surface.

Args:
surface (int or festim.SurfaceSubdomain): the surface subdomain
filename (str, optional): name of the file to which the average surface temperature is exported

Attributes:
temperature_field (fem.Constant or fem.Function): 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
"""

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

surface_integral = fem.assemble_scalar(
fem.form(temperature_field * ds(self.surface.id))
) # integral over surface

surface_area = fem.assemble_scalar(fem.form(1 * ds(self.surface.id)))

self.value = surface_integral / surface_area # avg temp

self.data.append(self.value)
14 changes: 13 additions & 1 deletion src/festim/hydrogen_transport_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@
a string, find species object in self.species"""

for export in self.exports:
if isinstance(export, exports.AverageSurfaceTemperature):
continue

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

View check run for this annotation

Codecov / codecov/patch

src/festim/hydrogen_transport_problem.py#L374

Added line #L374 was not covered by tests
# if name of species is given then replace with species object
if isinstance(export.field, list):
for idx, field in enumerate(export.field):
Expand Down Expand Up @@ -415,6 +418,9 @@
export.D = D
export.D_expr = D_expr

if isinstance(export, exports.AverageSurfaceTemperature):
export.temperature_field = self.temperature_fenics
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be tested!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below about integration test


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

View check run for this annotation

Codecov / codecov/patch

src/festim/hydrogen_transport_problem.py#L423

Added line #L423 was not covered by tests
# reset the data and time for SurfaceQuantity and VolumeQuantity
if isinstance(export, (exports.SurfaceQuantity, exports.VolumeQuantity)):
export.t = []
Expand Down Expand Up @@ -805,7 +811,12 @@
if isinstance(export, exports.SurfaceQuantity):
if isinstance(
export,
(exports.SurfaceFlux, exports.TotalSurface, exports.AverageSurface),
(
exports.SurfaceFlux,
exports.TotalSurface,
exports.AverageSurface,
exports.AverageSurfaceTemperature,
),
):
export.compute(
self.ds,
Expand All @@ -818,6 +829,7 @@
# if filename given write export data to file
if export.filename is not None:
export.write(t=float(self.t))

elif isinstance(export, exports.VolumeQuantity):
if isinstance(export, (exports.TotalVolume, exports.AverageVolume)):
export.compute(self.dx)
Expand Down
191 changes: 191 additions & 0 deletions test/test_surface_temperature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
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=6)
dummy_volume = F.VolumeSubdomain1D(
id=1, borders=[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)

my_model = F.HydrogenTransportProblem(
mesh=my_mesh,
temperature=T_function,
)
my_model.t = fem.Constant(my_model.mesh.mesh, 0.0)
dt = fem.Constant(my_mesh.mesh, 1.0)

my_model.define_temperature()
my_model.initialise_exports()

# RUN
for i in range(3):
my_model.t.value += dt.value
my_model.update_time_dependent_values()

my_export = F.AverageSurfaceTemperature(surface=dummy_surface)
my_export.temperature_field = my_model.temperature_fenics
my_export.compute(ds)
Comment on lines +49 to +51
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, but we also need to test the full integration with HydrogenTransportProblem ie. just do

my_model.exports = [....]
my_model.initialise()
my_model.run()

# test value of export after 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_write_overwrite(tmp_path):
"""Test that the write method overwrites the file if it already exists"""
filename = os.path.join(tmp_path, "my_export.csv")
my_model = F.HydrogenTransportProblem(
mesh=F.Mesh1D(np.linspace(0, 6.0, 10000)), temperature=500
)
my_model.define_temperature()

my_export = F.AverageSurfaceTemperature(
filename=filename,
surface=F.SurfaceSubdomain1D(id=35, x=1),
)
my_export.value = 2.0
my_export.write(0)
my_export.write(1)

my_export2 = F.AverageSurfaceTemperature(
filename=filename,
surface=F.SurfaceSubdomain1D(id=1, x=1),
)
my_export2.value = 3.0
my_export2.write(1)
my_export2.write(2)
my_export2.write(3)

data = np.genfromtxt(filename, delimiter=",", names=True)
file_length = data.size
expected_length = 3

assert file_length == expected_length


def test_filename_setter_raises_TypeError():
"""Test that a TypeError is raised when the filename is not a string"""

with pytest.raises(TypeError, match="filename must be of type str"):
my_model = F.HydrogenTransportProblem(
mesh=F.Mesh1D(np.linspace(0, 6.0, 10000)), temperature=500
)
my_model.define_temperature()

F.AverageSurfaceTemperature(
filename=1,
surface=F.SurfaceSubdomain1D(id=1, x=1),
)


def test_filename_setter_raises_ValueError(tmp_path):
"""Test that a ValueError is raised when the filename does not end with .csv or .txt"""

with pytest.raises(ValueError):
my_model = F.HydrogenTransportProblem(
mesh=F.Mesh1D(np.linspace(0, 6.0, 10000)), temperature=500
)
my_model.define_temperature()

F.AverageSurfaceTemperature(
filename=os.path.join(tmp_path, "my_export.xdmf"),
surface=F.SurfaceSubdomain1D(id=1, x=1),
)


@pytest.mark.parametrize("value", ["my_export.csv", "my_export.txt"])
def test_writer(tmp_path, value):
"""Test that the writes values at each timestep to either 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=1, x=0),
)
my_export.value = 2.0

for i in range(10):
my_export.write(i)
file_length = len(np.genfromtxt(my_export.filename, delimiter=","))

expected_length = i + 2

assert file_length == expected_length


def test_surface_setter_raises_TypeError():
"""Test that a TypeError is raised when the surface is not a
F.SurfaceSubdomain"""

with pytest.raises(
TypeError, match="surface should be an int or F.SurfaceSubdomain"
):
my_model = F.HydrogenTransportProblem(
mesh=F.Mesh1D(np.linspace(0, 6.0, 10000)), temperature=500
)
my_model.define_temperature()
F.AverageSurfaceTemperature(
surface="1",
)
Comment on lines +93 to +191
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests aren't need as it tests the functionality in the parent class SurfaceQuantity

Loading