diff --git a/docs/pages/Kratos/Documentation_Guide/How_Tos/Testing.md b/docs/pages/Kratos/Documentation_Guide/How_Tos/Testing.md index 5ad490fd3764..4821017bfd01 100644 --- a/docs/pages/Kratos/Documentation_Guide/How_Tos/Testing.md +++ b/docs/pages/Kratos/Documentation_Guide/How_Tos/Testing.md @@ -1,9 +1,9 @@ --- title: Documentation testing and updating -keywords: +keywords: tags: [Testing.md] sidebar: documentation_guide -summary: +summary: --- diff --git a/docs/pages/Kratos/Expressions/General/Expression_Arithmetics.md b/docs/pages/Kratos/Expressions/General/Expression_Arithmetics.md new file mode 100644 index 000000000000..634ca371a02d --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Expression_Arithmetics.md @@ -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) +``` diff --git a/docs/pages/Kratos/Expressions/General/Expression_Interface.md b/docs/pages/Kratos/Expressions/General/Expression_Interface.md new file mode 100644 index 000000000000..374432225719 --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Expression_Interface.md @@ -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. diff --git a/docs/pages/Kratos/Expressions/General/Expression_Types.md b/docs/pages/Kratos/Expressions/General/Expression_Types.md new file mode 100644 index 000000000000..0b7b22ae13fe --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Expression_Types.md @@ -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) +``` diff --git a/docs/pages/Kratos/Expressions/General/Notes.md b/docs/pages/Kratos/Expressions/General/Notes.md new file mode 100644 index 000000000000..b500849e788d --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Notes.md @@ -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++`. diff --git a/docs/pages/Kratos/Expressions/General/Overview.md b/docs/pages/Kratos/Expressions/General/Overview.md new file mode 100644 index 000000000000..f6635163edda --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Overview.md @@ -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``` +* ```array_1d``` +* ```array_1d``` +* ```array_1d``` +* ```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. + + + + + diff --git a/docs/pages/Kratos/Expressions/General/Working_with_Numpy.md b/docs/pages/Kratos/Expressions/General/Working_with_Numpy.md new file mode 100644 index 000000000000..0ed901957b9e --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/Working_with_Numpy.md @@ -0,0 +1,172 @@ +--- +title: Working with Numpy +keywords: +tags: [numpy, scipy, expressions, variable expression io, carray expression io] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +Expressions make working with numpy/scipy or any other thrid party library easier. It allows reading numpy arrays to expressions, and then assign them to Kratos containers using variables. + +**When running with MPI, these expressions will hold only data of corresponding containers of the local mesh**. + +## Writing to numpy arrays + +```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) + +# now get the numpy array from the expression +numpy_nodal_expression = nodal_expression.Evaluate() + +# first dimension of the numpy array always represents number of entities in the expression (local mesh entities only) +# rest of the dimensions represent the dimensions of the entity data. In this case, VELOCITY have only three components, +# it shows 3 as the last dimension. +print("Shape of the numpy array = ", numpy_nodal_expression.shape) +``` + +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. +Shape of the numpy array = (2, 3) +``` + +## Reading from numpy arrays +First create the numpy array independent from Kratos if the number of local entities are known (i.e. number of nodes/conditions/elements in the local mesh). The following numpy data types are supported when reading numpy arrays: +1. ```numpy.int32``` +2. ```numpy.float64``` + +The numpy array can then be **copied** to the expression. The following code snippet shows an example: + +```python +import numpy +# create the numpy expression. This does not need Kratos as long as you know correctly +# the number of local entities (i.e. nodes/conditions/elements) in the model part. +# it is a good practice to specify the "dtype" in here. +# here also, first dimension represent the number of local entities, rest of the +# dimensions represent the dimensionality of the entity data. +numpy_array = numpy.array([ + [1,2,3], + [3,4,5]], dtype=numpy.float64) + + +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) + +# now create the expression: +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# now read in the data from numpy array to expression +Kratos.Expression.CArrayExpressionIO.Read(nodal_expression, numpy_array) + +# now write the expression data to VELOCITY variable +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.VELOCITY, False) + +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + print(f"node id: {node.Id}, velocity: [{velocity[0]}, {velocity[1]}, {velocity[2]}]") +``` + +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. +node id: 1, velocity: [1.0, 2.0, 3.0] +node id: 2, velocity: [3.0, 4.0, 5.0] +``` + +## Moving from numpy arrays + +This is similar to [reading from numpy arrays](#reading-from-numpy-arraystest) with the difference that this does not create a copy for the expression. +It uses the memory location of the original numpy array within the expression, eliding the copy and its related memory allocation. An important consequence is that **the original numpy array must be kept in memory for entire lifetime of the expression**, otherwise evaluating the expression will result in a segmentation fault. + +Following code snippet illustrates how to move numpy arrays to expressions: +```python +import numpy +# create the numpy expression. This does not need Kratos as long as you know correctly +# the number of local entities (i.e. nodes/conditions/elements) in the model part. +# it is a good practice to specify the "dtype" in here. +# here also, first dimension represent the number of local entities, rest of the +# dimensions represent the dimensionality of the entity data. +numpy_array = numpy.array([ + [1,2,3], + [3,4,5]], dtype=numpy.float64) + + +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) + +# now create the expression: +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# now move in the data from numpy array to expression (linking nodal expression with numpy array) +Kratos.Expression.CArrayExpressionIO.Move(nodal_expression, numpy_array) + +# now write the expression data to VELOCITY variable +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.VELOCITY, False) + +# now it will print the value in the numpy array +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + print(f"node id: {node.Id}, velocity: [{velocity[0]}, {velocity[1]}, {velocity[2]}]") + +# now change some values in the numpy array +numpy_array[1, 1] = 10.0 + +# now write the expression data to VELOCITY variable to update the nodal data value container. +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.VELOCITY, False) +# now it will print the modified value in the numpy array +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + print(f"node id: {node.Id}, velocity: [{velocity[0]}, {velocity[1]}, {velocity[2]}]") +``` +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. +node id: 1, velocity: [1.0, 2.0, 3.0] +node id: 2, velocity: [3.0, 4.0, 5.0] +node id: 1, velocity: [1.0, 2.0, 3.0] +node id: 2, velocity: [3.0, 10.0, 5.0] +``` diff --git a/docs/pages/Kratos/Expressions/General/menu_info.json b/docs/pages/Kratos/Expressions/General/menu_info.json new file mode 100644 index 000000000000..36c7a56d5203 --- /dev/null +++ b/docs/pages/Kratos/Expressions/General/menu_info.json @@ -0,0 +1,6 @@ +{ + "custom_entries": [ + "Overview.md", + "Expression_Types.md" + ] +} \ No newline at end of file diff --git a/docs/pages/Kratos/Expressions/IOs/C_Array_Expression_IO.md b/docs/pages/Kratos/Expressions/IOs/C_Array_Expression_IO.md new file mode 100644 index 000000000000..57baa3286400 --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/C_Array_Expression_IO.md @@ -0,0 +1,141 @@ +--- +title: C Array Expression IO +keywords: +tags: [c array expression io, numpy, scipy, Vector] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```CArrayExpressionIO``` is used to exchange data between `C` type arrays and expressions. In python, it can be used to exchange data between numpy arrays, ```Kratos::Vectors```, or any other contiguous array of supported types. + +## Reading or viewing a numpy array + +Please refer to [Working with numpy](../General/Working_with_Numpy.html) section. + +## Writing to numpy array +In MPI runs, expressions will only write data from the ```LocalMesh``` to the numpy array. The size of the numpy array should be compatible with the expression shape. The following code snippet shows an example: +```python +import numpy +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) + +# now get the numpy array from the expression +numpy_array = numpy.zeros((2,3), dtype=numpy.float64) +Kratos.Expression.CArrayExpressionIO.Write(nodal_expression, numpy_array) + +# first dimension of the numpy array always represents number of entities in the expression (local mesh entities only) +# rest of the dimensions represent the dimensions of the entity data. In this case, VELOCITY have only three components, +# it shows 3 as the last dimension. +print("numpy array = ", numpy_array) +``` + +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. +numpy array = [[1. 2. 3.] + [3. 4. 5.]] +``` + +## Reading and writing to `Kratos::Vector` +```CArrayExpressionIO``` also allows reading and writing from ```Kratos::Vector``` containers. In this case, the size of the ```Kratos::Vector``` should be the flattened size of the shape of interest which the user will be working on. + +The arguments for reading from a ```Kratos::Vector``` are: +- expression to read to +- `Kratos::Vector` to read from +- shape of the entity + +Example: +```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) + +vector = Kratos.Vector([1,2,3,4,5,6]) + +# now create the expression: +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# now read in the Kratos::Vector +Kratos.Expression.CArrayExpressionIO.Read(nodal_expression, vector, [3]) + +# now write the VELOCITY to the non-historical container +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.VELOCITY, False) + +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + print(f"node_id: {node.Id}, velocity: [{velocity[0]}, {velocity[1]}, {velocity[2]}]") +``` + +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. +node_id: 1, velocity: [1.0, 2.0, 3.0] +node_id: 2, velocity: [4.0, 5.0, 6.0] +``` + +Writing to a ```Kratos::Vector``` is illustarted by the following code snippet. If the passed vector (to where the expression values are written) is not with the correct size, it will be resized. This will also only write the data values of the local entities in the LocalMesh. +```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) + +# now write the VELOCITY to the non-historical container +vector = Kratos.Vector() +Kratos.Expression.CArrayExpressionIO.Write(nodal_expression, vector) +print(vector) +``` + +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. +[6](1,2,3,3,4,5) +``` diff --git a/docs/pages/Kratos/Expressions/IOs/Domain_Size_Expression_IO.md b/docs/pages/Kratos/Expressions/IOs/Domain_Size_Expression_IO.md new file mode 100644 index 000000000000..a1ff83ebf6ad --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/Domain_Size_Expression_IO.md @@ -0,0 +1,92 @@ +--- +title: Domain Size Expression IO +keywords: +tags: [domain size, condition, element, expression io] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```DomainSizeExpressionIO``` computes the domain sizes (length, surface or volume, depending of the entity's dimension) of each entitiy (such as ```Condition``` or ```Element```) in the provided `ModelPart`. This only supports ```ConditionExpression``` or ```ElementExression```. Domain sizes are computed by accessing underlying geometry's ```Geometry::DomainSize``` method. + +1. If the ```Condition``` or ```Element``` as a geometry representing a line, then this will compute an expression with line length for each entitiy. +2. If the ```Condition``` or ```Element``` as a geometry representing a surface, then this will compute an expression with surface area for each entitiy. +3. If the ```Condition``` or ```Element``` as a geometry representing a volume, then this will compute an expression with volume for each entitiy. + +The resulting expression is always a scalar expression. + +## Reading domain sizes +Following code snippet shows how to read domain sizes to an expression +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) +model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) + +# now create the expression: +element_expression = Kratos.Expression.ElementExpression(model_part) + +# now read the element sizes (in this case triangle surface area) +Kratos.Expression.DomainSizeExpressionIO.Read(element_expression) + +shape = element_expression.Evaluate().shape +print(shape) +``` + +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. +(1,) +``` + +## Using expressions without the model parts +The ```ConditionExpression``` and ```ElementExpression``` has an expression which can be directly used if required. The advantage of working +with the ```Expression``` directely is, then it is not bound to a model part of a ```DataValueContainer```. Hence, these expressions can be interchanged if required in +advanced use cases. Following code snippet shows how to use bare ```Expressions```. +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) +model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) + +# now create the expression by reading element domain sizes: +exp = Kratos.Expression.DomainSizeExpressionIO.Input(model_part, Kratos.Globals.DataLocation.Element).Execute() + +# do some arithmetic operations +exp *= 2.0 + +print(exp) +``` + +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. +(DoubleVec[]*2) +``` diff --git a/docs/pages/Kratos/Expressions/IOs/Integration_Point_Expression_IO.md b/docs/pages/Kratos/Expressions/IOs/Integration_Point_Expression_IO.md new file mode 100644 index 000000000000..25c1724e08aa --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/Integration_Point_Expression_IO.md @@ -0,0 +1,82 @@ +--- +title: Integration Point Expression IO +keywords: +tags: [Integration_Point_Expression_IO.md] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```IntegrationPointExpressionIO``` is used to set or get quantities at integration points from elements or conditions. + +### Variable types +Following data types are supported for integration point quantity calculations. +* ```int``` +* ```double``` +* ```array_1d``` +* ```array_1d``` +* ```array_1d``` +* ```array_1d``` +* ```Vector``` +* ```Matrix``` + +### Shape of resulting expressions +The resulting expressions computed by ```IntegrationPointExpressionIO``` will have two additional dimensions on top of the data type's dimensions. The first one indicates the number of entities in the expression, while the second dimension is the number of gauss points computed in each entitiy. The rest of the dimensions are carried over from the integration point quantity. + +## Reading and writing integration point data +Following code snippet shows how to read and write integration point data. +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) +model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +cond1 = model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) +cond1.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 container +Kratos.Expression.IntegrationPointExpressionIO.Read(element_expression, Kratos.VELOCITY) + +# the shape of the element expression will be [1, 1, 3] where first "1" is number of elements, second "1" is number of gauss points. +shape = element_expression.Evaluate().shape + +# do some arithmetic operations +element_expression *= 2.0 + +# now read the ACCELERATION from the container +Kratos.Expression.IntegrationPointExpressionIO.Write(element_expression, Kratos.ACCELERATION) +``` + +## Using expressions without the model parts +The underlying `Expression` instance of ```NodalExpression```, ```ConditionExpression``` and ```ElementExpression``` can be accessed directly, if necessary. The advantage of working +with bare ```Expression```s is that they are not bound to a specific model part or entity type, which means that they are completely interchangable. The following code snippet shows how to use bare ```Expression```s. +```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) +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) +model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +cond1 = model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) +cond1.SetValue(Kratos.VELOCITY, Kratos.Array3([1,2,3])) + +# now create the expression by reading non historical velocity: +exp = Kratos.Expression.IntegrationPointExpressionIO.Input(model_part, Kratos.VELOCITY, Kratos.Globals.DataLocation.Element).Execute() + +# do some arithmetic operations +exp *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.IntegrationPointExpressionIO.Output(model_part, Kratos.ACCELERATION, Kratos.Globals.DataLocation.Element).Execute(exp) +``` diff --git a/docs/pages/Kratos/Expressions/IOs/Literal_Expression_Input.md b/docs/pages/Kratos/Expressions/IOs/Literal_Expression_Input.md new file mode 100644 index 000000000000..b2cbf2cff341 --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/Literal_Expression_Input.md @@ -0,0 +1,202 @@ +--- +title: Literal Expression Input +keywords: +tags: [literal values, expressions, scalars] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```LiteralExpressionIO``` is used to represent literal values. The following literal types are supported: +* int +* double +* array_1d +* array_1d +* array_1d +* array_1d +* Vector +* Matrix + +This IO will create an expression with the specified literal for all entities. + +## Setting literal expressions + +The following code snippet shows how to set literal expressions +```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) + +# create the expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# create the literal expression +Kratos.Expression.LiteralExpressionIO.SetData(nodal_expression, Kratos.Array3([1, 2, 3])) + +# now write the value to non-historical velocity +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.VELOCITY, False) + +# now check +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + print(f"node_id: {node.Id}, velocity = [{velocity[0]}, {velocity[1]}, {velocity[2]}]") +``` + +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. +node_id: 1, velocity = [1.0, 2.0, 3.0] +node_id: 2, velocity = [1.0, 2.0, 3.0] +``` + +## Setting literal expression to zero + +The ```LiteralExpressionIO``` also can be used to set entity data to zero for a given variable. **In the case of dynamically sized types, it will create empty instances [Such as Vector with size 0, Matrix with shape (0,0)**. The passed variable is only used to determine the entity shape. Example: +```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.PRESSURE, 10) +node_2.SetValue(Kratos.PRESSURE, 20) + +# create the expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the PRESSURE +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.PRESSURE, False) + +print("PRESSURE before resetting:\n", nodal_expression.Evaluate()) + +# create the literal expression +Kratos.Expression.LiteralExpressionIO.SetDataToZero(nodal_expression, Kratos.PRESSURE) + +# now write the value to non-historical velocity +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.TEMPERATURE, False) + +# now check +for node in model_part.Nodes: + print(f"node_id: {node.Id}, pressure = {node.GetValue(Kratos.PRESSURE)}, temperature = {node.GetValue(Kratos.TEMPERATURE)}") +``` + +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. +PRESSURE before resetting: + [10. 20.] +node_id: 1, pressure = 10.0, temperature = 0.0 +node_id: 2, pressure = 20.0, temperature = 0.0 +``` + +## Use cases + +Lets assume you want to get inverse of a scalar expressions such as PRESSURE. In that case you can easily use ```LiteralExpressionIO``` to compute it. +Following is an example. +```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.PRESSURE, 10) +node_2.SetValue(Kratos.PRESSURE, 20) + +# create the expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the PRESSURE +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.PRESSURE, False) + +print("PRESSURE before resetting:\n", nodal_expression.Evaluate()) + +scalar_expression = Kratos.Expression.NodalExpression(model_part) +Kratos.Expression.LiteralExpressionIO.SetData(scalar_expression, 1.0) +inverse_expression = scalar_expression / nodal_expression + +# now write the value to non-historical velocity +Kratos.Expression.VariableExpressionIO.Write(inverse_expression, Kratos.TEMPERATURE, False) + +# now check +for node in model_part.Nodes: + print(f"node_id: {node.Id}, pressure = {node.GetValue(Kratos.PRESSURE)}, temperature = {node.GetValue(Kratos.TEMPERATURE)}") +``` + +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. +PRESSURE before resetting: + [10. 20.] +node_id: 1, pressure = 10.0, temperature = 0.1 +node_id: 2, pressure = 20.0, temperature = 0.05 +``` + +## Using expressions without the model parts +The ```NodalExpression```, ```ConditionExpression``` and ```ElementExpression``` has an expression which can be directly used if required. The advantage of working +with the ```Expression``` directely is, then it is not bound to a model part of a ```DataValueContainer```. Hence, these expressions can be interchanged if required in +advanced use cases. Following code snippet shows how to use bare ```Expressions```. +```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) + +# now create the expression by reading non historical velocity: +exp = Kratos.Expression.LiteralExpressionIO.Input(model_part, Kratos.Array3([1,2,3]), Kratos.Globals.DataLocation.NodeNonHistorical).Execute() + +# do some arithmetic operations +exp *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.VariableExpressionIO.Output(model_part, Kratos.ACCELERATION, Kratos.Globals.DataLocation.NodeNonHistorical).Execute(exp) + +# now print and see +for node in model_part.Nodes: + acceleration = node.GetValue(Kratos.ACCELERATION) + print(f"node_id: {node.Id}, acceleration: [{acceleration[0]},{acceleration[1]},{acceleration[2]}]") +``` + +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. +node_id: 1, acceleration: [2.0,4.0,6.0] +node_id: 2, acceleration: [2.0,4.0,6.0] +``` diff --git a/docs/pages/Kratos/Expressions/IOs/Nodal_Position_Expression_IO.md b/docs/pages/Kratos/Expressions/IOs/Nodal_Position_Expression_IO.md new file mode 100644 index 000000000000..fc9800262e96 --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/Nodal_Position_Expression_IO.md @@ -0,0 +1,115 @@ +--- +title: Nodal Position Expression IO +keywords: +tags: [nodal position, initial, current, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```NodalPositionExpressionIO``` allows writing and reading nodal positions of a given model part. This can be used on following the configurations: +* Initial -> initial positions of the node +* Current -> positions of the nodes in the current configuration + +In the case of **distributed memory** parallelized runs, the reading will only read the nodal positions of the nodes in the local mesh, and the writing will write to local mesh nodes and will afterwards synchronize to update the ghost meshes. + +## Reading and writing nodal positions +Following code snippet shows how to read initial and current configuration from nodes. +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.AddNodalSolutionStepVariable(Kratos.ACCELERATION) +node_1 = model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +node_2 = model_part.CreateNewNode(2, 0.0, 1.0, 0.0) + +delta = 10.0 +node_1.X += delta +node_1.Y += delta + +# now create the expression: +initial_nodal_expression = Kratos.Expression.NodalExpression(model_part) +current_nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# now read the nodal positions +Kratos.Expression.NodalPositionExpressionIO.Read(initial_nodal_expression,Kratos.Configuration.Initial) +Kratos.Expression.NodalPositionExpressionIO.Read(current_nodal_expression,Kratos.Configuration.Current) + +print("initial:\n", initial_nodal_expression.Evaluate()) +print("current:\n", current_nodal_expression.Evaluate()) + +# now do some arithmetics with the exps +initial_nodal_expression *= 2 +current_nodal_expression *= 2 + +# now write the modified nodal positions back to nodes +Kratos.Expression.NodalPositionExpressionIO.Write(initial_nodal_expression,Kratos.Configuration.Initial) +Kratos.Expression.NodalPositionExpressionIO.Write(current_nodal_expression,Kratos.Configuration.Current) + +# now read nodal positions +for node in model_part.Nodes: + print(f"node_id: {node.Id}, initial: [{node.X0}, {node.Y0}, {node.Z0}], current: [{node.X}, {node.Y}, {node.Z}]") +``` + +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. +initial: + [[0. 0. 0.] + [0. 1. 0.]] +current: + [[10. 10. 0.] + [ 0. 1. 0.]] +node_id: 1, initial: [0.0, 0.0, 0.0], current: [20.0, 20.0, 0.0] +node_id: 2, initial: [0.0, 2.0, 0.0], current: [0.0, 2.0, 0.0] +``` + +## Using expressions without the model parts +The ```NodalExpression```, ```ConditionExpression``` and ```ElementExpression``` has an expression which can be directly used if required. The advantage of working +with the ```Expression``` directly is, then it is not bound to a model part of a ```DataValueContainer```. Hence, these expressions can be interchanged if required in +advanced use cases. Following code snippet shows how to use bare ```Expressions```. +```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) + +# now create the expression by reading initial configuration: +exp = Kratos.Expression.NodalPositionExpressionIO.Input(model_part, Kratos.Configuration.Initial).Execute() + +# do some arithmetic operations +exp *= 2.0 + +# now write the expression value to current configuration +Kratos.Expression.NodalPositionExpressionIO.Output(model_part, Kratos.Configuration.Current).Execute(exp) + +# now read nodal positions +for node in model_part.Nodes: + print(f"node_id: {node.Id}, initial: [{node.X0}, {node.Y0}, {node.Z0}], current: [{node.X}, {node.Y}, {node.Z}]") +``` + +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. +node_id: 1, initial: [0.0, 0.0, 0.0], current: [0.0, 0.0, 0.0] +node_id: 2, initial: [0.0, 1.0, 0.0], current: [0.0, 2.0, 0.0] +``` + diff --git a/docs/pages/Kratos/Expressions/IOs/Variable_Expression_IO.md b/docs/pages/Kratos/Expressions/IOs/Variable_Expression_IO.md new file mode 100644 index 000000000000..ec933bdf1196 --- /dev/null +++ b/docs/pages/Kratos/Expressions/IOs/Variable_Expression_IO.md @@ -0,0 +1,208 @@ +--- +title: Variable Expression IO +keywords: +tags: [variable expression io, expressions, variable] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +```VariableExpressionIO``` is used to read ```Kratos::Variable``` from a container to an expression vice versa. The expression will only read or write to the entities (i.e. nodes/conditions/elements) in the local mesh. If writing an expression to a variable in a container during an MPI run, synchronization between ranks is automatically done. + +### Variable types + +The following Kratos variable types are supported: +* ```Kratos::Variable``` +* ```Kratos::Variable``` +* ```Kratos::Variable>``` +* ```Kratos::Variable>``` +* ```Kratos::Variable>``` +* ```Kratos::Variable>``` +* ```Kratos::Variable``` +* ```Kratos::Variable``` + +### Shape of the resulting expression +If the data type has static size (such as ```Kratos::Variable```, ```Kratos::Variable>```), the result's shape is the number of local entities, followed by the static size of the type. However, if the data type has dynamic size (such as ```Kratos::Variable```, ```Kratos::Variable```), then all entries in the container are assumed to have the same shape as the first entry. [In MPI runs, the first entry's shape is synchronized across all ranks to determine the final shape of the expression]. + + +## Reading/Writing nodal values + +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.AddNodalSolutionStepVariable(Kratos.ACCELERATION) +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) + +# do some arithmetic operations +nodal_expression *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.VariableExpressionIO.Write(nodal_expression, Kratos.ACCELERATION, True) + +# now print and see +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + acceleration = node.GetSolutionStepValue(Kratos.ACCELERATION) + print(f"node_id: {node.Id}, velocity: [{velocity[0]},{velocity[1]},{velocity[2]}], acceleration: [{acceleration[0]},{acceleration[1]},{acceleration[2]}]") +``` + +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. +node_id: 1, velocity: [1.0,2.0,3.0], acceleration: [2.0,4.0,6.0] +node_id: 2, velocity: [3.0,4.0,5.0], acceleration: [6.0,8.0,10.0] +``` + +## Reading/Writing condition values +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +cond1 = model_part.CreateNewCondition("LineCondition2D2N", 1, [1, 2], prop) +cond1.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 non-historical container +Kratos.Expression.VariableExpressionIO.Read(condition_expression, Kratos.VELOCITY) + +# do some arithmetic operations +condition_expression *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.VariableExpressionIO.Write(condition_expression, Kratos.ACCELERATION) + +# now print and see +for condition in model_part.Conditions: + velocity = condition.GetValue(Kratos.VELOCITY) + acceleration = condition.GetValue(Kratos.ACCELERATION) + print(f"condition_id: {condition.Id}, velocity: [{velocity[0]},{velocity[1]},{velocity[2]}], acceleration: [{acceleration[0]},{acceleration[1]},{acceleration[2]}]") +``` + +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. +condition_id: 1, velocity: [1.0,2.0,3.0], acceleration: [2.0,4.0,6.0] +``` + +## Reading/Writing element values +```python +import KratosMultiphysics as Kratos +model = Kratos.Model() +model_part = model.CreateModelPart("test") +model_part.CreateNewNode(1, 0.0, 0.0, 0.0) +model_part.CreateNewNode(2, 0.0, 1.0, 0.0) +model_part.CreateNewNode(3, 1.0, 1.0, 0.0) + +prop = model_part.CreateNewProperties(1) +cond1 = model_part.CreateNewElement("Element2D3N", 1, [1, 2, 3], prop) +cond1.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 non-historical container +Kratos.Expression.VariableExpressionIO.Read(element_expression, Kratos.VELOCITY) + +# do some arithmetic operations +element_expression *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.VariableExpressionIO.Write(element_expression, Kratos.ACCELERATION) + +# now print and see +for element in model_part.Elements: + velocity = element.GetValue(Kratos.VELOCITY) + acceleration = element.GetValue(Kratos.ACCELERATION) + print(f"element_id: {element.Id}, velocity: [{velocity[0]},{velocity[1]},{velocity[2]}], acceleration: [{acceleration[0]},{acceleration[1]},{acceleration[2]}]") +``` + +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. +element_id: 1, velocity: [1.0,2.0,3.0], acceleration: [2.0,4.0,6.0] +``` + +## Using expressions without the model parts +The ```NodalExpression```, ```ConditionExpression``` and ```ElementExpression``` has an expression which can be directly used if required. The advantage of working +with the ```Expression``` directely is, then it is not bound to a model part of a ```DataValueContainer```. Hence, these expressions can be interchanged if required in +advanced use cases. Following code snippet shows how to use bare ```Expressions```. +```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 by reading non historical velocity: +exp = Kratos.Expression.VariableExpressionIO.Input(model_part, Kratos.VELOCITY, Kratos.Globals.DataLocation.NodeNonHistorical).Execute() + +# do some arithmetic operations +exp *= 2.0 + +# now write the expression value to model part as ACCELERATION in the historical container +Kratos.Expression.VariableExpressionIO.Output(model_part, Kratos.ACCELERATION, Kratos.Globals.DataLocation.NodeNonHistorical).Execute(exp) + +# now print and see +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + acceleration = node.GetValue(Kratos.ACCELERATION) + print(f"node_id: {node.Id}, velocity: [{velocity[0]},{velocity[1]},{velocity[2]}], acceleration: [{acceleration[0]},{acceleration[1]},{acceleration[2]}]") +``` + +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. +node_id: 1, velocity: [1.0,2.0,3.0], acceleration: [2.0,4.0,6.0] +node_id: 2, velocity: [3.0,4.0,5.0], acceleration: [6.0,8.0,10.0] +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Abs.md b/docs/pages/Kratos/Expressions/Utilities/Abs.md new file mode 100644 index 000000000000..811c5403bec9 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Abs.md @@ -0,0 +1,116 @@ +--- +title: Abs +keywords: +tags: [abs, expression] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +This computes the componentwise absolute value of the given expression. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. The Following equation illustrates the formulation of the resulting expression. + +

$$ Abs\left(\underline{\mathbf{u}}\right) = \left\lbrace \left|u_{ij}\right|, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +## Use cases + +### Using to compute absolute values +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +abs_nodal_expression = Kratos.Expression.Utils.Abs(nodal_expression) + +# now write the absolute value for checking to the ACCELERATION +Kratos.Expression.VariableExpressionIO.Write(abs_nodal_expression, Kratos.ACCELERATION, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + acceleration = node.GetValue(Kratos.ACCELERATION) + + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], acceleration = [{acceleration[0]}, {acceleration[1]}, {acceleration[2]}]") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 494037 +node_id: 1, velocity=[-1.0, -2.0, -3.0], acceleration = [1.0, 2.0, 3.0] +node_id: 2, velocity=[-4.0, -5.0, -6.0], acceleration = [4.0, 5.0, 6.0] +node_id: 3, velocity=[-7.0, -8.0, -9.0], acceleration = [7.0, 8.0, 9.0] +``` + +### Using to compute entity wise inf-norm +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +norm_inf_nodal_expression = Kratos.Expression.Utils.EntityMax(Kratos.Expression.Utils.Abs(nodal_expression)) + +# now write the entity wise norm inf scalar value for checking to the PRESSURE +Kratos.Expression.VariableExpressionIO.Write(norm_inf_nodal_expression, Kratos.PRESSURE, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + pressure = node.GetValue(Kratos.PRESSURE) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], pressure = {pressure}") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 494090 +node_id: 1, velocity=[-1.0, -2.0, -3.0], pressure = 3.0 +node_id: 2, velocity=[-4.0, -5.0, -6.0], pressure = 6.0 +node_id: 3, velocity=[-7.0, -8.0, -9.0], pressure = 9.0 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Collapse.md b/docs/pages/Kratos/Expressions/Utilities/Collapse.md new file mode 100644 index 000000000000..5ccbfa0b3844 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Collapse.md @@ -0,0 +1,64 @@ +--- +title: Collapse +keywords: +tags: [collapse, lazy expression, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction +```Collapse``` method is used to collapse the lazy expression tree. **This is useful when the lazy expression tree is larger which may occupy or exceeds the RAM +limitations.**. + +The resulting expression retains the original's shape, having the same evaluated values. But the resulting expression will not be having the tree structure since it is collapsed. + +## Use case +The following example shows how to compute the maximum depth of the expression hierarchy, and collapse it down to a single array. +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +nodal_expression *= 2 +nodal_expression += 1 + +print(nodal_expression.GetMaxDepth()) + +collapsed_exp = Kratos.Expression.Utils.Collapse(nodal_expression) + +# Destroy the original expression to free up memory +del nodal_expression + +print(collapsed_exp.GetMaxDepth()) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 499448 +3 +1 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Comb.md b/docs/pages/Kratos/Expressions/Utilities/Comb.md new file mode 100644 index 000000000000..b4efe020e29d --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Comb.md @@ -0,0 +1,72 @@ +--- +title: Comb +keywords: +tags: [combing, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction +`Comb` merges multiple expressions in to one. **All input expressions must have the same number of entities.** + +Example: +``` +For example, let the list_of_expression contain the following expressions: +exp_list[0] = data{1, 2, 3} with 3 items, and item shape = [] + - - - +exp_list[1] = data{4, 5, -1, 6, 7, -1, 8, 9, -1} with 3 items, and item shape = [3] + -------- -------- -------- +The resulting expression has item shape [3] with 4 items: +output_exp = [1, 4, 5, -1, 2, 6, 7, -1, 3, 8, 9, -1] + --------- -------- -------- +``` +The expression won't be evaluated unless `Expression::Evaluate` is called. + +## Use case +```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 and PRESSURE of each node +node_1.SetValue(Kratos.VELOCITY, Kratos.Array3([4,5,-1])) +node_2.SetValue(Kratos.VELOCITY, Kratos.Array3([6,7,-1])) +node_3.SetValue(Kratos.VELOCITY, Kratos.Array3([8,9,-1])) +node_1.SetValue(Kratos.PRESSURE, 1) +node_2.SetValue(Kratos.PRESSURE, 2) +node_3.SetValue(Kratos.PRESSURE, 3) + +# create expressions +u_exp = Kratos.Expression.NodalExpression(model_part) +p_exp = Kratos.Expression.NodalExpression(model_part) + +# read data in to expressions +Kratos.Expression.VariableExpressionIO.Read(u_exp, Kratos.VELOCITY, False) +Kratos.Expression.VariableExpressionIO.Read(p_exp, Kratos.PRESSURE, False) + +# now combine +combined_exp = Kratos.Expression.Utils.Comb([p_exp, u_exp]) + +print(combined_exp.Evaluate()) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 502917 +[[ 1. 4. 5. -1.] + [ 2. 6. 7. -1.] + [ 3. 8. 9. -1.]] +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/EntityMax.md b/docs/pages/Kratos/Expressions/Utilities/EntityMax.md new file mode 100644 index 000000000000..9a20330034c7 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/EntityMax.md @@ -0,0 +1,63 @@ +--- +title: EntityMax +keywords: +tags: [entity max, max, expression] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +`EntityMax` finds the largest component of each entity. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. The result is always a scalar expression. + +

$$ EntityMax\left(\underline{\mathbf{u}}\right) = \left\lbrace v_i | \quad v_i = \max_{j\in\left[0, N\right)} {u_{ij}} \quad \forall i\in\left[0, M\right)\right\rbrace$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +max_nodal_expression = Kratos.Expression.Utils.EntityMax(nodal_expression) + +# now write it to PRESSURE for checking. +Kratos.Expression.VariableExpressionIO.Write(max_nodal_expression, Kratos.PRESSURE, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + pressure = node.GetValue(Kratos.PRESSURE) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], pressure = {pressure}") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 506403 +node_id: 1, velocity=[-1.0, -2.0, -3.0], pressure = -1.0 +node_id: 2, velocity=[-4.0, -5.0, -6.0], pressure = -4.0 +node_id: 3, velocity=[-7.0, -8.0, -9.0], pressure = -7.0 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/EntityMin.md b/docs/pages/Kratos/Expressions/Utilities/EntityMin.md new file mode 100644 index 000000000000..0638be416b0c --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/EntityMin.md @@ -0,0 +1,62 @@ +--- +title: EntityMin +keywords: +tags: [entity min, min, expressions] +sidebar: kratos_expressions +summary: +--- +## Introduction + +`EntityMin` finds the smallest component of each entity. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. The result is always a scalar expression. + +

$$ EntityMin\left(\underline{\mathbf{u}}\right) = \left\lbrace v_i | \quad v_i = \min_{j\in\left[0, N\right)} {u_{ij}} \quad \forall i\in\left[0, M\right)\right\rbrace$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +min_nodal_expression = Kratos.Expression.Utils.EntityMin(nodal_expression) + +# now write it to PRESSURE for checking. +Kratos.Expression.VariableExpressionIO.Write(min_nodal_expression, Kratos.PRESSURE, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + pressure = node.GetValue(Kratos.PRESSURE) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], pressure = {pressure}") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 508605 +node_id: 1, velocity=[-1.0, -2.0, -3.0], pressure = -3.0 +node_id: 2, velocity=[-4.0, -5.0, -6.0], pressure = -6.0 +node_id: 3, velocity=[-7.0, -8.0, -9.0], pressure = -9.0 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/EntitySum.md b/docs/pages/Kratos/Expressions/Utilities/EntitySum.md new file mode 100644 index 000000000000..78ebdc11a76d --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/EntitySum.md @@ -0,0 +1,62 @@ +--- +title: EntitySum +keywords: +tags: [entity sum, sum, expressions] +sidebar: kratos_expressions +summary: +--- +## Introduction + +`EntitySum` computes the sum of the components of each entity. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. The result is always a scalar expression. + +

$$ EntitySum\left(\underline{\mathbf{u}}\right) = \left\lbrace v_i | \quad v_i = \sum_{j\in\left[0, N\right)} {u_{ij}} \quad \forall i\in\left[0, M\right)\right\rbrace$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +min_nodal_expression = Kratos.Expression.Utils.EntitySum(nodal_expression) + +# now write it to PRESSURE for checking. +Kratos.Expression.VariableExpressionIO.Write(min_nodal_expression, Kratos.PRESSURE, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + pressure = node.GetValue(Kratos.PRESSURE) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], pressure = {pressure}") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 511541 +node_id: 1, velocity=[-1.0, -2.0, -3.0], pressure = -6.0 +node_id: 2, velocity=[-4.0, -5.0, -6.0], pressure = -15.0 +node_id: 3, velocity=[-7.0, -8.0, -9.0], pressure = -24.0 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/InnerProduct.md b/docs/pages/Kratos/Expressions/Utilities/InnerProduct.md new file mode 100644 index 000000000000..f12d4dea0798 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/InnerProduct.md @@ -0,0 +1,53 @@ +--- +title: InnerProduct +keywords: +tags: [inner product, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction +`InnerProduct `computes component wise inner product between two expressions. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. The second input expression is given by $$\underline{\mathbf{v}} = \left\lbrace v_{ij} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. + +**Both expressions should have the same shape.** + +

$$ InnerProduct\left(\underline{\mathbf{u}}, \underline{\mathbf{v}}\right) = \sum_{(i,j)\in\left[0, M\right)\times\left[0,N\right)}u_{ij} \times v_{ij}$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +print(Kratos.Expression.Utils.InnerProduct(nodal_expression, nodal_expression)) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 513031 +285.0 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/NormInf.md b/docs/pages/Kratos/Expressions/Utilities/NormInf.md new file mode 100644 index 000000000000..8867e482e53a --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/NormInf.md @@ -0,0 +1,51 @@ +--- +title: NormInf +keywords: +tags: [inf norm, expressions] +sidebar: kratos_expressions +summary: +--- +## Introduction +`NormInf` computes component wise inf norm in expressions. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. + +

$$ NormInf\left(\underline{\mathbf{u}}\right) = \max_{(i,j)\in\left[0, M\right)\times\left[0,N\right)} \left|u_{ij}\right|$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +print(Kratos.Expression.Utils.NormInf(nodal_expression)) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 514980 +9.0 +``` + diff --git a/docs/pages/Kratos/Expressions/Utilities/NormL2.md b/docs/pages/Kratos/Expressions/Utilities/NormL2.md new file mode 100644 index 000000000000..33b5eb752e73 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/NormL2.md @@ -0,0 +1,50 @@ +--- +title: NormL2 +keywords: +tags: [l2 norm, expressions] +sidebar: kratos_expressions +summary: +--- +## Introduction +`NormL2` computes component wise L2 norm in expressions. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. + +

$$ NormL2\left(\underline{\mathbf{u}}\right) = \sqrt{\sum_{(i,j)\in\left[0, M\right)\times\left[0,N\right)} {u_{ij}^2}}$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +print(Kratos.Expression.Utils.NormL2(nodal_expression)) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 516520 +16.881943016134134 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/NormP.md b/docs/pages/Kratos/Expressions/Utilities/NormP.md new file mode 100644 index 000000000000..4a263846596e --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/NormP.md @@ -0,0 +1,49 @@ +--- +title: NormP +keywords: +tags: [p norm, expressions] +sidebar: kratos_expressions +summary: +--- +## Introduction +`NormP` computes component wise p norm in expressions. Assume the input expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. + +

$$ NormP\left(\underline{\mathbf{u}}, P\right) = \left({\sum_{(i,j)\in\left[0, M\right)\times\left[0,N\right)} {\left|u_{ij}\right|^P}}\right)^{1/P}$$

+## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +print(Kratos.Expression.Utils.NormP(nodal_expression, 3)) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 517572 +12.651489979526238 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Pow.md b/docs/pages/Kratos/Expressions/Utilities/Pow.md new file mode 100644 index 000000000000..4e07361c77a9 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Pow.md @@ -0,0 +1,131 @@ +--- +title: Pow +keywords: +tags: [pow, expression] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +`Pow` raises value of each component to the specified power given by either a floating value or as an expression. +1. If it is raised to power by a scalar, then all the components are raised to that power. +2. If it is raised to power by an expression and that expression has the same shape as the first expression, then each component of the first expression is raised to power by the second expression's same component. +3. If it is raised to power by an expression and that expression has shape of a scalar expression, then each component of the first expression is raised to power by the second expression's entity value. + +Assume the first expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. Following equations illustrate the formulations of the resulting expression for each case. + +Case 1: + +

$$ Pow\left(\underline{\mathbf{u}}, P\right) = \left\lbrace u_{ij}^P, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +Case 2: + +The expression with power (i.e. second expression) is given by $$\underline{\mathbf{P}} = \left\lbrace p_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ +

$$ Pow\left(\underline{\mathbf{u}}, \underline{\mathbf{P}}\right) = \left\lbrace u_{ij}^{p_{ij}} | \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +Case 3: + +The expression with power (i.e. second expression) is given by $$\underline{\mathbf{P}} = \left\lbrace p_{i}, \forall i\in\left[0, M\right)\right\rbrace$$ +

$$ Pow\left(\underline{\mathbf{u}}, \underline{\mathbf{P}}\right) = \left\lbrace u_{ij}^{p_{i}}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +## Use cases + +### Using to raise to power +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +abs_nodal_expression = Kratos.Expression.Utils.Pow(nodal_expression, 3) + +# now write the absolute value for checking to the ACCELERATION +Kratos.Expression.VariableExpressionIO.Write(abs_nodal_expression, Kratos.ACCELERATION, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + acceleration = node.GetValue(Kratos.ACCELERATION) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], acceleration = [{acceleration[0]}, {acceleration[1]}, {acceleration[2]}]") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 525614 +node_id: 1, velocity=[-1.0, -2.0, -3.0], acceleration = [-1.0, -8.0, -27.0] +node_id: 2, velocity=[-4.0, -5.0, -6.0], acceleration = [-64.0, -125.0, -216.0] +node_id: 3, velocity=[-7.0, -8.0, -9.0], acceleration = [-343.0, -512.0, -729.0] +``` +### Using to compute entity wise L2 norm +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +norm_l2_nodal_expression = Kratos.Expression.Utils.Pow(Kratos.Expression.Utils.EntitySum(Kratos.Expression.Utils.Pow(nodal_expression, 2)), 0.5) + +# now write the entity wise L2 norm scalar value for checking to the PRESSURE +Kratos.Expression.VariableExpressionIO.Write(norm_l2_nodal_expression, Kratos.PRESSURE, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + pressure = node.GetValue(Kratos.PRESSURE) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], pressure = {pressure}") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 525646 +node_id: 1, velocity=[-1.0, -2.0, -3.0], pressure = 3.7416573867739413 +node_id: 2, velocity=[-4.0, -5.0, -6.0], pressure = 8.774964387392123 +node_id: 3, velocity=[-7.0, -8.0, -9.0], pressure = 13.92838827718412 +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Reshape.md b/docs/pages/Kratos/Expressions/Utilities/Reshape.md new file mode 100644 index 000000000000..9bdfc18844dc --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Reshape.md @@ -0,0 +1,67 @@ +--- +title: Reshape +keywords: +tags: [reshape, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction +`Reshape` is used to reshape any expression to another new shape. **The total number of components in the new shape should be same as the original shape's total number of components.** + +## Use case +```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 and PRESSURE of each node +node_1.SetValue(Kratos.VELOCITY, Kratos.Array3([4,5,-1])) +node_2.SetValue(Kratos.VELOCITY, Kratos.Array3([6,7,-1])) +node_3.SetValue(Kratos.VELOCITY, Kratos.Array3([8,9,-1])) +node_1.SetValue(Kratos.PRESSURE, 1) +node_2.SetValue(Kratos.PRESSURE, 2) +node_3.SetValue(Kratos.PRESSURE, 3) + +# create expressions +u_exp = Kratos.Expression.NodalExpression(model_part) +p_exp = Kratos.Expression.NodalExpression(model_part) + +# read data in to expressions +Kratos.Expression.VariableExpressionIO.Read(u_exp, Kratos.VELOCITY, False) +Kratos.Expression.VariableExpressionIO.Read(p_exp, Kratos.PRESSURE, False) + +# now combine +combined_exp = Kratos.Expression.Utils.Comb([p_exp, u_exp]) + +# now reshape +reshaped_exp = Kratos.Expression.Utils.Reshape(combined_exp, [2, 2]) + +print(reshaped_exp.Evaluate()) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 528742 +[[[ 1. 4.] + [ 5. -1.]] + + [[ 2. 6.] + [ 7. -1.]] + + [[ 3. 8.] + [ 9. -1.]]] +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Scale.md b/docs/pages/Kratos/Expressions/Utilities/Scale.md new file mode 100644 index 000000000000..ffedee0e9dd5 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Scale.md @@ -0,0 +1,79 @@ +--- +title: Scale +keywords: +tags: [scale, expression] +sidebar: kratos_expressions +summary: +--- + +## Introduction + +`Scale` scales value of each component to the specified value given by either a floating value or as an expression. +1. If it is scaled by a floating value, then all the components are scaled with the same. +2. If it is scaled by an expression and that expression has the same shape as the first expression, then each component of the first expression is scaled by the second expression's corresponding same component value. +3. If it is scaled by an expression and that expression has shape of a scalar expression, then each component of the first expression is scaled by the second expression's entity value. + +Assume the first expression is given by $$\underline{\mathbf{u}} = \left\lbrace u_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ where the $$i^{th}$$ entity's $$j^{th}$$ component is represented by $$u_{ij}$$ with $$i\in \left[0, M\right)$$ for each entity and $$j\in \left[0, N\right)$$ for each component in each entity. Following equations illustrate the formulations of the resulting expression. + +Case 1: +

$$ Scale\left(\underline{\mathbf{u}}, P\right) = \left\lbrace u_{ij}\times P, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +Case 2: + +The expression with scaling (i.e. second expression) is given by $$\underline{\mathbf{P}} = \left\lbrace p_{ij}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$ +

$$ Scale\left(\underline{\mathbf{u}}, \underline{\mathbf{P}}\right) = \left\lbrace u_{ij}\times{p_{ij}}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +Case 3: + +The expression with scaling (i.e. second expression) is given by $$\underline{\mathbf{P}} = \left\lbrace p_{i}, \forall i\in\left[0, M\right)\right\rbrace$$ +

$$ Scale\left(\underline{\mathbf{u}}, \underline{\mathbf{P}}\right) = \left\lbrace u_{ij}\times{p_{i}}, \forall (i,j)\in\left[0, M\right)\times\left[0, N\right)\right\rbrace$$

+ +## Use cases +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read the VELOCITY from non-historical nodal container +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +abs_nodal_expression = Kratos.Expression.Utils.Scale(nodal_expression, 3) + +# now write the absolute value for checking to the ACCELERATION +Kratos.Expression.VariableExpressionIO.Write(abs_nodal_expression, Kratos.ACCELERATION, False) + +# now printing +for node in model_part.Nodes: + velocity = node.GetValue(Kratos.VELOCITY) + acceleration = node.GetValue(Kratos.ACCELERATION) + print(f"node_id: {node.Id}, velocity=[{velocity[0]}, {velocity[1]}, {velocity[2]}], acceleration = [{acceleration[0]}, {acceleration[1]}, {acceleration[2]}]") +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 534910 +node_id: 1, velocity=[-1.0, -2.0, -3.0], acceleration = [-3.0, -6.0, -9.0] +node_id: 2, velocity=[-4.0, -5.0, -6.0], acceleration = [-12.0, -15.0, -18.0] +node_id: 3, velocity=[-7.0, -8.0, -9.0], acceleration = [-21.0, -24.0, -27.0] +``` diff --git a/docs/pages/Kratos/Expressions/Utilities/Slice.md b/docs/pages/Kratos/Expressions/Utilities/Slice.md new file mode 100644 index 000000000000..0ceb30fab586 --- /dev/null +++ b/docs/pages/Kratos/Expressions/Utilities/Slice.md @@ -0,0 +1,68 @@ +--- +title: Slice +keywords: +tags: [slice, expressions] +sidebar: kratos_expressions +summary: +--- + +## Introduction +`Slice` method slices existing expression to expressions having a new shape with some sub components from the original expression. +``` +Assume an @ref Expression of shape [3] and 3 entities with +the following data in the flattened representation: +@code +data = [1, 2, 3, 4, 5, 6, 7, 8, 9] + <- 1 -> <- 2 -> <- 3 -> +Data for entity 1 is represented with <-1->. + +Let Offset = 1 and Stride = 2. The resulting sliced expression +then represents the following data: + +output_data = [2, 3, 5, 6, 8, 9] +output container shape = [2] = equal to Stride. +``` + +## Use case +```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 the nodal expression +nodal_expression = Kratos.Expression.NodalExpression(model_part) + +# read in the expression +Kratos.Expression.VariableExpressionIO.Read(nodal_expression, Kratos.VELOCITY, False) + +# slice +sliced_exp = Kratos.Expression.Utils.Slice(nodal_expression, 1, 2) + +print(sliced_exp.Evaluate()) +``` + +Expected output: +```console + | / | + ' / __| _` | __| _ \ __| + . \ | ( | | ( |\__ \ +_|\_\_| \__,_|\__|\___/ ____/ + Multi-Physics 9.4."3"-docs/add_python_processing_locally-eb00abccc7-FullDebug-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. +Process Id: 540110 +[[2. 3.] + [5. 6.] + [8. 9.]] +``` diff --git a/docs/pages/Kratos/Expressions/menu_info.json b/docs/pages/Kratos/Expressions/menu_info.json new file mode 100644 index 000000000000..7b519796c1d0 --- /dev/null +++ b/docs/pages/Kratos/Expressions/menu_info.json @@ -0,0 +1,13 @@ +{ + "side_bar_name": "kratos_expressions", + "landing_page": "General/Overview.md", + "additional_menu_options": { + "product": "Expressions", + "title": "sidebar" + }, + "custom_entries": [ + "General", + "Utilities", + "IOs" + ] +} \ No newline at end of file diff --git a/docs/scripts/build_site.sh b/docs/scripts/build_site.sh index 80bde8859032..db8ca43b97ee 100644 --- a/docs/scripts/build_site.sh +++ b/docs/scripts/build_site.sh @@ -15,13 +15,16 @@ fi cp -r ../pages ../_site/Page_files cp ../_config.yml ../_site/Page_files -if [ ! -d "../_site/Page_files/_data" ]; then +if [ ! -d "../_site/Page_files/_data" ] || [ "$1" == "build_menus" ]; then cd .. python3 process_pages.py -t local cd scripts fi if [ -d "../_data" ]; then + if [ -d ../_site/Page_files/_data ]; then + rm -r ../_site/Page_files/_data + fi mv ../_data ../_site/Page_files/_data fi