pystormflow 0.2.1__tar.gz → 0.3.0__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.
- pystormflow-0.3.0/.cargo/config.toml +14 -0
- pystormflow-0.3.0/CHANGELOG.md +24 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/Cargo.lock +5 -5
- {pystormflow-0.2.1 → pystormflow-0.3.0}/Cargo.toml +3 -3
- {pystormflow-0.2.1 → pystormflow-0.3.0}/PKG-INFO +1 -1
- {pystormflow-0.2.1 → pystormflow-0.3.0}/pyproject.toml +2 -1
- {pystormflow-0.2.1 → pystormflow-0.3.0}/pystormflow/__init__.pyi +4 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/src/result_structs.rs +41 -7
- {pystormflow-0.2.1 → pystormflow-0.3.0}/src/simulation.rs +7 -4
- pystormflow-0.2.1/CHANGELOG.md +0 -14
- {pystormflow-0.2.1 → pystormflow-0.3.0}/.gitignore +0 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/LICENSE +0 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/README.md +0 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/pystormflow/__init__.py +0 -0
- {pystormflow-0.2.1 → pystormflow-0.3.0}/src/lib.rs +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Cargo configuration for pystormflow
|
|
2
|
+
# These settings optimize the build for the user's specific CPU
|
|
3
|
+
|
|
4
|
+
[build]
|
|
5
|
+
# Use all available CPU cores for compilation
|
|
6
|
+
jobs = -1
|
|
7
|
+
|
|
8
|
+
[target.'cfg(target_arch = "x86_64")']
|
|
9
|
+
# Enable native CPU optimizations (AVX, AVX2, etc. if available)
|
|
10
|
+
rustflags = ["-C", "target-cpu=native"]
|
|
11
|
+
|
|
12
|
+
[target.'cfg(target_arch = "aarch64")']
|
|
13
|
+
# Enable native CPU optimizations for ARM64 (Apple Silicon, etc.)
|
|
14
|
+
rustflags = ["-C", "target-cpu=native"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Change log pystormflow
|
|
2
|
+
|
|
3
|
+
This file contains an overview of the changes made to pystormflow, the Python interface to the Stormflow CFD solver. See the [Stormflow change log](../../stormflow/CHANGELOG.md) for changes to the solver, and the [Stormbird change log](../../stormbird/CHANGELOG.md) for changes to the actuator line model.
|
|
4
|
+
|
|
5
|
+
## 0.3.0 - 2026-10-31
|
|
6
|
+
### Breaking changes
|
|
7
|
+
- Depends on the published versions of Stormflow 0.3.0 and Stormbird 0.12.0. There are no changes to the Python interface itself, but the setup files may need to be updated. See the [Stormflow change log](../../stormflow/CHANGELOG.md) for the changes to the solver, such as the new `boundary_condition_type` setting, and the [Stormbird change log](../../stormbird/CHANGELOG.md) for the changes to the actuator line model, such as the new dynamic stall model.
|
|
8
|
+
|
|
9
|
+
### Other changes
|
|
10
|
+
- Invalid input raises a Python exception rather than a panic, in the same way as in pystormbird: creating a `Simulation` from a setup string that can not be read raises a `ValueError`, and reading simulation results from file with `SimulationResult.from_json_file` or `SimulationResult.result_history_from_file` raises an `OSError` if the file can not be read, and a `ValueError` if the content can not be parsed. Settings that are found to be invalid when the simulation is built in Stormflow still give a panic.
|
|
11
|
+
- New `section_models_internal_state` and `amount_of_stall` properties on the `SectionalForcesInput` class, as in pystormbird.
|
|
12
|
+
- The source distribution is compiled with native CPU optimizations, through a new `.cargo/config.toml`, as in pystormbird.
|
|
13
|
+
- The single rotor example is replaced by the new `rotor_sails/deybach_wind_tunnel` example, with one or two rotor sails in a wind tunnel, compared against the experiments by Deybach et al.
|
|
14
|
+
|
|
15
|
+
## 0.2.1
|
|
16
|
+
- Depends on Stormflow 0.2.1 and Stormbird 0.11.1. The main changes are new experimental limits on the lifting line correction in the actuator line model. See the [Stormflow change log](../../stormflow/CHANGELOG.md) and the [Stormbird change log](../../stormbird/CHANGELOG.md).
|
|
17
|
+
|
|
18
|
+
## 0.2.0 - 2026-10-23
|
|
19
|
+
### Breaking changes
|
|
20
|
+
- Depends on Stormflow 0.2.0, Stormbird 0.11.0 and Stormath 0.4.0. The input format for the Stormbird models has changed in Stormbird 0.11.0, so setup files may need to be updated.
|
|
21
|
+
- The `gyroscopic` property of the `SectionalForces` class is renamed to `gyroscopic_moment`, as the gyroscopic effect is now a pure moment in Stormbird. The `gyroscopic` property of the `IntegratedValues` class is unchanged.
|
|
22
|
+
|
|
23
|
+
## 0.1.0
|
|
24
|
+
The first version.
|
|
@@ -919,7 +919,7 @@ dependencies = [
|
|
|
919
919
|
|
|
920
920
|
[[package]]
|
|
921
921
|
name = "pystormflow"
|
|
922
|
-
version = "0.
|
|
922
|
+
version = "0.3.0"
|
|
923
923
|
dependencies = [
|
|
924
924
|
"pyo3",
|
|
925
925
|
"stormath",
|
|
@@ -1141,9 +1141,9 @@ dependencies = [
|
|
|
1141
1141
|
|
|
1142
1142
|
[[package]]
|
|
1143
1143
|
name = "stormbird"
|
|
1144
|
-
version = "0.
|
|
1144
|
+
version = "0.12.0"
|
|
1145
1145
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1146
|
-
checksum = "
|
|
1146
|
+
checksum = "58dd3ef773ce702fd01e8928fd09c122b71dfe0d611850d1c066cc775e212929"
|
|
1147
1147
|
dependencies = [
|
|
1148
1148
|
"serde",
|
|
1149
1149
|
"serde_json",
|
|
@@ -1152,9 +1152,9 @@ dependencies = [
|
|
|
1152
1152
|
|
|
1153
1153
|
[[package]]
|
|
1154
1154
|
name = "stormflow"
|
|
1155
|
-
version = "0.
|
|
1155
|
+
version = "0.3.0"
|
|
1156
1156
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1157
|
-
checksum = "
|
|
1157
|
+
checksum = "af8cf495075d36001dbac15413c67142fd30915a5ced8dc28a0eba76e8c8ba2c"
|
|
1158
1158
|
dependencies = [
|
|
1159
1159
|
"bytemuck",
|
|
1160
1160
|
"clap",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "pystormflow"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
authors = ["Jarle Kramer <jarle.kramer@gmail.com>"]
|
|
5
5
|
description = "Python interface to the Stormflow CFD solver."
|
|
6
6
|
homepage = "https://github.com/NTNU-IMT/stormbird"
|
|
@@ -16,8 +16,8 @@ crate-type = ["cdylib"]
|
|
|
16
16
|
[dependencies]
|
|
17
17
|
pyo3 = "0.29.0"
|
|
18
18
|
stormath = {version = "0.4.0", features=["single_precision"]}
|
|
19
|
-
stormbird = { version="0.
|
|
20
|
-
stormflow =
|
|
19
|
+
stormbird = { version = "0.12.0", features = ["single_precision"] }
|
|
20
|
+
stormflow = "0.3.0"
|
|
21
21
|
|
|
22
22
|
[profile.release]
|
|
23
23
|
opt-level = 3
|
|
@@ -35,7 +35,8 @@ module-name = "pystormflow._native"
|
|
|
35
35
|
python-source = "."
|
|
36
36
|
features = ["pyo3/extension-module"]
|
|
37
37
|
profile = "release"
|
|
38
|
-
# The examples are not needed in the source distribution
|
|
38
|
+
# The examples and the notes for the maintainer are not needed in the source distribution
|
|
39
39
|
exclude = [
|
|
40
40
|
{ path = "examples/**/*", format = "sdist" },
|
|
41
|
+
{ path = "maintainer_cheat_sheet.md", format = "sdist" },
|
|
41
42
|
]
|
|
@@ -9,6 +9,10 @@ class SectionalForcesInput:
|
|
|
9
9
|
@property
|
|
10
10
|
def angles_of_attack(self) -> list[float]: ...
|
|
11
11
|
@property
|
|
12
|
+
def section_models_internal_state(self) -> list[float]: ...
|
|
13
|
+
@property
|
|
14
|
+
def amount_of_stall(self) -> list[float]: ...
|
|
15
|
+
@property
|
|
12
16
|
def acceleration(self) -> list[list[float]]: ...
|
|
13
17
|
@property
|
|
14
18
|
def rotation_velocity(self) -> list[float]: ...
|
|
@@ -4,9 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
use pyo3::prelude::*;
|
|
6
6
|
use pyo3::types::PyType;
|
|
7
|
+
use pyo3::exceptions::{PyIOError, PyValueError};
|
|
7
8
|
|
|
8
9
|
use stormath::type_aliases::Float;
|
|
9
10
|
|
|
11
|
+
use stormbird::error::Error;
|
|
12
|
+
|
|
10
13
|
use stormbird::common_utils::results::simulation::SimulationResult as SimulationResultRust;
|
|
11
14
|
use stormbird::common_utils::forces_and_moments::SectionalForces as SectionalForcesRust;
|
|
12
15
|
use stormbird::common_utils::forces_and_moments::IntegratedValues as IntegratedValuesRust;
|
|
@@ -35,6 +38,20 @@ impl SectionalForcesInput {
|
|
|
35
38
|
self.data.angles_of_attack.clone()
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
#[getter]
|
|
42
|
+
/// The internal state given to the section model on each line element
|
|
43
|
+
pub fn section_models_internal_state(&self) -> Vec<Float> {
|
|
44
|
+
self.data.section_models_internal_state.clone()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[getter]
|
|
48
|
+
/// The amount of stall used for the lift and drag on each line element. This is the dynamic
|
|
49
|
+
/// amount of stall for wings with a dynamic stall model, and zero for section models that are
|
|
50
|
+
/// not built on the foil model.
|
|
51
|
+
pub fn amount_of_stall(&self) -> Vec<Float> {
|
|
52
|
+
self.data.amount_of_stall.clone()
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
#[getter]
|
|
39
56
|
pub fn acceleration(&self) -> Vec<[Float; 3]> {
|
|
40
57
|
self.data.acceleration.iter().map(|v| v.0).collect()
|
|
@@ -123,17 +140,21 @@ pub struct SimulationResult {
|
|
|
123
140
|
#[pymethods]
|
|
124
141
|
impl SimulationResult {
|
|
125
142
|
#[classmethod]
|
|
126
|
-
pub fn from_json_file(_cls: &Bound<'_, PyType>, file_path: String) -> SimulationResult {
|
|
127
|
-
let data = SimulationResultRust::from_json(&file_path).
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
pub fn from_json_file(_cls: &Bound<'_, PyType>, file_path: String) -> PyResult<SimulationResult> {
|
|
144
|
+
let data = SimulationResultRust::from_json(&file_path).map_err(|e| {
|
|
145
|
+
Self::read_file_error(&file_path, e)
|
|
146
|
+
})?;
|
|
147
|
+
|
|
148
|
+
Ok(SimulationResult { data })
|
|
130
149
|
}
|
|
131
150
|
|
|
132
151
|
#[classmethod]
|
|
133
|
-
pub fn result_history_from_file(_cls: &Bound<'_, PyType>, file_path: String) -> Vec<SimulationResult
|
|
134
|
-
let rust_vector = SimulationResultRust::result_history_from_file(&file_path).
|
|
152
|
+
pub fn result_history_from_file(_cls: &Bound<'_, PyType>, file_path: String) -> PyResult<Vec<SimulationResult>> {
|
|
153
|
+
let rust_vector = SimulationResultRust::result_history_from_file(&file_path).map_err(|e| {
|
|
154
|
+
Self::read_file_error(&file_path, e)
|
|
155
|
+
})?;
|
|
135
156
|
|
|
136
|
-
rust_vector.iter().map(|v| SimulationResult { data: v.clone() }).collect()
|
|
157
|
+
Ok(rust_vector.iter().map(|v| SimulationResult { data: v.clone() }).collect())
|
|
137
158
|
}
|
|
138
159
|
|
|
139
160
|
#[getter]
|
|
@@ -209,3 +230,16 @@ impl SimulationResult {
|
|
|
209
230
|
self.data.write_to_file(&file_path).expect("Error from write to file")
|
|
210
231
|
}
|
|
211
232
|
}
|
|
233
|
+
|
|
234
|
+
impl SimulationResult {
|
|
235
|
+
/// Converts an error from reading a result file to a Python error. Errors from reading the
|
|
236
|
+
/// file become an OSError, while errors from parsing the content become a ValueError.
|
|
237
|
+
fn read_file_error(file_path: &str, error: Error) -> PyErr {
|
|
238
|
+
let message = format!("Failed to read simulation result from file {}: {}", file_path, error);
|
|
239
|
+
|
|
240
|
+
match error {
|
|
241
|
+
Error::IoError(_) => PyIOError::new_err(message),
|
|
242
|
+
_ => PyValueError::new_err(message),
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
use pyo3::prelude::*;
|
|
3
3
|
use pyo3::types::PyBytes;
|
|
4
|
+
use pyo3::exceptions::PyValueError;
|
|
4
5
|
|
|
5
6
|
use stormath::type_aliases::Float;
|
|
6
7
|
use stormflow::simulation::Simulation as SimulationRust;
|
|
@@ -15,10 +16,12 @@ pub struct Simulation {
|
|
|
15
16
|
#[pymethods]
|
|
16
17
|
impl Simulation {
|
|
17
18
|
#[new]
|
|
18
|
-
pub fn new(setup_string: String) -> Self {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
pub fn new(setup_string: String) -> PyResult<Self> {
|
|
20
|
+
let data = SimulationRust::new_from_string(&setup_string).map_err(|e| {
|
|
21
|
+
PyValueError::new_err(format!("Failed to create simulation from string: {}", e))
|
|
22
|
+
})?;
|
|
23
|
+
|
|
24
|
+
Ok(Self { data })
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
pub fn time_step_from_courant_number(&self, courant_number: Float) -> Float {
|
pystormflow-0.2.1/CHANGELOG.md
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Change log pystormflow
|
|
2
|
-
|
|
3
|
-
This file contains an overview of the changes made to pystormflow, the Python interface to the Stormflow CFD solver. See the [Stormflow change log](../../stormflow/CHANGELOG.md) for changes to the solver, and the [Stormbird change log](../../stormbird/CHANGELOG.md) for changes to the actuator line model.
|
|
4
|
-
|
|
5
|
-
## 0.2.1
|
|
6
|
-
- Depends on Stormflow 0.2.1 and Stormbird 0.11.1. The main changes are new experimental limits on the lifting line correction in the actuator line model. See the [Stormflow change log](../../stormflow/CHANGELOG.md) and the [Stormbird change log](../../stormbird/CHANGELOG.md).
|
|
7
|
-
|
|
8
|
-
## 0.2.0 - 2026-10-23
|
|
9
|
-
### Breaking changes
|
|
10
|
-
- Depends on Stormflow 0.2.0, Stormbird 0.11.0 and Stormath 0.4.0. The input format for the Stormbird models has changed in Stormbird 0.11.0, so setup files may need to be updated.
|
|
11
|
-
- The `gyroscopic` property of the `SectionalForces` class is renamed to `gyroscopic_moment`, as the gyroscopic effect is now a pure moment in Stormbird. The `gyroscopic` property of the `IntegratedValues` class is unchanged.
|
|
12
|
-
|
|
13
|
-
## 0.1.0
|
|
14
|
-
The first version.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|