pycfast 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {pycfast-0.2.0/src/pycfast.egg-info → pycfast-0.2.1}/PKG-INFO +2 -2
  2. {pycfast-0.2.0 → pycfast-0.2.1}/README.md +1 -1
  3. {pycfast-0.2.0 → pycfast-0.2.1}/pyproject.toml +1 -1
  4. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/__init__.py +1 -0
  5. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/compartment.py +77 -32
  6. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/datasets/_sp_ast_diesel.py +2 -4
  7. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/device.py +3 -2
  8. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/model.py +10 -6
  9. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/parsers/cfast_parser.py +3 -3
  10. {pycfast-0.2.0 → pycfast-0.2.1/src/pycfast.egg-info}/PKG-INFO +2 -2
  11. {pycfast-0.2.0 → pycfast-0.2.1}/LICENSE +0 -0
  12. {pycfast-0.2.0 → pycfast-0.2.1}/setup.cfg +0 -0
  13. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/_base_component.py +0 -0
  14. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/ceiling_floor_vent.py +0 -0
  15. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/datasets/__init__.py +0 -0
  16. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/datasets/data/sp_ast_diesel_1p1.csv.gz +0 -0
  17. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/fire.py +0 -0
  18. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/material.py +0 -0
  19. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/mechanical_vent.py +0 -0
  20. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/parsers/__init__.py +0 -0
  21. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/simulation_environment.py +0 -0
  22. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/surface_connection.py +0 -0
  23. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/utils/__init__.py +0 -0
  24. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/utils/csv_config.py +0 -0
  25. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/utils/namelist.py +0 -0
  26. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast/wall_vent.py +0 -0
  27. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast.egg-info/SOURCES.txt +0 -0
  28. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast.egg-info/dependency_links.txt +0 -0
  29. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast.egg-info/requires.txt +0 -0
  30. {pycfast-0.2.0 → pycfast-0.2.1}/src/pycfast.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycfast
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Python interface for building, running, and analyzing CFAST fire simulation models
5
5
  Author-email: WYGAS Benoît <97663334+bewygs@users.noreply.github.com>
6
6
  Maintainer-email: WYGAS Benoît <97663334+bewygs@users.noreply.github.com>
@@ -221,7 +221,7 @@ Check out the [examples](https://pycfast.org/examples.html) for more usage scena
221
221
 
222
222
  ## Installation
223
223
 
224
- PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) from CFAST version **7.7.0** to version **7.7.5**.
224
+ PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) and [validation input files](https://github.com/bewygs/pycfast/tree/main/tests/validation_tests) from CFAST version **7.7.0** to version **7.7.6**. Versions below **7.7.0** might work but are not guaranteed to be fully compatible.
225
225
 
226
226
  ### Pip or Conda
227
227
 
@@ -132,7 +132,7 @@ Check out the [examples](https://pycfast.org/examples.html) for more usage scena
132
132
 
133
133
  ## Installation
134
134
 
135
- PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) from CFAST version **7.7.0** to version **7.7.5**.
135
+ PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) and [validation input files](https://github.com/bewygs/pycfast/tree/main/tests/validation_tests) from CFAST version **7.7.0** to version **7.7.6**. Versions below **7.7.0** might work but are not guaranteed to be fully compatible.
136
136
 
137
137
  ### Pip or Conda
138
138
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pycfast"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Python interface for building, running, and analyzing CFAST fire simulation models"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -45,6 +45,7 @@ __version__ = version("pycfast")
45
45
  __author__ = "WYGAS Benoît"
46
46
 
47
47
  CFAST_VERSION = [
48
+ "7.7.6",
48
49
  "7.7.5",
49
50
  "7.7.4",
50
51
  "7.7.3",
@@ -12,6 +12,12 @@ from ._base_component import CFASTComponent
12
12
  from .utils.namelist import NamelistRecord
13
13
 
14
14
 
15
+ def _as_list(val: str | float | list | None) -> list:
16
+ if val is None:
17
+ return []
18
+ return val if isinstance(val, list) else [val]
19
+
20
+
15
21
  class Compartment(CFASTComponent):
16
22
  """
17
23
  Defines the size, position, materials of construction, and flow characteristics for compartments.
@@ -55,27 +61,30 @@ class Compartment(CFASTComponent):
55
61
  point must be the same for all elevations in the input data. All absolute positions
56
62
  for all compartments must be greater than or equal to zero, i.e., negative numbers are
57
63
  not allowed for these inputs. Default units: m, default value: 0.0 m.
58
- ceiling_mat_id : str, optional
59
- Material ID from the thermal properties from the Materials tab to define the ceiling
64
+ ceiling_mat_id : str or list[str], optional
65
+ Material ID(s) from the thermal properties from the Materials tab to define the ceiling
60
66
  surface of the compartment. Up to three materials can be used to define the layer(s)
61
67
  of the ceiling surface. The innermost layer is specified first. Default value: Off.
62
- ceiling_thickness : float, optional
63
- Thickness of each of the layers of the ceiling surface. Default units: m, default
64
- value: thickness of material specified on the Materials tab.
65
- wall_mat_id : str, optional
66
- Material ID from the thermal properties from the Materials tab to define the wall
68
+ ceiling_thickness : float or list[float], optional
69
+ Thickness of each of the layers of the ceiling surface. Must match the number of
70
+ materials in ``ceiling_mat_id``. Default units: m, default value: thickness of
71
+ material specified on the Materials tab.
72
+ wall_mat_id : str or list[str], optional
73
+ Material ID(s) from the thermal properties from the Materials tab to define the wall
67
74
  surface of the compartment. Up to three materials can be used to define the layer(s)
68
75
  of the wall surface. The innermost layer is specified first. Default value: Off.
69
- wall_thickness : float, optional
70
- Thickness of each of the layers of the wall surface. Default units: m, default
71
- value: thickness of material specified on the Materials tab.
72
- floor_mat_id : str, optional
73
- Material ID from the thermal properties from the Materials tab to define the floor
76
+ wall_thickness : float or list[float], optional
77
+ Thickness of each of the layers of the wall surface. Must match the number of
78
+ materials in ``wall_mat_id``. Default units: m, default value: thickness of
79
+ material specified on the Materials tab.
80
+ floor_mat_id : str or list[str], optional
81
+ Material ID(s) from the thermal properties from the Materials tab to define the floor
74
82
  surface of the compartment. Up to three materials can be used to define the layer(s)
75
83
  of the floor surface. The innermost layer is specified first. Default value: Off.
76
- floor_thickness : float, optional
77
- Thickness of each of the layers of the floor surface. Default units: m, default
78
- value: thickness of material specified on the Materials tab.
84
+ floor_thickness : float or list[float], optional
85
+ Thickness of each of the layers of the floor surface. Must match the number of
86
+ materials in ``floor_mat_id``. Default units: m, default value: thickness of
87
+ material specified on the Materials tab.
79
88
  shaft : bool, optional
80
89
  For tall compartments or those removed from the room of fire origin, the compartment
81
90
  may be modeled as a single, well-mixed zone rather than the default two-zone assumption.
@@ -135,12 +144,12 @@ class Compartment(CFASTComponent):
135
144
  width: float | None = 3.6,
136
145
  depth: float | None = 2.4,
137
146
  height: float | None = 2.4,
138
- ceiling_mat_id: str | None = None,
139
- ceiling_thickness: float | None = None,
140
- wall_mat_id: str | None = None,
141
- wall_thickness: float | None = None,
142
- floor_mat_id: str | None = None,
143
- floor_thickness: float | None = None,
147
+ ceiling_mat_id: str | list[str] | None = None,
148
+ ceiling_thickness: float | list[float] | None = None,
149
+ wall_mat_id: str | list[str] | None = None,
150
+ wall_thickness: float | list[float] | None = None,
151
+ floor_mat_id: str | list[str] | None = None,
152
+ floor_thickness: float | list[float] | None = None,
144
153
  origin_x: float | None = 0,
145
154
  origin_y: float | None = 0,
146
155
  origin_z: float | None = 0,
@@ -195,6 +204,28 @@ class Compartment(CFASTComponent):
195
204
  f"Compartment '{self.id}': {param} must be a list, got {type(list_val).__name__}."
196
205
  )
197
206
 
207
+ for surface in ("ceiling", "wall", "floor"):
208
+ mat_id = getattr(self, f"{surface}_mat_id")
209
+ thickness = getattr(self, f"{surface}_thickness")
210
+ n_mats = (
211
+ len(mat_id)
212
+ if isinstance(mat_id, list)
213
+ else (1 if mat_id is not None else 0)
214
+ )
215
+ if n_mats > 3:
216
+ raise ValueError(
217
+ f"Compartment '{self.id}': {surface}_mat_id accepts at most "
218
+ f"3 materials, got {n_mats}."
219
+ )
220
+ if mat_id is not None and thickness is not None:
221
+ n_thick = len(thickness) if isinstance(thickness, list) else 1
222
+ if n_mats != n_thick:
223
+ raise ValueError(
224
+ f"Compartment '{self.id}': {surface}_mat_id has {n_mats} "
225
+ f"material(s) but {surface}_thickness has {n_thick} value(s). "
226
+ "They must have the same length."
227
+ )
228
+
198
229
  if self.leak_area_ratio is not None and len(self.leak_area_ratio) != 2:
199
230
  raise ValueError(
200
231
  f"Compartment '{self.id}': leak_area_ratio must contain exactly 2 values "
@@ -241,8 +272,8 @@ class Compartment(CFASTComponent):
241
272
  f"Compartment("
242
273
  f"id='{self.id}', "
243
274
  f"width={self.width}, depth={self.depth}, height={self.height}, "
244
- f"ceiling_mat_id='{self.ceiling_mat_id}', wall_mat_id='{self.wall_mat_id}', "
245
- f"floor_mat_id='{self.floor_mat_id}', "
275
+ f"ceiling_mat_id={self.ceiling_mat_id!r}, wall_mat_id={self.wall_mat_id!r}, "
276
+ f"floor_mat_id={self.floor_mat_id!r}, "
246
277
  f"origin=({self.origin_x}, {self.origin_y}, {self.origin_z})"
247
278
  ")"
248
279
  )
@@ -259,11 +290,20 @@ class Compartment(CFASTComponent):
259
290
 
260
291
  materials = []
261
292
  if self.ceiling_mat_id:
262
- materials.append(f"ceiling: {self.ceiling_mat_id}")
293
+ val = self.ceiling_mat_id
294
+ materials.append(
295
+ f"ceiling: {', '.join(val) if isinstance(val, list) else val}"
296
+ )
263
297
  if self.wall_mat_id:
264
- materials.append(f"wall: {self.wall_mat_id}")
298
+ val = self.wall_mat_id
299
+ materials.append(
300
+ f"wall: {', '.join(val) if isinstance(val, list) else val}"
301
+ )
265
302
  if self.floor_mat_id:
266
- materials.append(f"floor: {self.floor_mat_id}")
303
+ val = self.floor_mat_id
304
+ materials.append(
305
+ f"floor: {', '.join(val) if isinstance(val, list) else val}"
306
+ )
267
307
 
268
308
  material_str = f" ({', '.join(materials)})" if materials else ""
269
309
 
@@ -315,16 +355,21 @@ class Compartment(CFASTComponent):
315
355
  rec.add_field("HALL", True)
316
356
 
317
357
  if self.ceiling_mat_id is not None:
318
- rec.add_field("CEILING_MATL_ID", self.ceiling_mat_id)
319
- rec.add_field("CEILING_THICKNESS", self.ceiling_thickness)
358
+ rec.add_list_field("CEILING_MATL_ID", _as_list(self.ceiling_mat_id))
359
+ if self.ceiling_thickness is not None:
360
+ rec.add_list_field(
361
+ "CEILING_THICKNESS", _as_list(self.ceiling_thickness)
362
+ )
320
363
 
321
364
  if self.wall_mat_id is not None:
322
- rec.add_field("WALL_MATL_ID", self.wall_mat_id)
323
- rec.add_field("WALL_THICKNESS", self.wall_thickness)
365
+ rec.add_list_field("WALL_MATL_ID", _as_list(self.wall_mat_id))
366
+ if self.wall_thickness is not None:
367
+ rec.add_list_field("WALL_THICKNESS", _as_list(self.wall_thickness))
324
368
 
325
369
  if self.floor_mat_id is not None:
326
- rec.add_field("FLOOR_MATL_ID", self.floor_mat_id)
327
- rec.add_field("FLOOR_THICKNESS", self.floor_thickness)
370
+ rec.add_list_field("FLOOR_MATL_ID", _as_list(self.floor_mat_id))
371
+ if self.floor_thickness is not None:
372
+ rec.add_list_field("FLOOR_THICKNESS", _as_list(self.floor_thickness))
328
373
 
329
374
  rec.add_list_field("CROSS_SECT_AREAS", self.cross_sect_areas)
330
375
  rec.add_list_field("CROSS_SECT_HEIGHTS", self.cross_sect_heights)
@@ -25,11 +25,9 @@ SP_AST_Diesel_1p1 Dataset
25
25
  =========================
26
26
 
27
27
  This dataset contains 5000 pre-computed CFAST simulation results
28
- based on the ``SP_AST_Diesel_1p1.in`` validation model. Each sample
28
+ based on the `SP_AST_Diesel_1p1.in <https://github.com/firemodels/cfast/blob/master/Validation/SP_AST/SP_AST_Diesel_1p1.in>`_ validation model. Each sample
29
29
  maps fire parameters to the maximum target surface temperature (TRGSURT).
30
30
 
31
- **Base model**: SP_AST_Diesel_1p1.in
32
-
33
31
  **Input features** (4):
34
32
  - ``heat_of_combustion`` (kJ/kg): Heat of combustion [5.0, 50.0]
35
33
  - ``radiative_fraction`` : Radiative fraction [0.1, 0.5]
@@ -59,7 +57,7 @@ def load_sp_ast_diesel_1p1(
59
57
  """Load the SP_AST_Diesel_1p1 pre-computed dataset.
60
58
 
61
59
  Returns 5000 CFAST simulation results based on the
62
- ``SP_AST_Diesel_1p1.in`` validation model, mapping fire parameters
60
+ `SP_AST_Diesel_1p1.in <https://github.com/firemodels/cfast/blob/master/Validation/SP_AST/SP_AST_Diesel_1p1.in>`_ validation model, mapping fire parameters
63
61
  (heat of combustion, radiative fraction, soot yield, target height)
64
62
  to maximum target surface temperature (TRGSURT).
65
63
 
@@ -103,6 +103,7 @@ class Device(CFASTComponent):
103
103
  If location does not contain exactly 3 numeric values.
104
104
  If target type is specified but required target parameters are missing.
105
105
  If detector type is specified but required detector parameters are missing.
106
+ If spray_density is negative.
106
107
  If both normal and surface_orientation are specified or both are None.
107
108
  If normal vector does not contain exactly 3 numeric values.
108
109
  If unknown device type is specified.
@@ -382,9 +383,9 @@ class Device(CFASTComponent):
382
383
  raise ValueError(
383
384
  f"SPRINKLER '{self.id}': setpoint must be positive, got {self.setpoint}."
384
385
  )
385
- if self.spray_density <= 0:
386
+ if self.spray_density < 0:
386
387
  raise ValueError(
387
- f"SPRINKLER '{self.id}': spray_density must be positive, got {self.spray_density}."
388
+ f"SPRINKLER '{self.id}': spray_density must be >= 0, got {self.spray_density}."
388
389
  )
389
390
  elif self.type == "SMOKE_DETECTOR":
390
391
  if not 0.0 <= self.obscuration <= 100.0:
@@ -881,7 +881,6 @@ class CFASTModel:
881
881
  """
882
882
  if file_name is not None:
883
883
  original_file_name = self.file_name
884
- original_written_content = self._written_content
885
884
  self.file_name = file_name
886
885
 
887
886
  try:
@@ -890,7 +889,6 @@ class CFASTModel:
890
889
  finally:
891
890
  if file_name is not None:
892
891
  self.file_name = original_file_name
893
- self._written_content = original_written_content
894
892
 
895
893
  def summary(self) -> str:
896
894
  """
@@ -1241,10 +1239,16 @@ class CFASTModel:
1241
1239
  for comp in self.compartments:
1242
1240
  for attr in ("ceiling_mat_id", "wall_mat_id", "floor_mat_id"):
1243
1241
  m_id = getattr(comp, attr, None)
1244
- if m_id is not None and m_id != "OFF" and m_id not in material_ids:
1245
- raise ValueError(
1246
- f"Compartment '{comp.id}': {attr}='{m_id}' does not match any defined material."
1247
- )
1242
+ ids_to_check = (
1243
+ m_id
1244
+ if isinstance(m_id, list)
1245
+ else ([m_id] if m_id is not None else [])
1246
+ )
1247
+ for mid in ids_to_check:
1248
+ if mid != "OFF" and mid not in material_ids:
1249
+ raise ValueError(
1250
+ f"Compartment '{comp.id}': {attr}='{mid}' does not match any defined material."
1251
+ )
1248
1252
 
1249
1253
  # device_id referenced in Fire or Vent must exist in devices
1250
1254
  for fire in self.fires:
@@ -520,11 +520,11 @@ class CFASTParser:
520
520
  "depth": {"source": "DEPTH", "required": True, "type": float},
521
521
  "height": {"source": "HEIGHT", "required": True, "type": float},
522
522
  "ceiling_mat_id": {"source": "CEILING_MATL_ID", "default": "OFF"},
523
- "ceiling_thickness": {"source": "CEILING_THICKNESS", "type": float},
523
+ "ceiling_thickness": {"source": "CEILING_THICKNESS"},
524
524
  "wall_mat_id": {"source": "WALL_MATL_ID", "default": "OFF"},
525
- "wall_thickness": {"source": "WALL_THICKNESS", "type": float},
525
+ "wall_thickness": {"source": "WALL_THICKNESS"},
526
526
  "floor_mat_id": {"source": "FLOOR_MATL_ID", "default": "OFF"},
527
- "floor_thickness": {"source": "FLOOR_THICKNESS", "type": float},
527
+ "floor_thickness": {"source": "FLOOR_THICKNESS"},
528
528
  "shaft": {"source": "SHAFT", "type": bool},
529
529
  "hall": {"source": "HALL", "type": bool},
530
530
  "leak_area_ratio": {"source": "LEAK_AREA_RATIO", "type": list},
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycfast
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Python interface for building, running, and analyzing CFAST fire simulation models
5
5
  Author-email: WYGAS Benoît <97663334+bewygs@users.noreply.github.com>
6
6
  Maintainer-email: WYGAS Benoît <97663334+bewygs@users.noreply.github.com>
@@ -221,7 +221,7 @@ Check out the [examples](https://pycfast.org/examples.html) for more usage scena
221
221
 
222
222
  ## Installation
223
223
 
224
- PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) from CFAST version **7.7.0** to version **7.7.5**.
224
+ PyCFAST requires **Python 3.10 or later**. It is fully [tested on verification input files](https://github.com/bewygs/pycfast/tree/main/tests/verification_tests) and [validation input files](https://github.com/bewygs/pycfast/tree/main/tests/validation_tests) from CFAST version **7.7.0** to version **7.7.6**. Versions below **7.7.0** might work but are not guaranteed to be fully compatible.
225
225
 
226
226
  ### Pip or Conda
227
227
 
File without changes
File without changes
File without changes
File without changes