Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0aba42d
Create the module for core classes
camUrban Mar 27, 2026
760390a
Add _get_steady_problem_at method
camUrban Mar 27, 2026
022c703
Route steady_problems access through dispatch
camUrban Mar 27, 2026
f39c273
Extract _initialize_panel_vortices_at
camUrban Mar 27, 2026
5c674fc
Replace batch oscillating functions
camUrban Mar 28, 2026
e3d0b4f
Add CoreMovement to _core.py
camUrban Mar 28, 2026
5c5f06c
Refactor Movement to extend CoreMovement
camUrban Mar 28, 2026
1419b4c
Fix RTD build and clean up doc links
camUrban Mar 28, 2026
508f737
Fix inherited-members option name
camUrban Mar 28, 2026
1aa4af6
Add CoreOperatingPointMovement to _core.py
camUrban Mar 29, 2026
377761b
Add CoreWingCrossSectionMovement to _core.py
camUrban Mar 29, 2026
cf5e87b
Add CoreWingMovement to _core.py
camUrban Mar 29, 2026
4af2ddb
Add CoreAirplaneMovement to _core.py
camUrban Mar 30, 2026
4e3945c
Add CoreUnsteadyProblem to _core.py
camUrban Mar 30, 2026
492cf66
Add free flight wing movement skeletons
camUrban Mar 30, 2026
c187411
Add FreeFlightAirplaneMovement
camUrban Mar 30, 2026
ca6a6aa
Enforce child type within each hierarchy
camUrban Mar 30, 2026
c2a17e7
Add FreeFlightOperatingPointMovement
camUrban Mar 30, 2026
bdf3c69
Add FreeFlightMovement
camUrban Mar 30, 2026
b225f72
Move oscillation functions to _oscillation.py
camUrban Mar 31, 2026
dbf4dd1
Add Aeroelastic movement skeletons
camUrban Mar 31, 2026
2f4936b
Exclude skeleton modules from docs
camUrban Mar 31, 2026
7eaf936
Add CoreWingCrossSectionMovement test module
camUrban Mar 31, 2026
42cf1b3
Add CoreWingMovement test module
camUrban Mar 31, 2026
47a9002
Add CoreAirplaneMovement test module
camUrban Mar 31, 2026
efdf2c4
Add CoreOperatingPointMovement test module
camUrban Mar 31, 2026
031ddff
Add CoreMovement test module
camUrban Mar 31, 2026
f4cd8f3
Add CoreUnsteadyProblem test module
camUrban Mar 31, 2026
fa34138
Add cleanup and core slots tests
camUrban Mar 31, 2026
4613419
Precompute lcm_period cache
camUrban Mar 31, 2026
fd14b68
Fix core class docstrings for RTD
camUrban Mar 31, 2026
d62a4fe
Delete unused fixtures and dead setUp attrs
camUrban Mar 31, 2026
5f14b81
Clean up test imports and references
camUrban Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/inspectionProfiles/Ptera_Software_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 43 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,26 @@ Requires Python 3.11, but active development is done in 3.13
- `wing.py`: Wing class with symmetry processing
- `wing_cross_section.py`: WingCrossSection class with validation
- `movements/`: Package with movement classes (definitions for time-dependent motion)
- `_functions.py`: Movement utility functions
- `airplane_movement.py`: Airplane motion definitions
- `movement.py`: Core Movement class
- `operating_point_movement.py`: Operating condition changes
- `wing_cross_section_movement.py`: Wing cross section motion
- `wing_movement.py`: Wing flapping motion
- `aeroelastic_airplane_movement.py`: AeroelasticAirplaneMovement skeleton
- `aeroelastic_movement.py`: AeroelasticMovement skeleton
- `aeroelastic_operating_point_movement.py`: AeroelasticOperatingPointMovement skeleton
- `aeroelastic_wing_cross_section_movement.py`: AeroelasticWingCrossSectionMovement skeleton
- `aeroelastic_wing_movement.py`: AeroelasticWingMovement skeleton
- `airplane_movement.py`: AirplaneMovement class
- `free_flight_airplane_movement.py`: FreeFlightAirplaneMovement skeleton
- `free_flight_movement.py`: FreeFlightMovement skeleton
- `free_flight_operating_point_movement.py`: FreeFlightOperatingPointMovement skeleton
- `free_flight_wing_cross_section_movement.py`: FreeFlightWingCrossSectionMovement skeleton
- `free_flight_wing_movement.py`: FreeFlightWingMovement skeleton
- `movement.py`: Movement class
- `operating_point_movement.py`: OperatingPointMovement class
- `wing_cross_section_movement.py`: WingCrossSectionMovement class
- `wing_movement.py`: WingMovement class
- `_aerodynamics_functions.py`: Induced velocity functions
- `_core.py`: Core classes for the movement and problem hierarchies
- `_functions.py`: Shared utility functions
- `_logging.py`: Contains function for setting up logging
- `_oscillation.py`: Oscillation functions for movement classes
- `_panel.py`: Panel class for discretized mesh elements
- `_parameter_validation.py`: Input validation functions
- `_serialization.py`: JSON serialization and deserialization (save/load)
Expand Down Expand Up @@ -112,40 +123,62 @@ Requires Python 3.11, but active development is done in 3.13
- `test_serialization_output.py`
- `test_steady_convergence.py`
- `test_steady_horseshoe_vortex_lattice_method.py`
- `test_steady_horseshoe_vortex_lattice_method_surface_effect.py`
- `test_steady_ring_vortex_lattice_method.py`
- `test_steady_ring_vortex_lattice_method_surface_effect.py`
- `test_steady_trim.py`
- `test_unsteady_convergence.py`
- `test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry.py`
- `test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry.py`
- `test_unsteady_ring_vortex_lattice_method_static_geometry.py`
- `test_unsteady_ring_vortex_lattice_method_surface_effect.py`
- `test_unsteady_ring_vortex_lattice_method_variable_geometry.py`
- `test_unsteady_ring_vortex_lattice_method_wake_truncation.py`
- `unit/`: Unit tests for individual classes and functions
- `fixtures/`: Fixtures for unit tests
- `aerodynamics_function_fixtures.py`
- `aerodynamics_functions_fixtures.py`
- `airplane_movement_fixtures.py`
- `core_airplane_movement_fixtures.py`
- `core_movement_fixtures.py`
- `core_operating_point_movement_fixtures.py`
- `core_wing_cross_section_movement_fixtures.py`
- `core_wing_movement_fixtures.py`
- `geometry_fixtures.py`
- `horseshoe_fixtures.py`
- `horseshoe_vortex_fixtures.py`
- `line_vortex_fixtures.py`
- `movement_fixtures.py`
- `movement_function_fixtures.py`
- `operating_point_fixtures.py`
- `operating_point_movement_fixtures.py`
- `oscillation_fixtures.py`
- `panel_fixtures.py`
- `parameter_validation_fixtures.py`
- `problem_fixtures.py`
- `ring_vortex_fixtures.py`
- `serialization_fixtures.py`
- `solver_fixtures.py`
- `wing_cross_section_movement_fixtures.py`
- `wing_movement_fixtures.py`
- `test_aerodynamics_functions.py`
- `test_airfoil.py`
- `test_airplane.py`
- `test_airplane_movement.py`
- `test_core.py`
- `test_core_airplane_movement.py`
- `test_core_movement.py`
- `test_core_operating_point_movement.py`
- `test_core_unsteady_problem.py`
- `test_core_wing_cross_section_movement.py`
- `test_core_wing_movement.py`
- `test_horseshoe_vortex.py`
- `test_line_vortex.py`
- `test_logging.py`
- `test_movement.py`
- `test_movement_functions.py`
- `test_operating_point.py`
- `test_operating_point_movement.py`
- `test_oscillation.py`
- `test_package_init.py`
- `test_panel.py`
- `test_parameter_validation.py`
- `test_problems.py`
- `test_ring_vortex.py`
- `test_serialization.py`
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ We are excited that you are interested in contributing to **Ptera Software**! Th

## Before Contributing

Please review the following documents before making contributions. These documents are also available on the [Ptera Software documentation website](https://pterasoftware.readthedocs.io/).
Please review the following documents before making contributions. These documents are also available on the [Ptera Software documentation website](https://docs.pterasoftware.com/).

1. [README](README.md)
2. [Code of Conduct](CODE_OF_CONDUCT.md)
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ If you haven't already, install Ptera Software from PyPI (see [Quick Start](#qui
pip install pterasoftware
```

Your IDE should automatically provide docstring hints for the available classes and functions. For more detailed documentation, visit the [Ptera Software documentation site](https://pterasoftware.readthedocs.io/).
Your IDE should automatically provide docstring hints for the available classes and functions. For more detailed documentation, visit the [Ptera Software documentation site](https://docs.pterasoftware.com/).

### From Source

If you want to browse the example scripts or dig into the source code, you will need a local copy of the repository. Follow the environment setup instructions in the [Contributing Guidelines](CONTRIBUTING.md#contributing-code) to clone the repository, create a virtual environment, and install dependencies.

Once set up, the `examples/` directory contains scripts that demonstrate the full range of Ptera Software's features and solvers. These scripts are also available on the [documentation site](https://pterasoftware.readthedocs.io/en/latest/examples.html).
Once set up, the `examples/` directory contains scripts that demonstrate the full range of Ptera Software's features and solvers. These scripts are also available on the [documentation site](https://docs.pterasoftware.com/en/latest/examples.html).

## Example Output

Expand All @@ -150,7 +150,7 @@ Since the release of version 1.0.0, Ptera Software is now validated against expe

## Documentation

For detailed API documentation and guides, visit the [Ptera Software documentation site](https://pterasoftware.readthedocs.io/).
For detailed API documentation and guides, visit the [Ptera Software documentation site](https://docs.pterasoftware.com/).

## How to Contribute

Expand Down
100 changes: 57 additions & 43 deletions docs/CLASSES_AND_IMMUTABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

This document describes the consistent pattern of immutability and lazy caching across the following core data and geometry classes in the Ptera Software codebase:

- `UnsteadyProblem`
- `Movement`
- `AirplaneMovement`
- `WingMovement`
- `WingCrossSectionMovement`
- `OperatingPointMovement`
- `CoreUnsteadyProblem` / `UnsteadyProblem`
- `CoreMovement` / `Movement`
- `CoreAirplaneMovement` / `AirplaneMovement`
- `CoreWingMovement` / `WingMovement`
- `CoreWingCrossSectionMovement` / `WingCrossSectionMovement`
- `CoreOperatingPointMovement` / `OperatingPointMovement`
- `SteadyProblem`
- `OperatingPoint`
- `Airplane`
Expand All @@ -19,6 +19,8 @@ This document describes the consistent pattern of immutability and lazy caching
- `HorseshoeVortex`
- `LineVortex`

The `Core*` classes live in `pterasoftware/_core.py` and own the shared slots and properties. The public classes extend their core parents, sometimes adding additional slots and sometimes inheriting everything with an empty `__slots__`. See each class section below for details on which attributes are defined at which level.

## Design Principles

### Class Attribute Categories
Expand Down Expand Up @@ -85,22 +87,24 @@ Store collections as tuples internally to prevent external mutation via `.append

---

## UnsteadyProblem Class (`problems.py`)
## CoreUnsteadyProblem / UnsteadyProblem Class (`_core.py`, `problems.py`)

`UnsteadyProblem` extends `CoreUnsteadyProblem`. `CoreUnsteadyProblem` owns all attributes except `movement` and `steady_problems`, which are defined on `UnsteadyProblem`.

### Attribute Classification

#### Immutable (set in `__init__`, never modified)

| Attribute | Type | Notes |
|------------------------|-----------------------------|-----------------------|
| `movement` | `Movement` | Movement definition |
| `only_final_results` | `bool` | Results flag |
| `num_steps` | `int` | Copied from Movement |
| `delta_time` | `float` | Copied from Movement |
| `first_averaging_step` | `int` | Computed during init |
| `first_results_step` | `int` | Computed during init |
| `max_wake_rows` | `int \| None` | Copied from Movement |
| `steady_problems` | `tuple[SteadyProblem, ...]` | Generated during init |
| Attribute | Type | Defined On | Notes |
|------------------------|-----------------------------|-------------------------|-----------------------|
| `movement` | `Movement` | `UnsteadyProblem` | Movement definition |
| `only_final_results` | `bool` | `CoreUnsteadyProblem` | Results flag |
| `num_steps` | `int` | `CoreUnsteadyProblem` | Copied from Movement |
| `delta_time` | `float` | `CoreUnsteadyProblem` | Copied from Movement |
| `first_averaging_step` | `int` | `CoreUnsteadyProblem` | Computed during init |
| `first_results_step` | `int` | `CoreUnsteadyProblem` | Computed during init |
| `max_wake_rows` | `int \| None` | `CoreUnsteadyProblem` | Copied from Movement |
| `steady_problems` | `tuple[SteadyProblem, ...]` | `UnsteadyProblem` | Generated during init |

#### Mutable (populated by solver)

Expand All @@ -119,40 +123,44 @@ Store collections as tuples internally to prevent external mutation via `.append
| `finalRmsMoments_W_CgP1` | `list[np.ndarray]` | RMS moments |
| `finalRmsMomentCoefficients_W_CgP1` | `list[np.ndarray]` | RMS moment coefficients |

**Note**: The solver result lists must remain mutable as they are populated after initialization by the solver. These are initialized as empty lists and appended to during the solve.
**Note**: The mutable solver result lists are defined on `CoreUnsteadyProblem` and must remain mutable as they are populated after initialization by the solver. These are initialized as empty lists and appended to during the solve.

## Movement Class (`movements/movement.py`)
## CoreMovement / Movement Class (`_core.py`, `movements/movement.py`)

`Movement` extends `CoreMovement`. `CoreMovement` owns the shared slots (`airplane_movements`, `operating_point_movement`, `delta_time`, `num_steps`, `max_wake_rows`) and derived properties (`lcm_period`, `max_period`, `min_period`, `static`). `Movement` adds cycle/chord counting, wake sizing parameters, and batch pre-generation of `Airplane`s and `OperatingPoint`s.

### Attribute Classification

#### Immutable (set in `__init__`, never modified)

| Attribute | Type | Notes |
|----------------------------|------------------------------------|---------------------------|
| `airplane_movements` | `tuple[AirplaneMovement, ...]` | Tuple prevents mutation |
| `operating_point_movement` | `OperatingPointMovement` | Operating point changes |
| `delta_time` | `float` | Time step |
| `num_cycles` | `int \| None` | Number of cycles |
| `num_chords` | `int \| None` | Number of chord lengths |
| `num_steps` | `int` | Total time steps |
| `max_wake_rows` | `int \| None` | Max wake rows per Wing |
| `max_wake_chords` | `int \| None` | Max wake in chord lengths |
| `max_wake_cycles` | `int \| None` | Max wake in motion cycles |
| `airplanes` | `tuple[tuple[Airplane, ...], ...]` | Generated Airplanes |
| `operating_points` | `tuple[OperatingPoint, ...]` | Generated OperatingPoints |
| Attribute | Type | Defined On | Notes |
|----------------------------|------------------------------------|----------------|---------------------------|
| `airplane_movements` | `tuple[AirplaneMovement, ...]` | `CoreMovement` | Tuple prevents mutation |
| `operating_point_movement` | `OperatingPointMovement` | `CoreMovement` | Operating point changes |
| `delta_time` | `float` | `CoreMovement` | Time step |
| `num_steps` | `int` | `CoreMovement` | Total time steps |
| `max_wake_rows` | `int \| None` | `CoreMovement` | Max wake rows per Wing |
| `num_cycles` | `int \| None` | `Movement` | Number of cycles |
| `num_chords` | `int \| None` | `Movement` | Number of chord lengths |
| `max_wake_chords` | `int \| None` | `Movement` | Max wake in chord lengths |
| `max_wake_cycles` | `int \| None` | `Movement` | Max wake in motion cycles |
| `airplanes` | `tuple[tuple[Airplane, ...], ...]` | `Movement` | Generated Airplanes |
| `operating_points` | `tuple[OperatingPoint, ...]` | `Movement` | Generated OperatingPoints |

#### Derived from Immutable (use manual lazy caching)

| Property | Depends On | Notes |
|--------------|--------------------------------------------------|--------|
| `lcm_period` | `airplane_movements`, `operating_point_movement` | Cached |
| `max_period` | `airplane_movements`, `operating_point_movement` | Cached |
| `min_period` | `airplane_movements`, `operating_point_movement` | Cached |
| `static` | `max_period` | Cached |
| Property | Depends On | Defined On | Notes |
|--------------|--------------------------------------------------|----------------|--------|
| `lcm_period` | `airplane_movements`, `operating_point_movement` | `CoreMovement` | Cached |
| `max_period` | `airplane_movements`, `operating_point_movement` | `CoreMovement` | Cached |
| `min_period` | `airplane_movements`, `operating_point_movement` | `CoreMovement` | Cached |
| `static` | `max_period` | `CoreMovement` | Cached |

**Note on `airplanes` and `operating_points`**: These are defined on `Movement` and generated during `__init__` by calling the child movements' `generate_*` methods. They are stored as nested tuples to prevent modification after generation.

**Note on `airplanes` and `operating_points`**: These are generated during `__init__` by calling the child movements' `generate_*` methods. Are stored as nested tuples to prevent modification after generation.
## CoreAirplaneMovement / AirplaneMovement Class (`_core.py`, `movements/airplane_movement.py`)

## AirplaneMovement Class (`movements/airplane_movement.py`)
`AirplaneMovement` extends `CoreAirplaneMovement`. All slots are defined on `CoreAirplaneMovement`; `AirplaneMovement` has empty `__slots__` and only narrows the `wing_movements` type to require `WingMovement` children.

### Attribute Classification

Expand All @@ -174,7 +182,9 @@ Store collections as tuples internally to prevent external mutation via `.append
| `all_periods` | Own periods + child `all_periods` | Tuple of unique non zero periods (cached) |
| `max_period` | Own periods + child `max_period` | Scalar float, longest period (cached) |

## WingMovement Class (`movements/wing_movement.py`)
## CoreWingMovement / WingMovement Class (`_core.py`, `movements/wing_movement.py`)

`WingMovement` extends `CoreWingMovement`. All slots are defined on `CoreWingMovement`; `WingMovement` has empty `__slots__` and only narrows the `wing_cross_section_movements` type to require `WingCrossSectionMovement` children.

### Attribute Classification

Expand All @@ -201,7 +211,9 @@ Store collections as tuples internally to prevent external mutation via `.append
| `all_periods` | Own periods + child `all_periods` | Tuple of unique non zero periods (cached) |
| `max_period` | Own periods + child `max_period` | Scalar float, longest period (cached) |

## WingCrossSectionMovement Class (`movements/wing_cross_section_movement.py`)
## CoreWingCrossSectionMovement / WingCrossSectionMovement Class (`_core.py`, `movements/wing_cross_section_movement.py`)

`WingCrossSectionMovement` extends `CoreWingCrossSectionMovement`. All slots are defined on `CoreWingCrossSectionMovement`; `WingCrossSectionMovement` has empty `__slots__`.

### Attribute Classification

Expand All @@ -226,7 +238,9 @@ Store collections as tuples internally to prevent external mutation via `.append
| `all_periods` | Period arrays | Tuple of unique non zero periods (cached) |
| `max_period` | Period arrays | Scalar float, longest period (cached) |

## OperatingPointMovement Class (`movements/operating_point_movement.py`)
## CoreOperatingPointMovement / OperatingPointMovement Class (`_core.py`, `movements/operating_point_movement.py`)

`OperatingPointMovement` extends `CoreOperatingPointMovement`. All slots are defined on `CoreOperatingPointMovement`; `OperatingPointMovement` has empty `__slots__`.

### Attribute Classification

Expand Down
Loading
Loading