Coverage for /opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/pysagas/sensitivity/cart3d/cart3d.py: 83%
65 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-10-30 04:27 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-10-30 04:27 +0000
1import numpy as np
2import pandas as pd
3from tqdm import tqdm
4from typing import List, Optional
5from pysagas.flow import FlowState
6from pysagas.sensitivity.calculator import SensitivityCalculator
7from pysagas.geometry import Vector, Cell, DegenerateCell
8from pysagas.sensitivity.cart3d.utilities import process_components_file
11class Cart3DSensitivityCalculator(SensitivityCalculator):
12 """PySAGAS Cart3D flow sensitivity calculator."""
14 solver = "Cart3D"
16 def __init__(
17 self,
18 freestream: FlowState,
19 sensitivity_filepath: str,
20 components_filepath: Optional[str] = None,
21 pointdata: Optional[pd.DataFrame] = None,
22 celldata: Optional[pd.DataFrame] = None,
23 write_data: Optional[bool] = False,
24 verbosity: Optional[int] = 1,
25 **kwargs,
26 ) -> None:
27 """A PySAGAS sensitivity calculator for Cart3D.
29 Parameters
30 ----------
31 freestream : FlowState
32 The flow state of the freestream.
34 sensitivity_filepath : str
35 The filepath to the geometry sensitivities.
37 components_filepath : str, optional
38 The filepath to the Components.i.plt file to be processed.
39 The default is None.
41 pointdata : pd.DataFrame, optional
42 The point data. Must be supplied with celldata.
44 celldata : pd.DataFrame, optional
45 The cell data. Must be supplied with pointdata.
47 write_data : bool, optional
48 Write the flow data to CSV files. The default is True.
50 verbosity : int, optional
51 The verbosity of the code. The defualt is 1.
52 """
53 # Load data
54 self.sensdata = pd.read_csv(sensitivity_filepath)
55 if pointdata is not None and celldata is not None:
56 self.pointdata = pointdata
57 self.celldata = celldata
58 else:
59 self.pointdata, self.celldata = process_components_file(
60 freestream.a,
61 freestream.rho,
62 components_filepath,
63 write_data=write_data,
64 verbosity=verbosity,
65 )
66 self.verbosity = verbosity
68 # Check dimensionality
69 l1 = len(self.sensdata)
70 l2 = len(self.pointdata)
71 if l1 != l2:
72 raise ValueError(
73 f"The sensitivity data does not match the point data ({l1} vs. {l2})."
74 )
76 super().__init__(**kwargs)
78 def _transcribe_cells(self, parameters: List[str]) -> List[Cell]:
79 """Transcribes the cells from Components.i.plt files into
80 PySAGAS Cell objects.
82 Parameters
83 -----------
84 parameters : List[str]
85 A list of the geometric design parameters.
87 Returns
88 --------
89 cells : List[Cell]
90 A list of all transcribed cells.
92 See Also
93 --------
94 pysagas.geometry.Cell
95 """
96 coordinates = self.pointdata[["Points_0", "Points_1", "Points_2"]]
97 cell_vertex_ids = self.celldata[
98 ["Point Index 0", "Point Index 1", "Point Index 2"]
99 ]
101 # Construct cells
102 if self.verbosity > 0:
103 print("\nTranscribing cells from Components.i.plt...")
104 pbar = tqdm(
105 total=len(self.celldata.index),
106 position=0,
107 leave=True,
108 )
109 cells = []
110 degen_cells = 0
111 for cell in self.celldata.index:
112 vertex_ids = cell_vertex_ids.loc[cell].values
113 cell_v_coords = [coordinates.loc[v_id].values for v_id in vertex_ids]
114 vertices = [Vector.from_coordinates(c) for c in cell_v_coords]
116 # Extract sensitivity information for the cell
117 vertex_sensitivity_info = [self.sensdata.loc[v_id] for v_id in vertex_ids]
119 dvdp = np.empty((9, len(parameters)))
120 for i, p in enumerate(parameters):
121 r = 0
122 for v in vertex_sensitivity_info:
123 for c in ["x", "y", "z"]:
124 dvdp[r, i] = v[f"d{c}d{p}"]
125 r += 1
127 # Create Cell
128 try:
129 newcell = Cell.from_points(vertices)
130 except DegenerateCell:
131 # Bad cell, skip it
132 degen_cells += 1
133 if self.verbosity > 0:
134 pbar.update(1)
136 if self.verbosity > 2:
137 print("\033[1mWarning\033[0m: Degenerate cell.")
138 continue
140 # Add geometry sensitivity information
141 newcell._add_sensitivities(np.array(dvdp))
143 # Add flow state at cell
144 cell_velocity = Vector.from_coordinates(
145 self.celldata.loc[cell][["U", "V", "W"]].values
146 )
147 cell_flowstate = FlowState(
148 mach=self.celldata.loc[cell]["M"],
149 pressure=self.celldata.loc[cell]["p"],
150 temperature=self.celldata.loc[cell]["T"],
151 direction=cell_velocity,
152 )
153 newcell.flowstate = cell_flowstate
155 # Append new Cell
156 cells.append(newcell)
158 # Update progress bar
159 if self.verbosity > 0:
160 pbar.update(1)
162 if self.verbosity > 0:
163 pbar.close()
164 print("Done.")
166 if self.verbosity > 1:
167 if degen_cells > 0:
168 print(f"{100*degen_cells/len(self.celldata):.2f}% degenerate cells")
170 return cells