11import warnings
22from pathlib import Path
3+ from typing import Optional
34
4- from dolfinx import fem
5+ import numpy as np
6+ from dolfinx import fem , io
57
6- from festim .species import Species as _Species
7- from festim .subdomain .volume_subdomain import (
8- VolumeSubdomain as _VolumeSubdomain ,
9- )
8+ from festim .species import Species
9+ from festim .subdomain .volume_subdomain import VolumeSubdomain
1010
1111
1212class ExportBaseClass :
13+ """Export functions to VTX file
14+
15+ Args:
16+ filename: The name of the output file
17+ times: if provided, the field will be exported at these timesteps. Otherwise
18+ exports at all timesteps. Defaults to None.
19+
20+ Attributes:
21+ filename: The name of the output file
22+ times: if provided, the field will be exported at these timesteps. Otherwise
23+ exports at all timesteps. Defaults to None.
24+ """
25+
1326 _filename : Path | str
27+ writer : io .VTXWriter
1428
15- def __init__ (self , filename : str | Path , ext : str ) -> None :
29+ def __init__ (
30+ self ,
31+ filename : str | Path ,
32+ ext : str ,
33+ times : Optional [list [float ] | list [int ] | None ] = None ,
34+ ):
1635 name = Path (filename )
1736 if name .suffix != ext :
1837 warnings .warn (
@@ -21,86 +40,141 @@ def __init__(self, filename: str | Path, ext: str) -> None:
2140 name = name .with_suffix (ext )
2241
2342 self ._filename = name
43+ if times :
44+ self .times = sorted (times )
45+ else :
46+ self .times = times
2447
2548 @property
2649 def filename (self ):
2750 return self ._filename
2851
52+ def is_it_time_to_export (self , current_time : float ) -> bool :
53+ """
54+ Checks if the exported field should be written to a file or not based on the
55+ current time and the times in `export.times`
56+
57+ Args:
58+ current_time: the current simulation time
59+
60+ Returns:
61+ bool: True if the exported field should be written to a file, else False
62+ """
63+
64+ if self .times is None :
65+ return True
66+
67+ for time in self .times :
68+ if np .isclose (time , current_time , atol = 0 ):
69+ return True
70+
71+ return False
72+
2973
3074class VTXTemperatureExport (ExportBaseClass ):
31- def __init__ (self , filename : str | Path ):
32- super ().__init__ (filename , ".bp" )
75+ """Export temperature field functions to VTX file
76+
77+ Args:
78+ filename: The name of the output file
79+ times: if provided, the field will be exported at these timesteps. Otherwise
80+ exports at all timesteps. Defaults to None.
81+
82+ Attributes:
83+ filename: The name of the output file
84+ times: if provided, the field will be exported at these timesteps. Otherwise
85+ exports at all timesteps. Defaults to None.
86+ writer: The VTXWriter object used to write the file
87+ """
88+
89+ writer : io .VTXWriter
90+
91+ def __init__ (
92+ self ,
93+ filename : str | Path ,
94+ times : Optional [list [float ] | list [int ] | None ] = None ,
95+ ):
96+ super ().__init__ (filename , ".bp" , times )
3397
3498
3599class VTXSpeciesExport (ExportBaseClass ):
36- """Export functions to VTX file
100+ """Export species field functions to VTX file
37101
38102 Args:
39103 filename: The name of the output file
40104 field: Set of species to export
41- subdomain: A field can be defined on multiple domains.
42- This arguments specifies what subdomains we export on.
43- If `None` we export on all domains.
44- checkpoint: If True, the export will be a checkpoint file
45- using adios4dolfinx and won't be readable by ParaView.
46- Default is False.
105+ subdomain: A field can be defined on multiple domains. This arguments specifies
106+ what subdomains we export on. If `None` we export on all domains.
107+ checkpoint: If True, the export will be a checkpoint file using adios4dolfinx
108+ and won't be readable by ParaView. Default is False.
109+ times: if provided, the field will be exported at these timesteps. Otherwise
110+ exports at all timesteps. Defaults to None.
111+
112+ Attributes:
113+ filename: The name of the output file
114+ field: Set of species to export
115+ times: if provided, the field will be exported at these timesteps. Otherwise
116+ exports at all timesteps. Defaults to None.
117+ writer: The VTXWriter object used to write the file
47118 """
48119
49- field : list [_Species ]
50- _subdomain : _VolumeSubdomain
120+ _subdomain : VolumeSubdomain
51121 _checkpoint : bool
122+ writer : io .VTXWriter
52123
53124 def __init__ (
54125 self ,
55126 filename : str | Path ,
56- field : _Species | list [_Species ],
57- subdomain : _VolumeSubdomain = None ,
127+ field : Species | list [Species ],
128+ subdomain : VolumeSubdomain = None ,
58129 checkpoint : bool = False ,
59- ) -> None :
60- super ().__init__ (filename , ".bp" )
130+ times : Optional [list [float ] | list [int ] | None ] = None ,
131+ ):
132+ super ().__init__ (filename , ".bp" , times )
61133 self .field = field
62134 self ._subdomain = subdomain
63135 self ._checkpoint = checkpoint
64136
65137 @property
66- def field (self ) -> list [_Species ]:
138+ def field (self ) -> list [Species ]:
67139 return self ._field
68140
69141 @field .setter
70- def field (self , value : _Species | list [_Species ]):
142+ def field (self , value : Species | list [Species ]):
71143 """
72144 Update the field to export.
73145
74- Note:
75- This also creates a new writer with the updated field.
76-
77146 Args:
78147 value: The species to export
79148
80149 Raises:
81150 TypeError: If input field is not a Species or a list of Species
151+
152+ Note:
153+ This also creates a new writer with the updated field.
82154 """
83155 # check that all elements of list are festim.Species
84156 if isinstance (value , list ):
85157 for element in value :
86- if not isinstance (element , ( _Species , str ) ):
158+ if not isinstance (element , Species | str ):
87159 raise TypeError (
88- "field must be of type festim.Species or a list of festim.Species or str"
160+ "field must be of type festim.Species or a list of "
161+ "festim.Species or str"
89162 )
90163 val = value
91- elif isinstance (value , _Species ):
164+ elif isinstance (value , Species ):
92165 val = [value ]
93166 else :
94167 raise TypeError (
95- "field must be of type festim.Species or a list of festim.Species or str" ,
168+ "field must be of type festim.Species or a list of festim.Species or "
169+ "str" ,
96170 f"got { type (value )} ." ,
97171 )
98172 self ._field = val
99173
100174 def get_functions (self ) -> list [fem .Function ]:
101175 """
102- Returns list of species for a given subdomain.
103- If using legacy mode, return the whole species.
176+ Returns list of species for a given subdomain. If using legacy mode, return the
177+ whole species.
104178 """
105179
106180 legacy_output : bool = False
0 commit comments