cffview 0.4.2__tar.gz → 0.4.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cffview
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A Python CLI tool to view Ansys Fluent .cas.h5/.msh.h5/.dat.h5 files without opening Fluent
5
5
  Author-email: preamer <1524477126@qq.com>
6
6
  License-Expression: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cffview"
7
- version = "0.4.2"
7
+ version = "0.4.4"
8
8
  description = "A Python CLI tool to view Ansys Fluent .cas.h5/.msh.h5/.dat.h5 files without opening Fluent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -115,31 +115,10 @@ class BoundaryFactory:
115
115
  boundary_cls = cls._REGISTRY.get(type_, NotImplementedBoundary)
116
116
  return boundary_cls(name, id_)
117
117
 
118
- @staticmethod
119
- def match_property(property_list: list[str | list[str]]) -> str | dict[str, str]:
120
- match property_list:
121
- case [_]:
122
- return ''
123
- case [_, expr] | [_, '.', expr] if isinstance(expr, str):
124
- return expr
125
- case [_, x, y, z] if all(isinstance(i, str) for i in (x, y, z)):
126
- return f'{x} {y} {z}'
127
- case [_, [sel, '.', expr], *_]:
128
- return f'{sel}/{expr}'
129
- case [_, ['profile', sel, expr], *_]:
130
- return f'profile/{sel}/{expr}'
131
- case ['source-terms', *source_terms_list]:
132
- for source_term in (st for st in source_terms_list if len(st) == 2):
133
- eq_name, source_property_list = source_term
134
- source_property = source_property_list[0]
135
- if source_property[1] == '.':
136
- return {eq_name: f'{source_property[0]}/{source_property[2]}'}
137
- elif source_property[0] == 'profile' and source_property[1]:
138
- return {eq_name: f'profile/{source_property[1]}/{source_property[2]}'}
139
-
140
118
 
141
119
  # ------------------------------------------------- shared to_dict helpers
142
120
 
121
+
143
122
  TURBULENCE_KEYS = (
144
123
  'ke_spec', 'turb_intensity', 'turb_length_scale',
145
124
  'turb_hydraulic_diam', 'turb_viscosity_ratio',
@@ -243,7 +243,7 @@ def plot(file_path: str, out: bool = False, xy: bool = False, dat: bool = False)
243
243
  raise ValueError("Please specify --out, --xy or --dat")
244
244
 
245
245
 
246
- def plot_data(file_path: str):
246
+ def plot_data(file_path: str) -> None:
247
247
  """Visualize Fluent .cas.h5 + .dat.h5 solution data with interactive cross-sections.
248
248
 
249
249
  Uses PyVista's built-in VTK FLUENTCFF Reader to load both mesh and solution data
@@ -8,7 +8,7 @@ variable switching, opacity and clip-plane widgets.
8
8
  import sys
9
9
  from functools import wraps
10
10
 
11
- from pyvista import _vtk, Plotter, MultiBlock, PolyData, UnstructuredGrid, DataSetMapper
11
+ from pyvista import _vtk, Actor, Plotter, MultiBlock, PolyData, UnstructuredGrid, DataSetMapper
12
12
 
13
13
  from .utils import print_colored_dict
14
14
 
@@ -32,7 +32,7 @@ KEYBOARD_SHORTCUTS = {
32
32
 
33
33
 
34
34
  class BasePlotter:
35
- def __init__(self, mesh: MultiBlock | PolyData):
35
+ def __init__(self, mesh: MultiBlock | PolyData) -> None:
36
36
  self.mesh = mesh.combine() if isinstance(mesh, MultiBlock) else mesh
37
37
 
38
38
  # Monkey patch to fix clip plane error
@@ -55,7 +55,7 @@ class BasePlotter:
55
55
  self.keyboard_shortcuts = KEYBOARD_SHORTCUTS
56
56
 
57
57
  @wraps(Plotter.show)
58
- def show(self, *args, **kwargs):
58
+ def show(self, *args, **kwargs) -> None:
59
59
  print_colored_dict(self.keyboard_shortcuts)
60
60
  self.pl.show(*args, **kwargs)
61
61
 
@@ -63,7 +63,7 @@ class BasePlotter:
63
63
  self,
64
64
  checkbox_params: dict = None,
65
65
  text_params: dict = None,
66
- ):
66
+ ) -> _vtk.vtkButtonWidget:
67
67
  checkbox_params = checkbox_params or {}
68
68
  text_params = text_params or {}
69
69
 
@@ -73,17 +73,17 @@ class BasePlotter:
73
73
  checkbox_params['position'][1] + 10,
74
74
  )
75
75
 
76
- check_box_widget = self.pl.add_checkbox_button_widget(**checkbox_params)
76
+ check_box_widget: _vtk.vtkButtonWidget = self.pl.add_checkbox_button_widget(**checkbox_params)
77
77
  check_box_widget.callback = checkbox_params['callback']
78
78
  self.pl.add_text(**text_params)
79
79
 
80
80
  return check_box_widget
81
81
 
82
- def _add_grid_cb(self):
83
- def toggle_grid(state: bool):
82
+ def _add_grid_cb(self) -> _vtk.vtkButtonWidget:
83
+ def toggle_grid(state: bool) -> None:
84
84
  self.pl.show_grid(font_size=10, fmt='%.2f') if state else self.pl.remove_bounds_axes()
85
85
 
86
- grid_cb = self._add_checkbox_and_text(
86
+ grid_cb: _vtk.vtkButtonWidget = self._add_checkbox_and_text(
87
87
  checkbox_params=dict(
88
88
  callback=toggle_grid,
89
89
  value=False,
@@ -98,13 +98,13 @@ class BasePlotter:
98
98
  return grid_cb
99
99
 
100
100
  def _add_keyboard_shortcuts(self, key_widget_dict: dict[str, tuple[_vtk.vtkButtonWidget | _vtk.vtkSliderWidget, str]]):
101
- def reverse(checkbox_button_widget: _vtk.vtkButtonWidget):
101
+ def reverse(checkbox_button_widget: _vtk.vtkButtonWidget) -> None:
102
102
  rep = checkbox_button_widget.button_representation
103
103
  new_state = not rep.state
104
104
  rep.state = new_state
105
105
  checkbox_button_widget.callback(new_state)
106
106
 
107
- def set_value(slider_widget: _vtk.vtkSliderWidget, new_value: int):
107
+ def set_value(slider_widget: _vtk.vtkSliderWidget, new_value: int) -> None:
108
108
  slider_widget.slider_representation.value = new_value
109
109
  slider_widget.callback(new_value)
110
110
 
@@ -117,7 +117,7 @@ class BasePlotter:
117
117
 
118
118
 
119
119
  class MeshPlotter(BasePlotter):
120
- def __init__(self, mesh, dimension: int = None):
120
+ def __init__(self, mesh, dimension: int = None) -> None:
121
121
  super().__init__(mesh)
122
122
  self.dimension = dimension
123
123
  self.mesh_actor = self._add_mesh()
@@ -132,7 +132,7 @@ class MeshPlotter(BasePlotter):
132
132
  }
133
133
  )
134
134
 
135
- def _add_mesh(self):
135
+ def _add_mesh(self) -> Actor:
136
136
  mesh_actor = self.pl.add_mesh(
137
137
  self.mesh,
138
138
  show_edges=True,
@@ -140,8 +140,8 @@ class MeshPlotter(BasePlotter):
140
140
  )
141
141
  return mesh_actor
142
142
 
143
- def _add_opcatity_slider(self):
144
- opacity_slider_widget = self.pl.add_slider_widget(
143
+ def _add_opcatity_slider(self) -> _vtk.vtkSliderWidget:
144
+ opacity_slider_widget: _vtk.vtkSliderWidget = self.pl.add_slider_widget(
145
145
  lambda value: setattr(self.mesh_actor.prop, 'opacity', value),
146
146
  rng=(0.1, 1.0),
147
147
  value=1.0,
@@ -155,14 +155,14 @@ class MeshPlotter(BasePlotter):
155
155
  )
156
156
  return opacity_slider_widget
157
157
 
158
- def _add_mesh_clip_plane(self):
158
+ def _add_mesh_clip_plane(self) -> None:
159
159
  self.mesh_clip_plane_actor = self.pl.add_mesh_clip_plane(self.mesh, show_edges=True)
160
160
  self.mesh_clip_plane_actor.visibility = False
161
161
  self.clip_plane = self.pl.widgets.plane_widgets[-1]
162
162
  self.clip_plane.Off()
163
163
 
164
- def _add_clip_plane_cb(self):
165
- def toggle_clip_plane(state):
164
+ def _add_clip_plane_cb(self) -> _vtk.vtkButtonWidget:
165
+ def toggle_clip_plane(state) -> None:
166
166
  if state:
167
167
  self.mesh_actor.visibility = False
168
168
  self.opacity_slider_widget.Off()
@@ -190,7 +190,7 @@ class MeshPlotter(BasePlotter):
190
190
 
191
191
 
192
192
  class DataPlotter(BasePlotter):
193
- def __init__(self, mesh: MultiBlock | PolyData, var_names: tuple[str]):
193
+ def __init__(self, mesh: MultiBlock | PolyData, var_names: tuple[str]) -> None:
194
194
  super().__init__(mesh)
195
195
  self.var_names = var_names
196
196
 
@@ -254,11 +254,11 @@ class DataPlotter(BasePlotter):
254
254
  self.scalar_bar.title = name
255
255
  self.pl.render()
256
256
 
257
- def _add_scalar_slider_widget(self):
258
- def change_scalar(value: float):
257
+ def _add_scalar_slider_widget(self) -> _vtk.vtkSliderWidget:
258
+ def change_scalar(value: float) -> None:
259
259
  self._set_scalars(self.var_names[int(value)])
260
260
 
261
- scalar_slider = self.pl.add_slider_widget(
261
+ scalar_slider: _vtk.vtkSliderWidget = self.pl.add_slider_widget(
262
262
  change_scalar,
263
263
  rng=(0, len(self.var_names) - 1),
264
264
  value=0,
@@ -274,8 +274,8 @@ class DataPlotter(BasePlotter):
274
274
  scalar_slider.callback = change_scalar
275
275
  return scalar_slider
276
276
 
277
- def _add_clip_plane_cb(self):
278
- def toggle_clip_plane(state):
277
+ def _add_clip_plane_cb(self) -> _vtk.vtkButtonWidget:
278
+ def toggle_clip_plane(state) -> None:
279
279
  if state:
280
280
  self.mesh_actor.visibility = False
281
281
  self.mesh_clip_plane_actor.visibility = True
@@ -15,6 +15,7 @@ import sexpdata
15
15
 
16
16
  NestedStrList: TypeAlias = list[Union[str, 'NestedStrList']]
17
17
  CaseTexts = namedtuple('CaseTexts', ['general', 'boundary', 'cortex'])
18
+ ReaderFunc: TypeAlias = Callable[[CaseTexts], dict[str, Any]]
18
19
 
19
20
  # from Ansys Fluent sg.h
20
21
  DISCRETIZATION_SCHEME = {
@@ -165,6 +166,30 @@ def _get_reference_values(general: str) -> dict[str, str]:
165
166
  }
166
167
 
167
168
 
169
+ @lru_cache(maxsize=None)
170
+ def _get_flow_scheme(general: str) -> str:
171
+ """Return the pressure-velocity coupling scheme name (e.g. ``SIMPLE``)."""
172
+ scheme = re.search(r'\(flow/scheme\s+(\d+)\)', general).group(1)
173
+ return DISCRETIZATION_SCHEME.get(scheme, scheme)
174
+
175
+
176
+ @lru_cache(maxsize=None)
177
+ def _get_pseudo_time_method(general: str, flow_scheme: str) -> str:
178
+ """Return the pseudo time method state: ``Off``, ``Global Time Step`` or ``Local Time Step``.
179
+
180
+ Disabled when ``user-defined-settings?`` is ``#f``; for the Coupled
181
+ scheme a global pseudo time step is used, otherwise a local one.
182
+ """
183
+ if flow_scheme == 'Coupled':
184
+ key = 'pseudo-time-method/coupled-pbns/user-defined-settings?'
185
+ else:
186
+ key = 'pseudo-time-method/segregated-pbns/user-defined-settings?'
187
+ enabled = re.search(rf'\({re.escape(key)}\s+([^)]+)\)', general).group(1)
188
+ if enabled == '#f':
189
+ return 'Off'
190
+ return 'Global Time Step' if flow_scheme == 'Coupled' else 'Local Time Step'
191
+
192
+
168
193
  @singledispatch
169
194
  def _sel_expr(arg, *args) -> str:
170
195
  """Unsupported first-argument type for :func:`_sel_expr`."""
@@ -196,12 +221,12 @@ def _(lst: list[str], return_expr: bool = False) -> str:
196
221
  # ------------------------------------------------------------- dispatcher
197
222
 
198
223
 
199
- READERS: dict[str, Callable[[CaseTexts], dict[str, Any]]] = {}
224
+ READERS: dict[str, ReaderFunc] = {}
200
225
 
201
226
 
202
- def register_reader(name: str):
227
+ def register_reader(name: str) -> Callable[[ReaderFunc], ReaderFunc]:
203
228
  """Register a reader function under a flag name."""
204
- def decorator(func: Callable[[CaseTexts], dict[str, Any]]) -> Callable[[CaseTexts], dict[str, Any]]:
229
+ def decorator(func: ReaderFunc) -> ReaderFunc:
205
230
  READERS[name] = func
206
231
  return func
207
232
  return decorator
@@ -215,6 +240,7 @@ def _read_solver(texts: CaseTexts) -> dict[str, Any]:
215
240
  general = texts.general
216
241
  kvs = _parse_case_config(general)
217
242
  dimension = '3d' if kvs['rp-3d?'] == '#t' else '2d'
243
+ flow_scheme = _get_flow_scheme(general)
218
244
 
219
245
  solver: dict[str, Any] = {
220
246
  'type': 'pbns' if kvs['rp-seg?'] == '#t' else 'dbns',
@@ -223,6 +249,8 @@ def _read_solver(texts: CaseTexts) -> dict[str, Any]:
223
249
  'precision': 'double' if kvs['rp-double?'] == '#t' else 'single',
224
250
  'axi': 'true' if kvs['rp-axi?'] == '#t' else 'false',
225
251
  'init': 'hybrid' if kvs['hyb-init?'] == '#t' else 'standard',
252
+ 'flow-scheme': flow_scheme,
253
+ 'pseudo-time-method': _get_pseudo_time_method(general, flow_scheme),
226
254
  'turb': _get_turb_model(general),
227
255
  'energy': 'true' if kvs['rf-energy?'] == '#t' else 'false',
228
256
  'radiation': _get_radiation_model(general),
@@ -250,29 +278,33 @@ def _read_materials(texts: CaseTexts) -> dict[str, Any]:
250
278
  data[name] = {'type': material[1]}
251
279
  for property_ in material[2:]:
252
280
  property_name = property_[0]
253
- if property_[1] == '.':
254
- data[name][property_name] = property_[2]
255
- elif isinstance(property_value_list := property_[1], list):
256
- if property_value_list[1] == '.':
257
- data[name][property_name] = f'{property_value_list[0]}/{property_value_list[2]}'
258
- elif property_value_list[1] == 'piecewise-linear':
259
- value = [f'{p[0]}, {p[2]}' for p in property_value_list[2:]]
260
- data[name][property_name] = {f'{property_value_list[0]}/{property_value_list[1]}': value}
261
- elif property_value_list[1] in ['piecewise-polynomial', 'nasa-9-piecewise-polynomial']:
262
- value = [str(p).strip('[]') for p in property_value_list[2:]]
263
- data[name][property_name] = {f'{property_value_list[0]}/{property_value_list[1]}': value}
264
- elif property_value_list[0] == 'orthotropic':
281
+ match property_[1:]:
282
+ case ['.', value]:
283
+ data[name][property_name] = value
284
+ case [[sel, '.', expr], *_]:
285
+ data[name][property_name] = f'{sel}/{expr}'
286
+ case [['polynomial', 'piecewise-linear', *values_list], *_]:
287
+ data[name][property_name] = {
288
+ f'polynomial/piecewise-linear': [f'{v[0]}, {v[2]}' for v in values_list]
289
+ }
290
+ case [['polynomial', polynomial_type, *values_list], *_] if polynomial_type in ('piecewise-polynomial', 'nasa-9-piecewise-polynomial'):
291
+ data[name][property_name] = {
292
+ f'polynomial/{polynomial_type}': [str(v).strip('[]') for v in values_list]
293
+ }
294
+ case [['polynomial', *values_list], *_]:
295
+ data[name][property_name] = {f'polynomial': [str(v).strip('[]') for v in values_list]}
296
+ case [['orthotropic', *orth_properties], *_]:
265
297
  value = {}
266
- for p in property_value_list[1:]:
267
- orth_property_name = p[0]
268
- if orth_property_name in ['direction-0', 'direction-1', 'direction-2']:
269
- value[orth_property_name] = [int(i) for i in p[1:]]
270
- elif orth_property_name in ['k0', 'k1', 'k2']:
271
- value[orth_property_name] = _sel_expr(p[1])
272
- data[name][property_name] = {property_value_list[0]: value}
273
- else:
274
- value = ' '.join(str(p) for p in property_value_list[1:])
275
- data[name][property_name] = f'{property_value_list[0]}/{value}'
298
+ for orth_property in orth_properties:
299
+ orth_property_name = orth_property[0]
300
+ if orth_property_name in ('direction-0', 'direction-1', 'direction-2'):
301
+ value[orth_property_name] = str([int(i) for i in orth_property[1:]]).strip('[]')
302
+ elif orth_property_name in ('k0', 'k1', 'k2'):
303
+ value[orth_property_name] = _sel_expr(orth_property[1])
304
+ data[name][property_name] = value
305
+ case _:
306
+ value = ' '.join(str(p) for p in property_[1:])
307
+ data[name][property_name] = f'{property_[0]}/{value}'
276
308
  return {'materials': data}
277
309
 
278
310
 
@@ -293,7 +325,27 @@ def _read_boundary(texts: CaseTexts) -> dict[str, Any]:
293
325
  for property_list in boundary_info[2]:
294
326
  property_name = property_list[0].replace('-', '_').replace('?', '').replace('/', '_')
295
327
  if hasattr(new_boundary, property_name):
296
- setattr(new_boundary, property_name, BoundaryFactory.match_property(property_list))
328
+ match property_list:
329
+ case [_, expr] | [_, '.', expr] if isinstance(expr, str):
330
+ value = expr
331
+ case [_, x, y, z] if all(isinstance(i, str) for i in (x, y, z)):
332
+ value = f'{x} {y} {z}'
333
+ case [_, [sel, '.', expr], *_]:
334
+ value = f'{sel}/{expr}'
335
+ case [_, ['profile', sel, expr], *_]:
336
+ value = f'profile/{sel}/{expr}'
337
+ case ['source-terms', *source_terms_list]:
338
+ value = {}
339
+ for source_term in (st for st in source_terms_list if len(st) == 2):
340
+ eq_name, source_property_list = source_term
341
+ source_property = source_property_list[0]
342
+ if source_property[1] == '.':
343
+ value[eq_name] = f'{source_property[0]}/{source_property[2]}'
344
+ elif source_property[0] == 'profile' and source_property[1]:
345
+ value[eq_name] = f'profile/{source_property[1]}/{source_property[2]}'
346
+ case _:
347
+ value = ''
348
+ setattr(new_boundary, property_name, value)
297
349
 
298
350
  b_list.append(
299
351
  new_boundary.to_dict(_get_turb_model(texts.general), _get_radiation_model(texts.general))
@@ -316,10 +368,13 @@ def _read_interfaces(texts: CaseTexts) -> dict[str, Any]:
316
368
  data: dict[str, Any] = {}
317
369
  for interface in interfaces_list:
318
370
  name = interface[0]
319
- data[name] = {
320
- property_[0]: property_[2] if len(property_) == 3 else property_[1]
321
- for property_ in filter(lambda x: len(x) > 1, interface[1:])
322
- }
371
+ data[name] = {}
372
+ for interface_property in interface[1:]:
373
+ match interface_property:
374
+ case [property_name, '.', value] | [property_name, value]:
375
+ data[name][property_name] = value
376
+ case _:
377
+ continue
323
378
  return {'interfaces': data}
324
379
 
325
380
 
@@ -395,6 +450,13 @@ def _read_disc(texts: CaseTexts) -> dict[str, Any]:
395
450
  }
396
451
 
397
452
  data: dict[str, Any] = {'disc-scheme': {}, 'relax-factor': {}}
453
+ cell_lsq = re.search(r'\(recon/cell-lsq\?\s+([^)]+)\)', general).group(1)
454
+ node_lsq = re.search(r'\(recon/node-lsq\?\s+([^)]+)\)', general).group(1)
455
+ data['disc-scheme']['gradient'] = (
456
+ 'Least Squares Cell-Based' if cell_lsq == '#t'
457
+ else 'Green-Gauss Node-Based' if node_lsq == '#t'
458
+ else 'Green-Gauss Cell-Based'
459
+ )
398
460
  for eq in ['flow', 'pressure', 'mom', 'temperature', 'k', 'omega', 'epsilon']:
399
461
  data['disc-scheme'][eq] = disc_scheme.get(eq)
400
462
 
@@ -410,13 +472,27 @@ def _read_disc(texts: CaseTexts) -> dict[str, Any]:
410
472
  general
411
473
  ).group(1)
412
474
  else:
475
+ pseudo_time_method = _get_pseudo_time_method(general, data['disc-scheme']['flow'])
476
+ relax_prefix = '' if pseudo_time_method == 'Off' else 'dual-ts-implicit-'
413
477
  relax_factor = {
414
478
  ur[0]: ur[1]
415
- for ur in re.findall(r'\((.*)/relax\s+([\d.]+)\)', general)
479
+ for ur in re.findall(rf'\((.*)/{relax_prefix}relax\s+([\d.]+)\)', general)
416
480
  }
417
481
  for eq in ['pressure', 'mom', 'temperature', 'k', 'omega', 'epsilon', 'turb-viscosity', 'density', 'body-force']:
418
482
  data['relax-factor'][eq] = relax_factor.get(eq, '')
419
483
 
484
+ turb_model = _get_turb_model(general)
485
+ if turb_model == 'lam':
486
+ for eq in ['k', 'omega', 'epsilon', 'turb-viscosity']:
487
+ data['disc-scheme'].pop(eq, None)
488
+ data['relax-factor'].pop(eq, None)
489
+ elif turb_model == 'kw':
490
+ data['disc-scheme'].pop('epsilon', None)
491
+ data['relax-factor'].pop('epsilon', None)
492
+ elif turb_model == 'ke':
493
+ data['disc-scheme'].pop('omega', None)
494
+ data['relax-factor'].pop('omega', None)
495
+
420
496
  return data
421
497
 
422
498
 
@@ -435,34 +511,26 @@ def _read_report_definitions(texts: CaseTexts) -> dict[str, Any]:
435
511
  report_def = rd[1]
436
512
  type_ = report_def[1]
437
513
  data[name] = {'type': type_}
438
- property_dict = {
439
- property_[0]: property_[2]
440
- for property_ in report_def[2:]
441
- if len(property_) == 3 and property_[1] == '.'
442
- }
443
- data[name].update(property_dict)
444
- if 'volume' in type_:
445
- data[name]['zone-list'] = [zone for zone in report_def[4][1:]]
446
- data[name]['zone-names'] = [zone for zone in report_def[6][1:]]
447
- elif 'surface' in type_:
448
- data[name]['surface-ids'] = [surface for surface in report_def[4][1:]]
449
- data[name]['surface-names'] = [surface for surface in report_def[5][1:]]
450
- elif 'flux' in type_:
451
- data[name]['zone-ids'] = [zone for zone in report_def[2][1:]]
452
- data[name]['zone-names'] = [zone for zone in report_def[3][1:]]
514
+ for report_property in report_def[2:]:
515
+ match report_property:
516
+ case [prop_name, '.', value]:
517
+ data[name][prop_name] = value
518
+ case [prop_name, *values] if prop_name not in ('old-props', 'locations'):
519
+ data[name][prop_name] = values
520
+ case _:
521
+ continue
453
522
 
454
523
  avg_over_state = re.search(r'(\(monitor/average-over-state.*)', general, re.M).group(1)
455
524
  avg_over_state_list = stringify_nested_list(sexpdata.loads(avg_over_state, true=None)[1])
456
525
  for rd in avg_over_state_list:
457
526
  name = rd[0]
458
- ids = [id_.split('.')[0] for id_ in rd[1]]
459
- iter_range = rd[2][:2]
460
- data[name]['iter-range'] = ' -> '.join(iter_range)
527
+ data[name]['iter-range'] = rd[2][0] + ' -> ' + rd[2][1]
461
528
 
462
529
  if data[name].get('per-zone?') == '#f' or data[name].get('per-surface?') == '#f':
463
530
  value = rd[2][2]
464
531
  data[name]['average-over-state'] = value
465
532
  else:
533
+ ids = [id_.split('.')[0] for id_ in rd[1]]
466
534
  values = sum(rd[2][2:], [])
467
535
  right_order_ids = data[name].get('zone-list') or data[name].get('surface-ids') or data[name].get('zone-ids')
468
536
  sorted_values = [0] * len(values)
@@ -484,13 +552,16 @@ def _read_plotsets(texts: CaseTexts) -> dict[str, Any]:
484
552
 
485
553
  data: dict[str, Any] = {}
486
554
  for plotset in plotsets_list:
487
- plotset_dict = {
488
- property_[0]: property_[2]
489
- for property_ in plotset
490
- if property_[0] not in ['old-props', 'report-defs']
491
- }
492
- plotset_dict['report-defs'] = plotset[6][1:]
493
- data[plotset_dict['name']] = plotset_dict
555
+ name = plotset[0][2]
556
+ data[name] = {}
557
+ for plotset_property in plotset[1:]:
558
+ match plotset_property:
559
+ case [prop_name, '.', value]:
560
+ data[name][prop_name] = value
561
+ case [prop_name, *values] if prop_name not in ('old-props'):
562
+ data[name][prop_name] = values
563
+ case _:
564
+ continue
494
565
  return {'plotsets': data}
495
566
 
496
567
 
@@ -502,13 +573,16 @@ def _read_monitorsets(texts: CaseTexts) -> dict[str, Any]:
502
573
 
503
574
  data: dict[str, Any] = {}
504
575
  for monitorset in monitorsets_list:
505
- monitorset_dict = {
506
- property_[0]: property_[2]
507
- for property_ in monitorset
508
- if property_[0] not in ['old-props', 'report-defs']
509
- }
510
- monitorset_dict['report-defs'] = monitorset[-4][1:]
511
- data[monitorset_dict['name']] = monitorset_dict
576
+ name = monitorset[0][2]
577
+ data[name] = {}
578
+ for monitorset_property in monitorset[1:]:
579
+ match monitorset_property:
580
+ case [prop_name, '.', value]:
581
+ data[name][prop_name] = value
582
+ case [prop_name, *values] if prop_name not in ('old-props'):
583
+ data[name][prop_name] = values
584
+ case _:
585
+ continue
512
586
  return {'monitorsets': data}
513
587
 
514
588
 
@@ -596,31 +670,29 @@ def _read_surfaces(texts: CaseTexts) -> dict[str, Any]:
596
670
  data: dict[str, Any] = {}
597
671
  for surface_def in surface_def_list:
598
672
  surface = surface_def[2]
599
- surface_type = surface[0]
600
- match surface_type:
601
- case 'line-surface':
602
- virtual_id = surface[1]
673
+ match surface:
674
+ case ['line-surface', virtual_id, start, end]:
603
675
  data[virtual_id_name_map[virtual_id]] = {
604
- 'type': surface_type,
605
- 'start': surface[2],
606
- 'end': surface[3],
676
+ 'type': 'line-surface',
677
+ 'start': start,
678
+ 'end': end,
607
679
  }
608
- case 'plane-surface':
609
- virtual_id = surface[1]
680
+ case ['plane-surface', virtual_id, point1, point2, point3, bounded, [ref_plane, direction_vector, ref_point]]:
610
681
  data[virtual_id_name_map[virtual_id]] = {
611
- 'type': surface_type,
612
- 'point 1': surface[2],
613
- 'point 2': surface[3],
614
- 'point 3': surface[4],
615
- 'bounded': surface[5],
682
+ 'type': 'plane-surface',
683
+ 'point 1': point1,
684
+ 'point 2': point2,
685
+ 'point 3': point3,
686
+ 'bounded': bounded,
616
687
  'method': {
617
- 'type': surface[6][0],
618
- 'direction vector': surface[6][1],
619
- 'reference point': surface[6][2],
620
- },
688
+ 'reference plane': ref_plane,
689
+ 'direction vector': direction_vector,
690
+ 'reference point': ref_point,
691
+ }
621
692
  }
622
693
  case _:
623
694
  continue
695
+
624
696
  return {'surfaces': data}
625
697
 
626
698
 
@@ -635,25 +707,19 @@ def _read_contours(texts: CaseTexts) -> dict[str, Any]:
635
707
 
636
708
  data: dict[str, Any] = {}
637
709
  for contour in contours_list:
638
- contour_dict = {
639
- property_[0]: property_[2]
640
- for property_ in contour
641
- if property_[0] not in [
642
- 'locations', 'location-ids', 'options',
643
- 'range-options', 'range-option', 'surfaces-list',
644
- 'color-map', 'colorings', 'annotations-list',
645
- ]
646
- }
647
- contour_dict['surface-list'] = contour[2][1]
648
- contour_dict['range-options'] = {
649
- range_option[0]: range_option[2]
650
- for range_option in contour[6][1:]
651
- }
652
- contour_dict['color-map'] = {
653
- color_map[0]: color_map[2]
654
- for color_map in contour[-7][1:]
655
- }
656
- data[contour_dict['name']] = contour_dict
710
+ name = contour[0][2]
711
+ data[name] = {}
712
+ for contour_property in contour[1:]:
713
+ match contour_property:
714
+ case [property_name, '.', value]:
715
+ data[name][property_name] = value
716
+ case ['surfaces-list', *surfaces_list]:
717
+ data[name]['surfaces-list'] = surfaces_list
718
+ case [property_name, *values] if property_name in ('range-options', 'color-map'):
719
+ data[name][property_name] = {value[0]: value[2] for value in values}
720
+ case _:
721
+ continue
722
+
657
723
  return {'contours': data}
658
724
 
659
725
 
@@ -665,33 +731,19 @@ def _read_vectors(texts: CaseTexts) -> dict[str, Any]:
665
731
 
666
732
  data: dict[str, Any] = {}
667
733
  for vector in vectors_list:
668
- vector_dict = {
669
- property_[0]: property_[2]
670
- for property_ in vector
671
- if property_[0] not in [
672
- 'locations', 'location-ids', 'options', 'scale',
673
- 'range-options', 'range-option', 'surfaces-list',
674
- 'color-map', 'vector-opt', 'annotations-list',
675
- ]
676
- }
677
- vector_dict['surface-list'] = vector[3][1]
678
- vector_dict['range-options'] = {
679
- range_option[0]: range_option[2]
680
- for range_option in vector[7][1:]
681
- }
682
- vector_dict['scale'] = {
683
- scale[0]: scale[2]
684
- for scale in vector[9][1:]
685
- }
686
- vector_dict['vector-opt'] = {
687
- vector_opt[0]: vector_opt[2]
688
- for vector_opt in vector[-6][1:]
689
- }
690
- vector_dict['color-map'] = {
691
- color_map[0]: color_map[2]
692
- for color_map in vector[-5][1:]
693
- }
694
- data[vector_dict['name']] = vector_dict
734
+ name = vector[0][2]
735
+ data[name] = {}
736
+ for vector_property in vector[1:]:
737
+ match vector_property:
738
+ case [property_name, '.', value]:
739
+ data[name][property_name] = value
740
+ case ['surfaces-list', *surfaces_list]:
741
+ data[name]['surfaces-list'] = surfaces_list
742
+ case [property_name, *values] if property_name in ('range-options', 'scale', 'vector-opt', 'color-map'):
743
+ data[name][property_name] = {value[0]: value[2] for value in values}
744
+ case _:
745
+ continue
746
+
695
747
  return {'vectors': data}
696
748
 
697
749
 
@@ -703,17 +755,19 @@ def _read_xy_plot(texts: CaseTexts) -> dict[str, Any]:
703
755
 
704
756
  data: dict[str, Any] = {}
705
757
  for xy_plot in xy_plots_list:
706
- xy_plot_dict = {
707
- property_[0]: property_[2]
708
- for property_ in xy_plot
709
- if property_[0] not in [
710
- 'options', 'x-axis-data', 'y-axis-data',
711
- 'surfaces-list', 'location-ids', 'locations',
712
- 'option', 'plot-direction', 'axes',
713
- ]
714
- }
715
- xy_plot_dict['surfaces-list'] = xy_plot[7][1]
716
- data[xy_plot_dict['name']] = xy_plot_dict
758
+ name = xy_plot[0][2]
759
+ data[name] = {}
760
+ for xy_plot_property in xy_plot[1:]:
761
+ match xy_plot_property:
762
+ case [property_name, '.', value]:
763
+ data[name][property_name] = value
764
+ case ['surfaces-list', *surfaces_list]:
765
+ data[name]['surfaces-list'] = surfaces_list
766
+ case [property_name, *values] if property_name == 'options':
767
+ data[name][property_name] = {value[0]: value[2] for value in values}
768
+ case _:
769
+ continue
770
+
717
771
  return {'xy-plot': data}
718
772
 
719
773
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cffview
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A Python CLI tool to view Ansys Fluent .cas.h5/.msh.h5/.dat.h5 files without opening Fluent
5
5
  Author-email: preamer <1524477126@qq.com>
6
6
  License-Expression: BSD-3-Clause
File without changes
File without changes
File without changes
File without changes