-
Notifications
You must be signed in to change notification settings - Fork 247
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11990 from KratosMultiphysics/docs/expression_doc…
…umentation [Docs] Add user level documentation for Expressions
- Loading branch information
Showing
30 changed files
with
2,256 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
docs/pages/Kratos/Expressions/General/Expression_Arithmetics.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
--- | ||
title: Expression Arithmetics | ||
keywords: | ||
tags: [expression, arithmetics] | ||
sidebar: kratos_expressions | ||
summary: | ||
--- | ||
|
||
## Introduction | ||
|
||
The ```Expressions``` of type ```NodalExpression```, ```ConditionExpression```, ```ElementExpression``` and their underlying ```Expression``` can be used in arithmetic formulations. | ||
|
||
Following operations are supported: | ||
* Addition ```+``` or ```+=``` | ||
* Subtraction ```-``` or ```-=``` | ||
* Multiplication ```*``` or ```*=``` | ||
* Division ```/``` or ```/=``` | ||
* Power ```**``` or ```**=``` | ||
|
||
These operations are carried out only when their results are required ([lazy evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation)). | ||
|
||
## Example usage | ||
Here is an example for using ```NodalExpression``` (other expression types can be used in a similar fashion). | ||
```python | ||
import KratosMultiphysics as Kratos | ||
model = Kratos.Model() | ||
model_part = model.CreateModelPart("test") | ||
node_1 = model_part.CreateNewNode(1, 0, 0, 0) | ||
node_2 = model_part.CreateNewNode(2, 1, 0, 0) | ||
node_3 = model_part.CreateNewNode(3, 1, 1, 0) | ||
|
||
# setting VELOCITY of each node | ||
node_1.SetValue(Kratos.VELOCITY, Kratos.Array3([1,2,3])) | ||
node_2.SetValue(Kratos.VELOCITY, Kratos.Array3([4,5,6])) | ||
node_3.SetValue(Kratos.VELOCITY, Kratos.Array3([7,8,9])) | ||
|
||
# create nodal expression | ||
nodal_expression = Kratos.Expression.NodalExpression(model_part) | ||
|
||
# read non-historical nodal VELOCITY to expression | ||
Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) | ||
|
||
# now we can do arithmetics. | ||
nodal_expression += 1 # Adds 1 to all the components of VELOCITY in all the entities | ||
nodal_expression *= 2 # Multiplies by 2, the all the components of VELOCITY in all the entities | ||
nodal_expression /= 3 # Divides by 2, the all the components of VELOCITY in all the entities | ||
nodal_expression -= 0.5 # Subtract by 2, the all the components of VELOCITY in all the entities | ||
|
||
# writing the result to the ACCELERATION variable | ||
Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.ACCELERATION, False) | ||
|
||
for node in model_part.Nodes: | ||
print(node.GetValue(Kratos.ACCELERATION)) | ||
``` | ||
Expected output: | ||
```console | ||
| / | | ||
' / __| _` | __| _ \ __| | ||
. \ | ( | | ( |\__ \ | ||
_|\_\_| \__,_|\__|\___/ ____/ | ||
Multi-Physics 9.4."3"-docs/expression_documentation-156476ea1c-Release-x86_64 | ||
Compiled for GNU/Linux and Python3.11 with GCC-13.2 | ||
Compiled with threading and MPI support. | ||
Maximum number of threads: 30. | ||
Running without MPI. | ||
[3](0.833333,1.5,2.16667) | ||
[3](2.83333,3.5,4.16667) | ||
[3](4.83333,5.5,6.16667) | ||
``` |
11 changes: 11 additions & 0 deletions
11
docs/pages/Kratos/Expressions/General/Expression_Interface.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
title: Expression Interface | ||
keywords: | ||
tags: [Expression_Interface.md] | ||
sidebar: kratos_expressions | ||
summary: | ||
--- | ||
|
||
## Introduction | ||
|
||
TODO: Link this page to the doxygen page once it is properly online. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
--- | ||
title: Expression Types | ||
keywords: | ||
tags: [Expression_Types.md] | ||
sidebar: kratos_expressions | ||
summary: | ||
--- | ||
|
||
## Introduction | ||
|
||
There are four types of expressions. | ||
* `Expression` | ||
* `NodalExpression` | ||
* `ConditionExpression` | ||
* `ElementExpression` | ||
|
||
## `Expression` | ||
|
||
`Expression` is the lowest level class that everything else is built on top of. It models an array of numeric values (scalars, vectors, matrices, etc.), supports arithmetic operations, but is not related to any container in Kratos. To create an `Expression` or write an existing one, you can use one of the derived classes of `ExpressionIO`. | ||
|
||
TODO: add an example (@matekelemen) - requires exposing the `Input` and `Output` nested classes of `VariableExpressionIO` to python. | ||
|
||
|
||
## Nodal Expression | ||
|
||
Nodal expressions are used to store data related to nodal quantities. They may be historical or non-historical. Following code snippet illustrtes creating a nodal expression | ||
and reading ```VELOCITY``` from non-historical nodal container. | ||
```python | ||
import KratosMultiphysics as Kratos | ||
model = Kratos.Model() | ||
model_part = model.CreateModelPart("test") | ||
node_1 = model_part.CreateNewNode(1, 0.0, 0.0, 0.0) | ||
node_2 = model_part.CreateNewNode(2, 0.0, 1.0, 0.0) | ||
node_1.SetValue(Kratos.VELOCITY, Kratos.Array3([1,2,3])) | ||
node_2.SetValue(Kratos.VELOCITY, Kratos.Array3([3,4,5])) | ||
|
||
# now create the expression: | ||
nodal_expression = Kratos.Expression.NodalExpression(model_part) | ||
|
||
# now read the VELOCITY from the non-historical container | ||
Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) | ||
``` | ||
|
||
## Condition Expression | ||
|
||
Condition expressions are used to store data related to condition quantities. Following code snippet illustrtes creating a condition expression | ||
and reading ```VELOCITY``` from the conditions' container. | ||
```python | ||
import KratosMultiphysics as Kratos | ||
model = Kratos.Model() | ||
model_part = model.CreateModelPart("test") | ||
node_1 = model_part.CreateNewNode(1, 0.0, 0.0, 0.0) | ||
node_2 = model_part.CreateNewNode(2, 0.0, 1.0, 0.0) | ||
|
||
prop = model_part.CreateNewProperties(1) | ||
cond_1 = model_part.CreateNewCondition("LineCondition2D2N", 1, [1, 2], prop) | ||
cond_1.SetValue(Kratos.VELOCITY, Kratos.Array3([1,2,3])) | ||
|
||
# now create the expression: | ||
condition_expression = Kratos.Expression.ConditionExpression(model_part) | ||
|
||
# now read the VELOCITY from the condition data value container | ||
Kratos.Expression.VariableExpressionIO.Read(condition_expression, Kratos.VELOCITY) | ||
``` | ||
|
||
## Element Expression | ||
|
||
Element expressions are used to store data related to element quantities. Following code snippet illustrtes creating a element expression | ||
and reading ```VELOCITY``` from the elements' container. | ||
```python | ||
import KratosMultiphysics as Kratos | ||
model = Kratos.Model() | ||
model_part = model.CreateModelPart("test") | ||
node_1 = model_part.CreateNewNode(1, 0.0, 0.0, 0.0) | ||
node_2 = model_part.CreateNewNode(2, 0.0, 1.0, 0.0) | ||
node_3 = model_part.CreateNewNode(3, 0.0, 1.0, 0.0) | ||
|
||
prop = model_part.CreateNewProperties(1) | ||
elem_1 = model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) | ||
elem_1.SetValue(Kratos.VELOCITY, Kratos.Array3([1,2,3])) | ||
|
||
# now create the expression: | ||
element_expression = Kratos.Expression.ElementExpression(model_part) | ||
|
||
# now read the VELOCITY from the condition data value container | ||
Kratos.Expression.VariableExpressionIO.Read(element_expression, Kratos.VELOCITY) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: Notes | ||
keywords: | ||
tags: [notes, warnings, expression] | ||
sidebar: kratos_expressions | ||
summary: | ||
--- | ||
|
||
## Introduction | ||
|
||
The use of ```Expression```, ```NodalExpression```, ```ConditionExpression``` or ```ElementExpression``` should be done carefully for the following reasons. | ||
|
||
1. If it is possible to implement the arithmetics or opertations you do in ```C++``` level, then it is encouraged. | ||
2. Use arithmetic operators (`+=`, `-=`, `*=`, `/=`, `**=`, `+`, `-`, `*`, `/`) carefully. Operators keep their operands in memory, which means that if you chain operations for long enough, at some point you will run out of RAM. In such cases, `Kratos.Expression.Utils.Collpase` to forcefully evaluate an expression and discard the hierarchy of operands it stored. An example use case would be updating the same expression with new data in every time step of an analysis. | ||
3. Expressions have significant memory and performance overhead due to dynamic polymorphism. If it becomes a bottleneck, move your calculations to `C++`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
--- | ||
title: Overview | ||
keywords: | ||
tags: [overview.md] | ||
sidebar: kratos_expressions | ||
summary: | ||
--- | ||
## Introduction | ||
|
||
An expression represents a mechanism where a given mathematical expression is evaluated when actual value of that expression in required. One can compare these | ||
expressions to lazy expressions (expression templates) in [Eigen](https://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html) or in [Boost](https://www.boost.org/doc/libs/1_82_0/doc/html/boost_yap/manual.html). The main difference being, Kratos expressions are **dynamic** lazy expressions (evaluated on demand, not automatically) whose type is evaluated at runtime, whereas Eigen and Boost has **static** lazy expressions whose type is known at compile-time. Few of the main advantages of these lazy expressions are: | ||
* May reduce memory footprint. | ||
* May reduce computational cost. | ||
|
||
KratosMultiphysics stores its data in different containers depending on what kind of geometry that data is associated with (node, element, condition, etc.) and what that data represents. Each container requires a ```Kratos::Variable``` to access its underlying data. This requires defining the variable beforehand, and then using it to store and retrieve its value. Expressions allow users/developers to access and manipulate the data within these containers regardless of what `Kratos::Variable` they belong to. All expressions support **shared memory** and **distributed memory** parallelism. Though implemented in C++, expressions are meant to be used mainly in python. | ||
|
||
## Supported data containers | ||
|
||
The following data containers are supported: | ||
* NodalExpression - data related to nodes (with historical or non-historical variables). | ||
* ConditionExpression - data related to conditions. | ||
* ElementExpression - data related to elements. | ||
|
||
## Supported data types | ||
|
||
Expressions are compatible with most main variable types in Kratos: | ||
|
||
* ```int``` | ||
* ```double``` | ||
* ```array_1d<double, 3>``` | ||
* ```array_1d<double, 4>``` | ||
* ```array_1d<double, 6>``` | ||
* ```array_1d<double, 9>``` | ||
* ```Vector``` | ||
* ```Matrix``` | ||
|
||
## Use cases | ||
|
||
Expressions are useful in following scenarios: | ||
1. Transferring data between Kratos and other libraries - third-party libraries may be developed in other languages like Fortran as well. | ||
2. Transferring data between Kratos and numpy/scipy. | ||
3. Storing and fetching Kratos data in HDF5. | ||
4. Non performance-critical intermediate calculations in python. | ||
5. Transerring data back and forth within Kratos without variables such as in OptimizationApplication. | ||
6. Quick and convenient prototyping of research code in python while using **shared memory** and **distributed memory** paralellism. | ||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.