Skip to main content
Sign in
Snippets Groups Projects
Commit bdc92c28 authored by Alfin Johny's avatar Alfin Johny
Browse files

Merge branch 'main' into 'fix/delete_artifacts'

# Conflicts:
#   mkdocs.yml
parents b331edc7 a40b2ced
No related branches found
No related tags found
No related merge requests found
Pipeline #1703614 waiting for manual action
Showing
with 797 additions and 5207 deletions
# Repository-specific code ownership # Repository-specific code ownership
* @kbistreck * @kristina.mazur
# File-specific code ownership # File-specific code ownership
.gitattributes @Florian.Schueltke .gitattributes @Florian.Schueltke
... ...
......
...@@ -358,7 +358,7 @@ After the initial loop, we expect a robuster behavior which we can use to calcul ...@@ -358,7 +358,7 @@ After the initial loop, we expect a robuster behavior which we can use to calcul
## Additional Output ## Additional Output
Beside the output written into the [aircraft XML](#acxml), **mission_analysis** generates a few more files you and even other tools can work with Beside the output written into the [aircraft XML](#acxml), **mission_analysis** generates a few more files you and even other tools can work with.
### Mission Data CSV {#csv_file} ### Mission Data CSV {#csv_file}
...@@ -396,6 +396,11 @@ Remember that nice graph from this tool's [introduction](index.md)? This is a si ...@@ -396,6 +396,11 @@ Remember that nice graph from this tool's [introduction](index.md)? This is a si
- Glidepath angle [deg] - Glidepath angle [deg]
- Incidence angle (stabilizer) [deg] - Incidence angle (stabilizer) [deg]
The [High Fidelity Method](methods.md/#highfi) will provide in addition:
- Latitude [deg]
- Longitude [deg]
Beside being a neat dataset to show-off, [Ecological Assessment](../ecological_assessment/index.md) can go through it to calculate the ecological impact of an aircraft flying the displayed mission. Beside being a neat dataset to show-off, [Ecological Assessment](../ecological_assessment/index.md) can go through it to calculate the ecological impact of an aircraft flying the displayed mission.
...@@ -517,7 +522,7 @@ In the `program_specific` node, you can specify if the specific air range (SAR) ...@@ -517,7 +522,7 @@ In the `program_specific` node, you can specify if the specific air range (SAR)
In `general` you can decide how the needed fuel is estimated and you can tell **mission_analysis** in which way it shall behave in different flight segments. In `general` you can decide how the needed fuel is estimated and you can tell **mission_analysis** in which way it shall behave in different flight segments.
The `mode` node lets you choose the methods that are applied. Using the keyword `low`/`mid` you will trigger the low-fidelity/mid-fidelity version of the [Standard Mission](methods.md) method. It also has three sub-methods to differentiate between `design_mission`, `study_mission` and `requirements_mission` which can be selected in the `mission_type` node. Please mind that the low-fidelity method only accepts the `design_mission`. After the first iteration, the [Weight and Balance tool](../weight_and_balance_analysis/index.md) delivers vectors containing center of gravity positions in addition to the aircraft mass (center of gravity shift due to defueling). To take that into account, you can activate `interpolate_polars`. For kerosene based propulsion, the effects are rather small, but once H2 is involved you should consider using it. Furthermore, the `rate_of_climb_switch` will only affect the [Climb to Ceiling](mission_steps.md/#climb_to_ceiling_subparagraph) step of the `requirements_mission`. With this option, **mission_analysis** calculates the optimum rate of climb towards service ceiling. The `mode` node lets you choose the methods that are applied. Using the keyword `low`/`mid`/`high` you will trigger the low-fidelity/mid-fidelity/high-fidelity version of the [Standard Mission](methods.md) method. It also has three sub-methods to differentiate between `design_mission`, `study_mission` and `requirements_mission` which can be selected in the `mission_type` node. Please mind that the low-fidelity method only accepts the `design_mission` and the high-fidelity method only except the study mission. After the first iteration, the [Weight and Balance tool](../weight_and_balance_analysis/index.md) delivers vectors containing center of gravity positions in addition to the aircraft mass (center of gravity shift due to defueling). To take that into account, you can activate `interpolate_polars`. For kerosene based propulsion, the effects are rather small, but once H2 is involved you should consider using it. Furthermore, the `rate_of_climb_switch` will only affect the [Climb to Ceiling](mission_steps.md/#climb_to_ceiling_subparagraph) step of the `requirements_mission`. With this option, **mission_analysis** calculates the optimum rate of climb towards service ceiling.
Finally, in `precision` you can set the parameters which will define the before mentioned increments of your mission profile. Finally, in `precision` you can set the parameters which will define the before mentioned increments of your mission profile.
...@@ -35,22 +35,20 @@ Once your mission is calculated, you can choose from a wide range of profile dat ...@@ -35,22 +35,20 @@ Once your mission is calculated, you can choose from a wide range of profile dat
| [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`design_mission` | running :white_check_mark:| | [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`design_mission` | running :white_check_mark:|
| [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`study_mission` | running :white_check_mark:| | [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`study_mission` | running :white_check_mark:|
| [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`requirements_mission` | running :white_check_mark:| | [3D Standard Mission (mid-fidelity)](methods.md/#midfi)|`requirements_mission` | running :white_check_mark:|
| [4D_trajectory (high-fidelity)](methods.md/#highfi) |None | under development :construction:| | [4D_trajectory (high-fidelity)](methods.md/#highfi) |`study_mission::orthodrome`| running :white_check_mark:|
By now, only a [standard (3D) mission method](methods.md/#midfi) is implemented. Its mid-fidelity version can trigger the three missions mentioned above while the low-fidelity sub-version is only used for the `design_mission`. The later is a Breguet-based estimation of the consumed mission fuel and it is triggered automatically if no initial values where given for the `design_mission`. A 4D trajectory mission is also planned, but it is still in the making. By now, there is a [standard (3D) mission method](methods.md/#midfi) implemented providing a low-, a mid- and a high-fidelity method. Its mid-fidelity version can trigger the three missions mentioned above while the high-fidelity sub-version is only used for the `study_mission`and the low-fidelity sub-version is only used for the `design_mission`. The later is a Breguet-based estimation of the consumed mission fuel and it is triggered automatically if no initial values where given for the `design_mission`.
<pre class='mermaid'> <pre class='mermaid'>
graph TD; graph TD;
A[mission_analysis]-->B[design_mission] A[mission_analysis]-->B[design_mission]
B-->E[low-fidelity] B-->E[low-fidelity]
B-->F[mid-fidelity] B-->F[mid-fidelity]
B-->G["(high-fidelity)"]
A-->C[study_mission] A-->C[study_mission]
C-->H[mid-fidelity] C-->H[mid-fidelity]
C-->I["(high-fidelity)"] C-->I[high-fidelity]
A-->D[requirements_mission] A-->D[requirements_mission]
D-->J[mid-fidelity] D-->J[mid-fidelity]
D-->K["(high-fidelity)"]
</pre> </pre>
... ...
......
# Mission Methods {#missions} # Mission Methods {#missions}
Depending on computing resources and needed level of detail, we have set up three different approaches to calculate a mission. Okay... it's only two by now, but the third will come for sure! Let's see, what we can find here. Depending on computing resources and needed level of detail, we have set up three different approaches to calculate a mission. Let's see, what we can find here.
## Breguet Estimation (Low Fidelity) {#lowfi} ## Breguet Estimation (Low Fidelity) {#lowfi}
...@@ -109,4 +109,41 @@ _FAR_FLAG_ consists of: ...@@ -109,4 +109,41 @@ _FAR_FLAG_ consists of:
## 4D Trajectory (High Fidelity) {#highfi} ## 4D Trajectory (High Fidelity) {#highfi}
Oops, that is not ready yet. An industrious UNICADO coder is probably working on that right now :unicorn: The high fidelity method works exactly as the [3D Standard Mission](#midfi) ...with one difference: it will additionally calculate the longitude and latitude of the aircraft along an Orthodrome in every mission step. For using this feature, you will need to provide information about the origin and destination airport to define the route you'd like to fly ✈️ How to do this can be checked in [Create Mission XML](../../sizing/create_mission_xml/airports.md). The coordinates will be calculated as follows:
First, the ratio $f$ of the traveled distance $r$ to the total mission distance $d$ is calculated:
$$
f = \frac{r}{d}
$$
This ratio is used to weight the origin ($origin$) and destination ($des$) coordinates. Using the auxiliary variables $A$ and $B$, the current position is determined in Cartesian coordinates $X$, $Y$ and $Z$:
<div class="mathjax-render">
$$
A = \frac{\sin((1 - f) \cdot d)}{\sin(d)}
$$
$$
B = \frac{\sin(f \cdot d)}{\sin(d)}
$$
$$
X = A \cdot \cos(\text{LAT}_{origin}) \cdot \cos(\text{LONG}_{origin}) + B \cdot \cos(\text{LAT}_{des}) \cdot \cos(\text{LONG}_{des})
$$
$$
Y = A \cdot \cos(\text{LAT}_{origin}) \cdot \sin(\text{LONG}_{origin}) + B \cdot \cos(\text{LAT}_{des}) \cdot \sin(\text{LONG}_{des})
$$
$$
Z = A \cdot \sin(\text{LAT}_{origin}) + B \cdot \sin(\text{LAT}_{des})
$$
</div>
Finally, a conversion back to geographic coordinates (latitude $LAT$ and longitude $LONG$) is performed:
$$
\text{LAT} = \text{atan2}\left(Z, \sqrt{X^2 + Y^2}\right)
$$
$$
\text{LONG} = \text{atan2}(Y, X)
$$
You'll find a plot of the resulting trajectory in the HTML report.
# The `Airfoils` library
**Description:**
This file is part of UNICADO. It implements the `Airfoils` class which manages airfoil data stored in files. The class provides functionality to load airfoil files from a specified directory, print the available airfoils, retrieve airfoil polygon data, and copy airfoil files to a target directory.
---
## Class: Airfoils
### Overview
- **Purpose:** Manages airfoil data by loading airfoil files from a directory and providing methods to interact with them.
- **Key Responsibilities:**
- Load airfoil data from a given directory.
- Maintain a collection (`available_airfoils`) that maps airfoil names to their file paths.
- Provide methods to print, retrieve, and copy airfoil data.
---
### Constructor
#### `Airfoils(const std::filesystem::path& path_to_airfoil_directory)`
- **Description:** Initializes the `Airfoils` object by loading airfoil files from the provided directory.
- **Parameters:**
- `path_to_airfoil_directory`: Filesystem path to the directory containing airfoil files.
- **Behavior:**
- Checks if the provided directory exists.
- If not, throws an error using `throwError` with a formatted message.
- Calls the private method `add_directory_airfoils(path_to_airfoil_directory)` to populate the `available_airfoils` map.
---
### Public Methods
#### `void print_available_airfoils()`
- **Description:** Prints the list of available airfoils with their names and file paths.
- **Behavior:**
- Iterates over the `available_airfoils` map and prints each entry using formatted output.
- Uses `std::cout` or a runtime logging stream (`myRuntimeInfo->out`) if available.
---
#### `geom2::Polygon_2 get_airfoil(const std::string& airfoil)`
- **Description:** Retrieves the polygon data of the specified airfoil.
- **Parameters:**
- `airfoil`: Name of the airfoil.
- **Return:**
- A `geom2::Polygon_2` object representing the airfoil's polygon data.
- **Behavior:**
- Searches for the airfoil in the `available_airfoils` map.
- If the airfoil is not found, throws an error.
- Otherwise, reads and returns the airfoil data using `geom2::io::read_airfoil`.
---
#### `void copy_available_airfoil(const std::string& airfoil, const std::filesystem::path& target_directory)`
- **Description:** Copies the specified airfoil file to a target directory.
- **Parameters:**
- `airfoil`: Name of the airfoil.
- `target_directory`: Filesystem path to the destination directory.
- **Behavior:**
- Checks if the target directory exists; if not, throws an error.
- Validates that the airfoil is available in the `available_airfoils` map; if not, throws an error.
- Compares the absolute paths of the source (airfoil file) and the target directory.
- If they are the same, logs that the copying is skipped.
- Attempts to copy the airfoil file using `std::filesystem::copy` with the `update_existing` option.
- Catches any exceptions during copying and rethrows them using `throwError`.
---
### Private Methods
#### `void add_directory_airfoils(const std::filesystem::path& path_to_airfoil_directory)`
- **Description:** Adds all airfoil files from the specified directory to the `available_airfoils` map.
- **Parameters:**
- `path_to_airfoil_directory`: Filesystem path to the directory containing airfoil files.
- **Behavior:**
- Verifies that the directory exists; if not, throws an error.
- Iterates over each entry in the directory using `std::filesystem::directory_iterator`.
- For each entry, calls the private method `add_airfoil(entry.path())`.
---
#### `void add_airfoil(const std::filesystem::path& airfoil_path)`
- **Description:** Adds a single airfoil file to the `available_airfoils` map.
- **Parameters:**
- `airfoil_path`: Filesystem path to the airfoil file.
- **Behavior:**
- Checks if the file exists; if not, throws an error.
- Verifies that the path is a regular file and has a `.dat` extension.
- Extracts the airfoil name (using the filename's stem) and inserts it into the `available_airfoils` map.
---
# How to use the Endnode
This section gives simple examples on how to use an endnode.
!!! note
The values and variables are for tutorial purpose only
## Creating and using a numeric endnode
```cpp
// Example: Create a numeric endnode for a value representing length in meters.
Endnode<double> lengthNode("/path/to/wanted/endnode", "Aircraft Length", 10.0, "m", 5.0, 20.0);
// Read from an XML node
lengthNode.read(xml_node);
// Update the value and then update the XML node
lengthNode.set_value(12.5);
lengthNode.update(xml_node);
```
## Creating and using a non-numeric endnode
```cpp
// Example: Create a string endnode for an aircraft model identifier.
Endnode<std::string> modelNode("/path/to/string/endnode", "Aircraft Model", "A320");
// Read and print the node
modelNode.read(xml_node);
modelNode.print();
```
## Creating and using a read-only Endnode
```cpp
// Example: Create a read-only endnode for a boolean
EndnodeReadOnly<bool> readOnlyNode("/path/to/boolean/endnode");
// Read the XML data
readOnlyNode.read(xml_node);
// Print both the parsed and original XML values
// This will have only effect if it's working on a numeric node and if the numeric node is a none SI (but valid)
readOnlyNode.print_xml();
```
# The `endnode` in UNICADO
The `endnode` is a main access point to the aircraft exchange file and lets you interface the different nodes (leafs) in an easy way. This class is build on top of the aixml class (no inheritance) which is used for raw access of xml file content.
## Overview
The `endnode` implements templated classes that define an endnode as a part of an XML document. An `endnode` is the final element in a node hierarchy, representing a leaf node that contains a value and in the case of numeric nodes, its associated unit, lower and upper boundaries.
The classes support:
- **Numeric types** (any arithmetic type except `bool`)
- **Boolean types** (`bool`)
- **String type** (`std::string`)
Each variant comes with its own constructors and methods to read from or update XML nodes. For numeric types, additional checks ensure that the value remains within specified boundaries and that units are valid according to SI or allowed custom conversions.
## Code Structure
### Concept: `is_numeric`
- **Purpose:** Defines a concept that accepts arithmetic types excluding `bool`.
- **Usage:** Used to restrict template instantiation for numeric operations.
```cpp
template <typename T>
concept is_numeric = (std::is_arithmetic<T>::value && (!std::is_same<T, bool>::value));
```
For `std::string` and `bool` the concept is_numeric is used with logic operators:
### For boolean:
- **Purpose:** Adapts is_numeric concept that accepts bool type.
- **Usage:** Used to restrict template instantiation for numeric operations.
```cpp
template <typename T>
!is_numeric<T> && std::is_same<T, bool>::value
```
### For strings:
- **Purpose:** Adapts is_numeric that accepts strings.
- **Usage:** Used to restrict template instantiation for std::string operations.
```cpp
template <typename T>
!is_numeric<T> && std::is_same<T, std::string>::value
```
### Class: EndnodeBase
**Template Parameter:**
- `T` - the type of value the endnode holds (arithmetic, bool, or std::string).
**Responsibilities:**
- Provides common functionality for reading XML node attributes.
- Initializes node paths and default values.
- Implements methods for:
- Reading node content from an XML node.
- Printing node values.
- Checking and converting units (for numeric types).
- Validating that a numeric value lies within defined boundaries.
**Constructors:**
- Overloaded to handle numeric types, booleans, and strings.
- Allows setting default values, units, and boundaries.
**Key Methods:**
- `read(const node& xml)`: Reads XML node data.
- `print()`: Prints the node's content.
- `check_boundaries()`: Ensures numeric values are within allowed limits.
- `check_unit()`: Validates unit correctness and handles custom-to-SI conversion if needed.
- `convert_items()`: Converts values to SI units when a custom unit is used.
**Internal Data Members:**
- `description_`: A string description of the node.
- `paths`: A vector of strings storing the XML path parts.
- `value_`, `lower_boundary_`, `upper_boundary_`: Numeric values (for numeric types).
- `unit_`: The unit associated with the numeric value.
- Several constant collections for SI units and unit conversion factors.
---
### Class: Endnode
**Inheritance:**
- Derives from `EndnodeBase<T>`.
**Purpose:**
- Provides a concrete implementation of an endnode with capabilities to read from and update an XML node.
**Additional Methods:**
- `update(node& xml)`: Updates the XML node with the current values. Different overloads exist for numeric, boolean, and string types.
- Overloaded arithmetic operators (`+=`, `-=`, `*=`, `/=`) for numeric types.
- Assignment operators to easily update values or boundaries.
- Setter methods for changing the node’s value, unit, and boundaries.
**Usage Scenario:**
- Use this class when you need to modify XML data – both reading from and writing to an XML document.
---
### Class: EndnodeReadOnly
**Inheritance:**
- Also derived from `EndnodeBase<T>`.
**Purpose:**
- Represents an XML endnode whose value is read-only after the initial XML read.
**Differences from Endnode:**
- Stores original XML values in separate members (`value_xml_`, `unit_xml_`, etc.).
- Provides methods to print or retrieve the raw, unparsed XML data.
**Key Methods:**
- `read(const node& xml)`: Reads the XML data and stores both parsed and original (XML) values.
- `print_xml()`: Prints the original XML values (format differs for numeric and non-numeric types).
- Getters to access the raw XML values directly.
The `EndnodeReadOnly` is mainly used for configuration files since those data should not be altered by the module. For classic access and updating, use the Endnode class.
!!! danger "Important"
None SI units will be converted automatically to SI units by the given table in the endnode.h file when reading. Have a look at valid units in [valid units](valid_units.md)
# Allowed SI Units and how it is converted
### SI Units Table
| Unit | Description |
|--------|-------------------------------|
| m | meter |
| m^2 | squaremeter |
| m^3 | cubicmeter |
| m/s | meter per second |
| rad | radian |
| 1 | no unit |
| Pa | pascal |
| kg | kilogram |
| kg/s | kilogram per second |
| kg/Ns | kilogram per newton second |
| s | second |
| J | Joule |
| J/kg | Joule per kilogram |
| J/m^3 | Joule per cubic meter |
| W | Watt |
| V | volt |
| A | ampere |
| N | newton |
| N/m^2 | newton per square meter |
| kg/m^2 | kilogram per square meter |
| kg/m^3 | kilogram per cubic meter |
| kgm^2 | kilogram square meter |
| K | Kelvin |
| EUR | Euro |
| US | Dollar |
### Custom to SI Units Conversion Table
| Custom Unit | SI Unit |
|--------------|---------|
| deg | rad |
| ft | m |
| FL | m |
| NM | m |
| lbs | kg |
| lbs/min | kg/s |
| EUR | EUR |
| US | US |
| g | 1 |
| dBA | Pa |
| EPNdB | Pa |
| Sone | Pa |
| h | s |
| min | s |
| a | s |
| ft/min | m/s |
| kts | m/s |
| KCAS | m/s |
| l | m^3 |
| Celsius | K |
| micro meter | m |
| kg/h | kg/s |
# The aixml library
This library purpose is to interact with xml files, especially for accessing xml files like the aircraft exchange file and the module configuration files.
## Aixml
This library contains methods for "raw" accessing of xml files based on the tinyxml library
## Endnode
This library contains template classes especially for the usage in UNICADO and should be used in each C++ module for easy accessing nodes.
...@@ -50,7 +50,7 @@ The **airfoils** libary provides a database for different airfoils. ...@@ -50,7 +50,7 @@ The **airfoils** libary provides a database for different airfoils.
|Module Version|Language|License|Documentation|Dependencies| |Module Version|Language|License|Documentation|Dependencies|
|:---:|:---:|:---:|---|---| |:---:|:---:|:---:|---|---|
|0.5.0|:simple-cplusplus: |GPLv3|-|-| |0.5.0|:simple-cplusplus: |GPLv3|[Link](airfoils/index.md)|-|
--- ---
...@@ -62,7 +62,7 @@ It uses a simple XML library, namely *tinyxml*, to read and parse the XML files. ...@@ -62,7 +62,7 @@ It uses a simple XML library, namely *tinyxml*, to read and parse the XML files.
|Module Version|Language|License|Documentation|Dependencies| |Module Version|Language|License|Documentation|Dependencies|
|:---:|:---:|:---:|---|---| |:---:|:---:|:---:|---|---|
|0.5.0|:simple-cplusplus: |GPLv3|-|-| |0.5.0|:simple-cplusplus: |GPLv3|[Link](aixml/index.md)|[tinyxml](https://github.com/leethomason/tinyxml2)|
--- ---
...@@ -105,7 +105,7 @@ The engine decks can originate from different softwaretools as long as they prov ...@@ -105,7 +105,7 @@ The engine decks can originate from different softwaretools as long as they prov
## extern ## extern
UNICADO currently uses two external libaries as submodules: UNICADO currently uses two external libaries as submodules:
- `doxygen-awesome-css` for documentation formation [(see here)](https://github.com/jothepro/doxygen-awesome-css.git) - `doxygen-awesome-css` for documentation formation (LEGACY - will be removed) [(see here)](https://github.com/jothepro/doxygen-awesome-css.git)
- `pybind11` to use C++ libraries in the python tools [(see here)](https://github.com/pybind/pybind11.git) - `pybind11` to use C++ libraries in the python tools [(see here)](https://github.com/pybind/pybind11.git)
--- ---
...@@ -135,6 +135,28 @@ The library gives a template how modules should be structured and gives helpers ...@@ -135,6 +135,28 @@ The library gives a template how modules should be structured and gives helpers
--- ---
## pyavlpackage
![Icon](site:assets/images/documentation/pymodulepackage.svg){.overview-img align=left}
This library provides the core functionality to work with Athena Vortex Lattice (AVL) from M. Drela which is released under GPL.
{.overview-item}
|Module Version|Language|License|Documentation|Dependencies|
|:---:|:---:|:---:|---|---|
|0.5.0|:simple-cplusplus: |GPLv3|-|[AVL](https://web.mit.edu/drela/Public/web/avl/)|
---
## pyavlunicadopackage
![Icon](site:assets/images/documentation/pymodulepackage.svg){.overview-img align=left}
This library provides the core functionality to work with Athena Vortex Lattice (AVL) from M. Drela which is released under GPL using the pyavlpackage and the unicado geometry based on aircraftgeoemtry2.
{.overview-item}
|Module Version|Language|License|Documentation|Dependencies|
|:---:|:---:|:---:|---|---|
|0.5.0|:simple-cplusplus: |GPLv3|-|[AVL](https://web.mit.edu/drela/Public/web/avl/)|
---
## pymodulepackage ## pymodulepackage
![Icon](site:assets/images/documentation/pymodulepackage.svg){.overview-img align=left} ![Icon](site:assets/images/documentation/pymodulepackage.svg){.overview-img align=left}
This library provides standardized UNICADO data preprocessing, run, and postprocessing functions for Python modules. This library provides standardized UNICADO data preprocessing, run, and postprocessing functions for Python modules.
... ...
......
# Airports
The module provides the possibility to define an origin and destination airport of a study mission. If you use this, the module will read the location of the airports from a database, calculate the shortest distance (Orthodrome) between them and write those information to the [output xml file](getting_started.md#output). This is a nice feature, as it allows [Mission Analysis](../../analysis/mission_analysis/index.md) to calculate the location of the aircraft in every mission step for a designated route. While it is not a necessary information in the aircraft design process, for a detailed ecological assessment it is essential to know where exactly the aircraft operates.
To use this feature, you need to enable the switch `airports/enable` within the study_mission part of the [Configuration File](getting_started.md#config_file). Then you can define the airports via their ICAO or IATA code. In total, there are more than 5000 airports available in the database. If you're interested to see the list or would like to add your own airport, have a look into the airports.csv located in the `create_mission_xml_lib`-folder next to the executable. The list is based on data published [here](https://github.com/dedolist/open-data/blob/master/data/locations/airports/data.csv) under the [Open Data Commons Public Domain Dedication and License (PDDL) v1.0](https://opendatacommons.org/licenses/pddl/1-0/index.html) and you're free to extend or change this data.
If you provide two existing airport codes, the module will calculate the Orthodrome between the airports via the Haversine formula [@Ple24]:
<div class="mathjax-render">
$$
\chi = \sin^2\left(\frac{\Delta \text{LAT}}{2}\right) + \cos(\text{LAT}_A) \cdot \cos(\text{LAT}_B) \cdot \sin^2\left(\frac{\Delta \text{LONG}}{2}\right)
$$
$$
D = (R + H) \cdot 2 \cdot \text{arctan2}\left( \sqrt{\chi}, \sqrt{1 - \chi} \right)
$$
</div>
where:
- $D$: Distance between airports [m]
- $R$: Radius of the Earth [m]
- $H$: Initial flight altitude [m]
- $\text{LAT}$: Latitude in radians
- $\Delta \text{LAT} = \text{LAT}_A - \text{LAT}_B$
- $\text{LONG}$: Longitude in radians
- $\Delta \text{LONG} = \text{LONG}_A - \text{LONG}_B$
- $A$: Departure airport
- $B$: Destination airport
\ No newline at end of file
...@@ -77,8 +77,10 @@ program_settings ...@@ -77,8 +77,10 @@ program_settings
│ ├── alternate_distance │ ├── alternate_distance
│ ├── engine_warmup_time │ ├── engine_warmup_time
│ ├── taxiing_procedure │ ├── taxiing_procedure
│ ├── origin_airport │ ├── airports
│ ├── destination_airport │ │ ├── enable
│ │ ├── origin_airport
│ │ ├── destination_airport
├── study_mission ├── study_mission
│ ├── copy_mach_number │ ├── copy_mach_number
│ ├── copy_initial_cruise_altitude │ ├── copy_initial_cruise_altitude
...@@ -96,17 +98,19 @@ program_settings ...@@ -96,17 +98,19 @@ program_settings
│ ├── alternate_distance │ ├── alternate_distance
│ ├── engine_warmup_time │ ├── engine_warmup_time
│ ├── taxiing_procedure │ ├── taxiing_procedure
│ ├── origin_airport │ ├── airports
│ ├── destination_airport │ │ ├── enable
│ │ ├── origin_airport
│ │ ├── destination_airport
``` ```
In this config, you can decide what takeoff and approach procedure you want to use and how the aircraft shall operate at the airport and while cruising. In the `mission_selector`, you can choose if the `mission file` shall be generated for a `design_mission`, `study_mission` or `requirements_mission`. For more details, check the descriptions in `create_mission_xml_conf.xml`. In this config, you can decide what takeoff and approach procedure you want to use and how the aircraft shall operate at the airport and while cruising. In the `mission_selector`, you can choose if the `mission file` shall be generated for a `design_mission`, `study_mission` or `requirements_mission`. You can also define the origin and destination airport in case you'd like get detailed trajectory information of [Mission Analysis](../../analysis/mission_analysis/index.md). For more details on possible settings, check the descriptions in `create_mission_xml_conf.xml`.
!!!node !!!node
`maximum_operating_mach_number` and the nodes starting with `auto` will lead to **mission_analysis** ignoring user input from the aircraft XML. In those cases, the tool will try to find an own optimum. `maximum_operating_mach_number` and the nodes starting with `auto` will lead to **mission_analysis** ignoring user input from the aircraft XML. In those cases, the tool will try to find an own optimum.
## Output ## Output {#output}
Like we have already discussed, the output of **create_mission_xml** is the mission_file which generally looks like this: Like we have already discussed, the output of **create_mission_xml** is the mission_file which generally looks like this:
...@@ -175,6 +179,42 @@ Like we have already discussed, the output of **create_mission_xml** is the miss ...@@ -175,6 +179,42 @@ Like we have already discussed, the output of **create_mission_xml** is the miss
<taxiing_procedure description="Taxiing procedure for start and landing."> <taxiing_procedure description="Taxiing procedure for start and landing.">
<value>propulsion_taxiing</value> <value>propulsion_taxiing</value>
</taxiing_procedure> </taxiing_procedure>
<airports>
<origin>
<code description="ICAO or IATA code of origin airport">
<value>HAM</value>
</code>
<longitude description="Longitude of origin airport">
<value>0.1743274648</value>
<unit>rad</unit>
<lower_boundary>-3.15</lower_boundary>
<upper_boundary>3.15</upper_boundary>
</longitude>
<latitude description="Latitude of origin airport">
<value>0.9360268661</value>
<unit>rad</unit>
<lower_boundary>-1.58</lower_boundary>
<upper_boundary>1.58</upper_boundary>
</latitude>
</origin>
<destination>
<code description="ICAO or IATA code of origin airport">
<value>FRA</value>
</code>
<longitude description="Longitude of destination airport">
<value>0.1495826754</value>
<unit>rad</unit>
<lower_boundary>-3.15</lower_boundary>
<upper_boundary>3.15</upper_boundary>
</longitude>
<latitude description="Latitude of destination airport">
<value>0.8732459244</value>
<unit>rad</unit>
<lower_boundary>-1.58</lower_boundary>
<upper_boundary>1.58</upper_boundary>
</latitude>
</destination>
</airports>
<departure description="Departure procedure; Additional nodes neded for mode... <departure description="Departure procedure; Additional nodes neded for mode...
Takeoff: No additional nodes. Takeoff: No additional nodes.
climb: End Point Altitude [m] (double). climb: End Point Altitude [m] (double).
...@@ -273,16 +313,19 @@ Like we have already discussed, the output of **create_mission_xml** is the miss ...@@ -273,16 +313,19 @@ Like we have already discussed, the output of **create_mission_xml** is the miss
</mission> </mission>
``` ```
!!!node !!!note
Bleed air and power offtakes are not displayed here, but every step will include these, too. Offtakes are written and explained by [Systems Design](../systems_design/index.md). Bleed air and power offtakes are not displayed here, but every step will include these, too. Offtakes are written and explained by [Systems Design](../systems_design/index.md).
!!!note
The airport information will only be written for the study mission and only if you've enabled the aircraft switch in the configuration file!
While the most parameters like `range` and `alternate_distance` are copied directly from [Aircraft Exchange File](#acxml) and [Configuration File](#config_file), the `payload` is derived from the given number of passengers, their luggage and the mass per passenger. Each step (`departure_step`, `cruise_step` or `approach_step`) contains the nodes `configuration`, `mode`, `derate` and `rating`. The `configuration` node will tell [Mission Analysis](../../analysis/mission_analysis/index.md) which polar (generated by [Aerodynamic Assessment](../../analysis/aerodynamic_analysis/index.md)) shall be used. `derate` and `rating` characterize the engine operations and `mode` specifies what shall happen during the segment between two steps (more infos about `modes`, [click here](../../analysis/mission_analysis/mission_steps.md/#step_modes)). Furthermore, `cruise_steps` always include `flight_management_system` and `auto_select_optimum_flight_level` nodes. While the most parameters like `terminal_operation_time` and `alternate_distance` are copied directly from [Aircraft Exchange File](#acxml) and [Configuration File](#config_file), the `payload` is derived from the given number of passengers, their luggage and the mass per passenger. The `range`is either copied from the [Aircraft Exchange File](#acxml), or calculated as described in [Airports](airports.md). Each step (`departure_step`, `cruise_step` or `approach_step`) contains the nodes `configuration`, `mode`, `derate` and `rating`. The `configuration` node will tell [Mission Analysis](../../analysis/mission_analysis/index.md) which polar (generated by [Aerodynamic Assessment](../../analysis/aerodynamic_analysis/index.md)) shall be used. `derate` and `rating` characterize the engine operations and `mode` specifies what shall happen during the segment between two steps (more infos about `modes`, [click here](../../analysis/mission_analysis/mission_steps.md/#step_modes)). Furthermore, `cruise_steps` always include `flight_management_system` and `auto_select_optimum_flight_level` nodes.
Other entries within these steps can differ depending on which `mode` is used. What input nodes are needed can be found in the descriptions of `departure`, `cruise` and `approach`. As a rule of thumb, the following input nodes can usually be expected: Other entries within these steps can differ depending on which `mode` is used. What input nodes are needed can be found in the descriptions of `departure`, `cruise` and `approach`. As a rule of thumb, the following input nodes can usually be expected:
- `mode` that changes speed: Target speed (Mach or CAS), rate of climb or target speed - `mode` that changes speed: Target speed (Mach or CAS), rate of climb or target speed
- `mode` that changes altitude: Target altitude, rate of climb or target speed - `mode` that changes altitude: Target altitude, rate of climb or target speed
!!!node !!!note
For an `approach_step`, the rate of climb cannot be determined up-front, because the glide path angle must be kept constant at $3°$ due to regulatory requirements. Therefore, the rate of climb will be derived from the `glide_path` node by [Mission Analysis](../../analysis/mission_analysis/index.md). For an `approach_step`, the rate of climb cannot be determined up-front, because the glide path angle must be kept constant at $3°$ due to regulatory requirements. Therefore, the rate of climb will be derived from the `glide_path` node by [Mission Analysis](../../analysis/mission_analysis/index.md).
...@@ -36,7 +36,7 @@ If the limits are exceeded which are defined in the aircraft exchange file in th ...@@ -36,7 +36,7 @@ If the limits are exceeded which are defined in the aircraft exchange file in th
After computing the aspect ratio, the taper ratio can be user defined or determined by a method from Howe. Howe uses the aspect ration and the quarter chord sweep to compute the taper ratio. After computing the aspect ratio, the taper ratio can be user defined or determined by a method from Howe. Howe uses the aspect ration and the quarter chord sweep to compute the taper ratio.
#### Step 5: Dihedral computation #### Step 5: Dihedral computation
The next step computes the dihedral which can be set by user or will be computed based on limits defined by Howe or Raymer. Since both, Howe and Raymer just give limitations, the dihedral as a mean value between the minimum and maximum values. Howe differentiates between sweept and unsweept while Raymer includes the mach state of the aircraft. The next step computes the dihedral which can be set by user or will be computed based on limits defined by Raymer. Raymer only defines limitations, so the dihedral is calculated as a mean value between the minimum and maximum values. Raymer differentiates between swept and unswept, including the mach state (transonic / supersonic) of the aircraft.
#### Step 6: Calculate geometry #### Step 6: Calculate geometry
Based on the computed data and the information from the aircraft exchange file, it will be determined if the wing geometry will be calculated with a kink or not. The kink is enabled when the _landing gear_ is _wing mounted_ and the wing is mounted _low_. Otherwise it uses an unkinked geometry. Based on the computed data and the information from the aircraft exchange file, it will be determined if the wing geometry will be calculated with a kink or not. The kink is enabled when the _landing gear_ is _wing mounted_ and the wing is mounted _low_. Otherwise it uses an unkinked geometry.
...@@ -49,6 +49,6 @@ The unkinked geometry calculation is straight forward, however the kinked versio ...@@ -49,6 +49,6 @@ The unkinked geometry calculation is straight forward, however the kinked versio
The spar positions and control devices can be set by user. For control devices, a basic set of control devices will be set consisting of an aileron, and a number of high lift devices and spoilers for air and ground. The spar positions and control devices can be set by user. For control devices, a basic set of control devices will be set consisting of an aileron, and a number of high lift devices and spoilers for air and ground.
#### Step 8: Mass calculation #### Step 8: Mass calculation
With the wing finished, the mass of the wing will be computed by two different methods, one is the Flight Optimization System (Flops) method and the other is a Method from Chiozzotto (PhD Thesis). Both methods allow changes in material while Flops uses a factor from 0 to 1 to vary the ratio between aluminim and composite materials while Chiozzotto sets two materials - _AL_ for aluminium and _CFRP_ for carbon fibre reinforced plastics. With the wing finished, the mass of the wing will be computed by two different methods, one is the Flight Optimization System (Flops) method and the other is a Method from Chiozzotto (PhD Thesis). Both methods allow changes in material while Flops uses a factor from 0 to 1 to vary the ratio between aluminum and composite materials while Chiozzotto sets two materials - _AL_ for aluminum and _CFRP_ for carbon fibre reinforced plastics.
For the determination of the center of gravity and the position, again empirical methods from Howe are used. For the determination of the center of gravity and the position, again empirical methods from Howe are used.
...@@ -18,8 +18,8 @@ According to the workflow, the tool requires a valid _Aircraft Exchange File_ wi ...@@ -18,8 +18,8 @@ According to the workflow, the tool requires a valid _Aircraft Exchange File_ wi
Here is a quick overview of what the tool is currently capable of including a preview which is planned: Here is a quick overview of what the tool is currently capable of including a preview which is planned:
| Configuration | Wing Type | Methods | Status | | Configuration | Wing Type | Methods | Status |
|-------------------|------------|---------|:---------------------------------:| |-------------------|------------|---------|:---------------------------------------:|
| tube-and-wing | Cantilever | TUB | running :white_check_mark: | | tube-and-wing | Cantilever | TUB | running :octicons-feed-issue-closed-16: |
| blended-wing-body | ... | ... | under development :construction: | | blended-wing-body | ... | ... | under development :construction: |
## A User's Guide to Wing Design ## A User's Guide to Wing Design
... ...
......
...@@ -64,11 +64,11 @@ The class provides several public methods for various operations: ...@@ -64,11 +64,11 @@ The class provides several public methods for various operations:
- `showRuntime()` - Prints runtime information, e.g. program name, enabled flags etc. - `showRuntime()` - Prints runtime information, e.g. program name, enabled flags etc.
- `showDirectories()` - shows stored directories in directories_ map. - `showDirectories()` - shows stored directories in directories_ map.
- `getIODir()`, `getGeometryDir()` and other similar functions which return the path w/o ending seperator - `getIODir()`, `getGeometryDir()` and other similar functions which return the path w/o ending separator
- `createGeometryDir()`, `createAirfoilDataDir()` and other similar functions which create the directory if not existent - `createGeometryDir()`, `createAirfoilDataDir()` and other similar functions which create the directory if not existent
- `checkFileExistence()` - checks if a file exists by specific argument - `checkFileExistence()` - checks if a file exists by specific argument
- `create_common_directories` - creates standard output directories if not existent - `create_common_directories` - creates standard output directories if not existent
- `addDir()` - adds a directory to the directories_ map and creates it if not existent. The key will be specified in upper case letters - `add_directory()` - adds a directory to the directories_ map and creates it if not existent. The key will be specified in upper case letters
- `reopenAcXML()` - reopens the aircraftXML - please make sure to (save and) close the acxml before - `reopenAcXML()` - reopens the aircraftXML - please make sure to (save and) close the acxml before
- `saveAcXML()` - saves the current acxml node from the runtimeIO instantiation - `saveAcXML()` - saves the current acxml node from the runtimeIO instantiation
- `closeAcXML()` - closes the current acxml node from the runtimeIO instantiation - `closeAcXML()` - closes the current acxml node from the runtimeIO instantiation
...@@ -232,13 +232,14 @@ modeSelection = Modeselector("mode_2") ...@@ -232,13 +232,14 @@ modeSelection = Modeselector("mode_2")
modi selectedMode = modeSelection.get(); // selectedMode = 2 modi selectedMode = modeSelection.get(); // selectedMode = 2
``` ```
## Intermediate level ## Intermediate level (Virtual) and low level
### Strategy and StrategySelector The intermediate level is at the current state a virtual level which routes you to your desired strategy (called so, since we use the strategy pattern to define it). However, the strategy itself specifies a new method which can be integrated. The intermediate level itself just describes the route to it. So you can think of it as a tree.
The low level actual implements the new strategy (or method, however you want to call it for yourself). Since intermediate level and low level are somewhat connected, we will show what you need to create a new _strategy_ and how you can run such a strategy from the top level using the so called `StrategySelector`.
The intermediate level, which describes the routing from top to low level, uses the so called **Strategy Design Pattern**. This pattern allows to set a specific strategy at first place and let it run through Selector, in this case the `StrategySelector` class (`strategySelector.h`, header-only). ### Strategy
Each strategy, such as the low-fidelity strategy or high-fidelity strategy, is implemented as a class that inherits from the base class `Strategy`. The `Strategy` base class defines the following pure virtual methods: Each strategy, such as e.g. a low-fidelity strategy or a high-fidelity strategy, is implemented as a class that inherits from the base class `Strategy`. The `Strategy` base class defines the following pure virtual methods which is defined inside the `strategySelector.h` header:
- `initialize()` - `initialize()`
- `run()` - `run()`
...@@ -259,48 +260,11 @@ public: ...@@ -259,48 +260,11 @@ public:
virtual void save() = 0; virtual void save() = 0;
virtual ~Strategy() {}; virtual ~Strategy() {};
}; };
```
The `StrategySelector` class serves as a selector for strategies. It manages a dynamic allocation of a strategy using a `std::unique_ptr`. The class provides member functions to set the strategy, initialize the strategy with a given configuration class, run, update, report and save the strategy. Methods for this are:
- `setStrategy()`
- `initializeStrategy()`
- `runStrategy()`
- `updateStrategy()`
- `reportStrategy()`
- `saveStrategy()`
The code for the class: The Strategy class is given as a basic template which should be used. However, an adaption of Input/Output types might be necessary but must be clearly stated.
```c++ To use the class, a minimal example can be seen below:
class StrategySelector
{
public:
void setStrategy(std::unique_ptr<Strategy> strategy) {
strategy_ = std::move(strategy);
}
void initializeStrategy() {
strategy_->initialize();
}
void runStrategy() {
strategy_->run();
}
void updateStrategy() {
strategy_->update();
}
void reportStrategy() {
strategy_->report();
}
void saveStrategy() {
strategy_->save();
}
private:
std::unique_ptr<Strategy<> strategy_;
};
```
The Strategy and StrategySelector classes are given as basic templates which should be used. However, an adaption of Input/Output types might be necessary but must be clearly stated.
To use these classes, a minimal example can be seen below:
```c++ ```c++
#include "strategySelector.h" #include "strategySelector.h"
...@@ -331,81 +295,56 @@ public: ...@@ -331,81 +295,56 @@ public:
const std::shared_ptr<RuntimeIO>& rtIO; const std::shared_ptr<RuntimeIO>& rtIO;
}; };
```
int main(void) { Here, we have two strategies - a `low` strategy and a `high` strategy which inherit the base class `Strategy` and implement the necessary pure virtual methods. So we've now the low level and the top level. How to get to one of the strategies right now? Here the `StrategySelector` class will be introduced:
StrategySelector strategyholder;
const std::shared_ptr<RuntimeIO> rtIO = std::make_shared<RuntimeIO>(.....);
strategyholder.setStrategy(std::make_unique<Low>(rtIO));
strategyholder.runStrategy(); The `StrategySelector` class serves as a selector for strategies. It manages a dynamic allocation of a strategy using a `std::unique_ptr`. The class provides two major functions which will do the job you want to get to the strategy you want:
strategyholder.setStrategy(std::make_unique<High>()); - `registerStrategy<strategy>(std::vector<std::string>)` - registers the `strategy` under a specific path defined by a vector of strings
strategyholder.runStrategy(); - `setStrategy(std::vector<std::string> , std::shared_ptr<RuntimeIO>)` - sets a registered strategy based on a vector of strings and an instance of a smart pointer of RuntimeIO.
strategyholder.saveStrategy();
return 0;
}
```
Output generated: The first method allows you to set up the method you want and the second allows you to set the method you want to use. So we go a step further and setup the example for the `Low` and `High` strategy:
```bash ```c++
$ ./a.exe int main(void) {
run low
run high
save high
```
With `setStrategy`, a strategy will be selected and the RuntimeIO shared smart pointer is handed over to the strategy as a reference. All other calls via `strategyholder` will call methods from the *Low class strategy*. However, the strategy is changed after the first call of `runStrategy`, so below that second `setStrategy` statement, Methods within *High Strategy* are called.
The strategy is selected via a routing table system. To improve readability for the routing table, the file `strategySelector.h` provides two overlays: // Define the strategyselector as strategy
StrategySelector strategy;
- `strategyptr` - `std::unique_ptr<Strategy>(const std::shared_ptr<RuntimeIO>&` // Get an RuntimeIO instance as a smart shared pointer
- `strategyaccess` - `std::function<strategyptr>` const std::shared_ptr<RuntimeIO> rtIO = std::make_shared<RuntimeIO>(.....);
A routing table is defined in a method inside the derived module class. As an example for empennage_design: // Register your strategy by defining a path to the associated
strategy.registerStrategy<Low>({"low"})
strategy.registerStrategy<High>({"high"})
```c++ // Sets the strategy - here hardcoded selection of "high"
strategyaccess EmpennageDesign::routing_(const std::vector<std::string>& route) { strategy.setStrategy({"high"}, rtIO);
/* Routing table */
std::map<std::string,std::map<std::string,std::map<std::string,strategyaccess>>> table = {
{"TAW",
std::map<std::string,std::map<std::string,strategyaccess>>{
{"CONVENTIONAL",
std::map<std::string,strategyaccess>{
{"LOW",[](const std::shared_ptr<RuntimeIO>& arg) {return std::make_unique<LowConventionalTaw>(arg);}},
}
},
}
},
{"BWB",
std::map<std::string,std::map<std::string,strategyaccess>>{
{"FINS",
std::map<std::string,strategyaccess>{
{"LOW",[](const std::shared_ptr<RuntimeIO>& arg) {return std::make_unique<LowFinsBwb>(arg);}},
{"MID",[](const std::shared_ptr<RuntimeIO>& arg) {return std::make_unique<MidFinsBwb>(arg);}}
}
}
}
}
};
return table[route.at(0)][route.at(1)][route.at(2)]; // Afterwards you can run also any of the implemented pure virtual methods which are defined in the currently set strategy like
strategy.runStrategy()
return 0;
} }
``` ```
`[](const std::shared_ptr<RuntimeIO>& arg) {return std::make_unique<LowFinsBwb>(arg)` is a lambda function which handle is returned from the routing_ table. With `setStrategy`, a strategy will be selected and the RuntimeIO shared smart pointer is handed over to the strategy as a reference.
Inside the module constructor, the strategy is set by Inside the module constructor, the strategy is set by
```c++ ```c++
EmpennageDesign::EmpennageDesing(...) : Module(...) { EmpennageDesign::EmpennageDesign(...) : Module(...) {
// read route from configuration file and store into std::vector<std::string> route_; name of vector might differ if there are more than one strategy to call // read route from configuration file and store into std::vector<std::string> route; name of vector might differ if there are more than one strategy to call
strategy_.setStrategy(routing_(route)(rtIO_)); std::vector<std::string> route = ... // Directly set up route - might not be necessary
...
// Strategy registration
strategy.registerStrategy<...>(...);
...
strategy.setStrategy(route, rtIO_);
...} ...}
``` ```
The parameter for strategy set is called by invoking `routing_(...)` with the `route` vector which returns the handle for the selected strategy from the routing table according to the route. With `...(rtIO_)`, the returned handle is called with the `RuntimeIO` object `rtIO_` as an argument. The result is than handed over to the setStrategy method. The routing is done via a vector of `std::string` which can be anything (like keywords defining the aircraft type, the fidelity level of your method/strategy, the aircraft configuration or anything else). These strings build up the tree for the selection. If there is a registered strategy under such a vector string, you can access the strategy via setStrategy. Otherwise you get an error that the desired method is not existing.
If you'd like to add your own module, you can choose the structure of your routing table freely. Existing UNICADO modules use for example following layers: If you'd like to add your own module, you can choose the structure of your routing table freely. Existing UNICADO modules use for example following layers:
...@@ -415,9 +354,8 @@ If you'd like to add your own module, you can choose the structure of your routi ...@@ -415,9 +354,8 @@ If you'd like to add your own module, you can choose the structure of your routi
- method name - method name
- ... - ...
### The Fidelities {#fidelities} ??? info "Fidelities"
The modularization was introduced for different fidelities. However this might not fit for all modules. If you have methods/strategies for certain fidelities, please stick to our fidelity list:
The fidelity of each methods can be classified as low, mid, higher, high and own as follows:
- `low` - empirical methods - `low` - empirical methods
- `mid` - semi-empirical methods - `mid` - semi-empirical methods
...@@ -425,20 +363,20 @@ The fidelity of each methods can be classified as low, mid, higher, high and own ...@@ -425,20 +363,20 @@ The fidelity of each methods can be classified as low, mid, higher, high and own
- `high` - numerical methods - `high` - numerical methods
- `own` - own method (experimental) - `own` - own method (experimental)
## Low level ### The low level
This is a short recap of the former description. Make sure to have the strategy pure virtuals with you.
!!!note ??? note
The low level implementations members should be public only. This has different reasons: The low level implementations members should be public only. This has different reasons:
1. There is no method next to the current 1. There is no method next to the current
2. To keep the overhead of the class as small as possible (no setter/getter methods which must be provided for private members) 2. To keep the overhead of the class as small as possible (no setter/getter methods which must be provided for private members)
3. Due to pep8 conventions (python normally has no private / protected members) 3. Due to pep8 conventions (python normally has no private / protected members) - yes naming convention is pep8 (even if it is not handled everywhere correctly, since it started somewhere else)
4. isocpp: all private or all public - no mixture 4. isocpp: all private or all public - no mixture
On the low level, the implementation of the algorithms is focused. Here you can structure your implementations according to the five base methods: On the low level, the implementation of the algorithms is focused. Here you can structure your implementations according to the five base methods:
- `initialize` - initialize your module to your needs and your output data by reading and preparing the data. - `initialize` - initialize your module to your needs and your output data by reading and preparing the data.
- `run` - Here happens your wizardy stuff, sometimes muggle-like, sometime not 🧙. - `run` - Here happens your wizardly stuff, sometimes muggle-like, sometime not 🧙.
- `update` - lets you call the update methods within the IOData class - `update` - lets you call the update methods within the IOData class
- `save` - if you opened any specific document during your module execution, you can save the data within this method and close the data. - `save` - if you opened any specific document during your module execution, you can save the data within this method and close the data.
...@@ -490,6 +428,9 @@ public: ...@@ -490,6 +428,9 @@ public:
/* LOW FIDELITY CONFIGS END */ /* LOW FIDELITY CONFIGS END */
``` ```
To see an example for this, have a look at `wing_design` module or `empennage_design` module.
### Report ### Report
For report generation, a dedicated Report class (`report.h`) can be used. It offers access to HTML and Tex streams. Public methods are the following: For report generation, a dedicated Report class (`report.h`) can be used. It offers access to HTML and Tex streams. Public methods are the following:
...@@ -504,7 +445,7 @@ For report generation, a dedicated Report class (`report.h`) can be used. It off ...@@ -504,7 +445,7 @@ For report generation, a dedicated Report class (`report.h`) can be used. It off
- `reportName` - returns standard name of the report - `reportName` - returns standard name of the report
- Legacy Method `addPlot` - adds a plot to the plots map by the name of the plot in case `plot.h` is used - Legacy Method `addPlot` - adds a plot to the plots map by the name of the plot in case `plot.h` is used
All methods for a report must be on the low level for a specific fidelity in a seperate `...Report.cpp` File. Report is an object of the main specific fidelity class and NOT an inherited class. Within your html report, can add generated plots by using the `image` function of `html.h` All methods for a report must be on the low level for a specific fidelity in a separate `...Report.cpp` File. Report is an object of the main specific fidelity class and NOT an inherited class. Within your html report, can add generated plots by using the `image` function of `html.h`
### Plot ### Plot
!!!attention !!!attention
...@@ -523,11 +464,13 @@ The Plot class (`plot.h`) is a basic frame for SVG Plot generation. There are mu ...@@ -523,11 +464,13 @@ The Plot class (`plot.h`) is a basic frame for SVG Plot generation. There are mu
- `generatePlotScript` - Generates plot script which is in the script stringstream - `generatePlotScript` - Generates plot script which is in the script stringstream
- `generateSvg` - generates .svg based on the plotname in the given directory based on reference of a vector of unique pointers which stores svgObjects. - `generateSvg` - generates .svg based on the plotname in the given directory based on reference of a vector of unique pointers which stores svgObjects.
All methods for a report must be on the low level for a specific fidelity in a seperate `...Plot.cpp` File. Plot is an object inside a method from the main specific fidelity class class and NOT an inherited class. All methods for a report must be on the low level for a specific fidelity in a separate `...Plot.cpp` File. Plot is an object inside a method from the main specific fidelity class class and NOT an inherited class.
!!! note !!! note
In case `plot.h` is used: Plots which are not added to the report (not part of the map `plots`) will not appear on the generated report! In case `plot.h` is used: Plots which are not added to the report (not part of the map `plots`) will not appear on the generated report!
### Have a closer look ...
How different strategies are handled, have a look at other modules. If you have questions, ask the unicado team!
!!! tip
Have a look at modules like `wing_design`, `systems_design` or `mission_analysis` as a first start.
...@@ -31,12 +31,13 @@ def main(): ...@@ -31,12 +31,13 @@ def main():
# Initialize exception string and runtime output logger. # Initialize exception string and runtime output logger.
tool_name = 'cost estimation' tool_name = 'cost estimation'
tool_version = '0.5.0'
runtime_output = logging.getLogger('module_logger') runtime_output = logging.getLogger('module_logger')
try: try:
"""Preprocessing: Acquire necessary data and paths.""" """Preprocessing: Acquire necessary data and paths."""
# Run 'data_preprocessing' function from 'datapreprocessing.py'. # Run 'data_preprocessing' function from 'datapreprocessing.py'.
paths_and_names, routing_dict, runtime_output = data_preprocessing('cost_estimation_conf.xml', argv) paths_and_names, routing_dict, runtime_output = data_preprocessing('cost_estimation_conf.xml', tool_version, argv)
runtime_output.print('Cost estimation started...') runtime_output.print('Cost estimation started...')
"""Run: Execute code depending on method layers.""" """Run: Execute code depending on method layers."""
... ...
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
<module_configuration_file Name="Cost Estimation Runtime Configuration"> <!-- Change naming according to module name --> <module_configuration_file Name="Cost Estimation Runtime Configuration"> <!-- Change naming according to module name -->
<control_settings description="General control settings for this tool"> <control_settings description="General control settings for this tool">
<aircraft_exchange_file_name description="Specify the name of the exchange file"> <aircraft_exchange_file_name description="Specify the name of the exchange file">
<value>CSR-02.xml</value> <value>UNICADO-SMR-180-TF.xml</value>
</aircraft_exchange_file_name> </aircraft_exchange_file_name>
<aircraft_exchange_file_directory description="Specify the direction in which the aircraft exchange file can be found"> <aircraft_exchange_file_directory description="Specify the direction in which the aircraft exchange file can be found">
<value>./projects/CSR/CSR-02/</value> <value>../projects/UNICADO-SMR/UNICADO-SMR-180-TF/</value>
</aircraft_exchange_file_directory> </aircraft_exchange_file_directory>
<own_tool_level description="Specify the tool level of this tool"> <own_tool_level description="Specify the tool level of this tool">
<value>2</value> <value>2</value>
... ...
......
...@@ -8,7 +8,7 @@ from datapreprocessingmodule import get_paths_and_names, read_routing_values_fro ...@@ -8,7 +8,7 @@ from datapreprocessingmodule import get_paths_and_names, read_routing_values_fro
from src.readlayertext import read_energy_carrier from src.readlayertext import read_energy_carrier
def data_preprocessing(module_configuration_file, argv): def data_preprocessing(module_configuration_file, tool_version, argv):
"""Conduct data preprocessing. """Conduct data preprocessing.
This function provides data preprocessing functionalities. It sets up the necessary data and imports relevant This function provides data preprocessing functionalities. It sets up the necessary data and imports relevant
...@@ -41,6 +41,7 @@ def data_preprocessing(module_configuration_file, argv): ...@@ -41,6 +41,7 @@ def data_preprocessing(module_configuration_file, argv):
"""Get paths, names, and xml trees for module configuration and aircraft exchange file.""" """Get paths, names, and xml trees for module configuration and aircraft exchange file."""
# Call 'get_paths_and_names' function to obtain various paths and names. # Call 'get_paths_and_names' function to obtain various paths and names.
paths_and_names, runtime_output = get_paths_and_names(module_configuration_file, argv) paths_and_names, runtime_output = get_paths_and_names(module_configuration_file, argv)
paths_and_names['tool_version'] = tool_version
# Note: It is the exclusive responsibility of the module manager to modify the following information! # Note: It is the exclusive responsibility of the module manager to modify the following information!
# Create layer description dictionary according to the number of individual layers. The dictionary associates # Create layer description dictionary according to the number of individual layers. The dictionary associates
# layers with their respective XML paths and expected data types according to the following scheme: # layers with their respective XML paths and expected data types according to the following scheme:
... ...
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment