KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
expression_io_utils.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Suneth Warnakulasuriya
11 //
12 
13 #pragma once
14 
15 // System incldues
16 #include <algorithm>
17 #include <type_traits>
18 #include <variant>
19 
20 // Project includes
23 #include "expression/traits.h"
25 #include "includes/communicator.h"
27 #include "includes/mesh.h"
32 
33 namespace Kratos {
34 
36 {
37 public:
40 
41  template <class TContainerType, class TContainerDataIO, class TVariableType>
43  const TContainerType& rContainer,
44  TVariableType pVariable,
45  const DataCommunicator& rDataCommunicator)
46  {
48 
49  const IndexType number_of_entities = rContainer.size();
50 
51  return std::visit([&rContainer, &rDataCommunicator, number_of_entities](auto pVariable) {
52  using data_type = typename std::remove_const_t<std::remove_pointer_t<decltype(pVariable)>>::Type;
53  using raw_data_type = std::conditional_t<std::is_same_v<data_type, int>, int, double>;
54 
55  // first get the shape correctly
56  std::vector<int> shape_info;
57  if (number_of_entities != 0) {
58  // initialize the shape with the first entity value
59  // required for dynamic data types such as Vector and Matrix
60  VariableExpressionDataIO<data_type> variable_flatten_data_io(TContainerDataIO::GetValue(*rContainer.begin(), *pVariable));
61  const auto& shape = variable_flatten_data_io.GetItemShape();
62  shape_info.resize(shape.size() + 1, number_of_entities);
63  std::transform(shape.begin(), shape.end(), shape_info.begin() + 1, [](const auto v) -> int { return v; });
64  } else {
65  shape_info.resize(1, number_of_entities);
66  }
67 
68  // now communicate the shape
69  const auto& r_shapes_info_in_ranks = rDataCommunicator.AllGatherv(shape_info);
70 
71  // get the shape
72  std::vector<IndexType> shape;
73  for (const auto& r_shape_info_in_rank : r_shapes_info_in_ranks) {
74  if (r_shape_info_in_rank[0] != 0) {
75  shape.resize(r_shape_info_in_rank.size() - 1);
76  std::transform(r_shape_info_in_rank.begin() + 1, r_shape_info_in_rank.end(), shape.begin(), [](const auto v) -> IndexType { return v;});
77  break;
78  }
79  }
80 
81  // remove number of entities for check
82  shape_info.erase(shape_info.begin());
83 
84  // cross check between all ranks the shape is the same
85  IndexType local_index = 0;
86  KRATOS_ERROR_IF(number_of_entities > 0 && !std::all_of(shape.begin(), shape.end(), [&local_index, &shape_info](const auto v) { return static_cast<int>(v) == shape_info[local_index++]; }))
87  << "All the ranks should have values with the same shape.\n";
88 
89  auto p_expression = LiteralFlatExpression<raw_data_type>::Create(number_of_entities, shape);
90  auto& r_expression = *p_expression;
91 
92  if (number_of_entities != 0) {
93  // initialize the shape with the first entity value
94  VariableExpressionDataIO<data_type> variable_flatten_data_io(TContainerDataIO::GetValue(*rContainer.begin(), *pVariable));
95 
96  IndexPartition<IndexType>(number_of_entities).for_each([&rContainer, &pVariable, &variable_flatten_data_io, &r_expression](const IndexType Index) {
97  const auto& values = TContainerDataIO::GetValue(*(rContainer.begin() + Index), *pVariable);
98  variable_flatten_data_io.Read(r_expression, Index, values);
99  });
100  }
101 
102  return Kratos::intrusive_ptr<Expression>(&r_expression);
103 
104  }, pVariable);
105 
106  KRATOS_CATCH("");
107  }
108 
109  template <class TContainerType, class TContainerDataIO, class TVariableType>
110  static void WriteFromExpression(
111  TContainerType& rContainer,
112  Communicator& rCommunicator,
113  const Expression& rExpression,
114  TVariableType pVariable)
115  {
116  KRATOS_TRY
117 
118  const IndexType number_of_entities = rContainer.size();
119 
120  std::visit([&, number_of_entities](auto pVariable) {
121  KRATOS_TRY
122 
123  if (number_of_entities > 0) {
124 
125  using data_type = typename std::remove_const_t<std::remove_pointer_t<decltype(pVariable)>>::Type;
126 
127  VariableExpressionDataIO<data_type> variable_flatten_data_io(rExpression.GetItemShape());
128 
129  // initialize the container variables first
130  if constexpr(std::is_same_v<TContainerType, ModelPart::NodesContainerType>) {
131  // initializes ghost nodes as for the later synchronization
132  // only, the nodal non historical values needs to be set unless
133  // they are properly initialized. Otherwise, in synchronization, the variables will
134  // not be there in the ghost nodes hence seg faults.
135 
136  // the vectors and matrices needs to be initialized in historical and non-historical
137  // data containers because they need to be initialized with the correct size for synchronization
138  if constexpr(std::is_same_v<data_type, Vector> || std::is_same_v<data_type, Matrix>) {
139  data_type dummy_value{};
140  variable_flatten_data_io.Assign(dummy_value, rExpression, 0);
141  if constexpr(std::is_same_v<TContainerDataIO, ContainerDataIO<ContainerDataIOTags::Historical>>) {
142  VariableUtils().SetVariable(*pVariable, dummy_value, rCommunicator.GhostMesh().Nodes());
143  } else if constexpr(std::is_same_v<TContainerDataIO, ContainerDataIO<ContainerDataIOTags::NonHistorical>>) {
144  VariableUtils().SetNonHistoricalVariable(*pVariable, dummy_value, rCommunicator.GhostMesh().Nodes());
145  }
146  } else {
147  // if it is a static type, then it only needs to be initialized in the non-historical container with zeros.
148  // historical container should be initialized with the default values when the container is created.
149  if constexpr(std::is_same_v<TContainerDataIO, ContainerDataIO<ContainerDataIOTags::NonHistorical>>) {
150  VariableUtils().SetNonHistoricalVariableToZero(*pVariable, rCommunicator.GhostMesh().Nodes());
151  }
152  }
153  }
154 
155  IndexPartition<IndexType>(number_of_entities).for_each(data_type{}, [&rContainer, &pVariable, &rExpression, &variable_flatten_data_io](const IndexType Index, data_type& rValue){
156  variable_flatten_data_io.Assign(rValue, rExpression, Index);
157  TContainerDataIO::SetValue(*(rContainer.begin() + Index), *pVariable, rValue);
158  });
159  }
160 
161  if constexpr(std::is_same_v<TContainerType, ModelPart::NodesContainerType>) {
162  // synchronize nodal values
163  if constexpr(std::is_same_v<TContainerDataIO, ContainerDataIO<ContainerDataIOTags::Historical>>) {
164  rCommunicator.SynchronizeVariable(*pVariable);
165  } else if constexpr(std::is_same_v<TContainerDataIO, ContainerDataIO<ContainerDataIOTags::NonHistorical>>) {
166  rCommunicator.SynchronizeNonHistoricalVariable(*pVariable);
167  }
168  }
169 
170  KRATOS_CATCH(" Variable: " + pVariable->Name())
171 
172  }, pVariable);
173 
174  KRATOS_CATCH("");
175  }
176 
178  Communicator& rCommunicator,
179  MeshType rMeshType)
180  {
181  switch (rMeshType) {
182  case MeshType::Local: {
183  return rCommunicator.LocalMesh();
184  break;
185  }
186  case MeshType::Interface: {
187  return rCommunicator.InterfaceMesh();
188  break;
189  }
190  case MeshType::Ghost: {
191  return rCommunicator.GhostMesh();
192  break;
193  }
194  default: {
195  KRATOS_ERROR << "Invalid mesh type";
196  break;
197  }
198  }
199  }
200 
202  const Communicator& rCommunicator,
203  MeshType rMeshType)
204  {
205  switch (rMeshType) {
206  case MeshType::Local: {
207  return rCommunicator.LocalMesh();
208  break;
209  }
210  case MeshType::Interface: {
211  return rCommunicator.InterfaceMesh();
212  break;
213  }
214  case MeshType::Ghost: {
215  return rCommunicator.GhostMesh();
216  break;
217  }
218  default: {
219  KRATOS_ERROR << "Invalid mesh type";
220  break;
221  }
222  }
223  }
224 
239  template<class TApplyFunctor>
241  Communicator& rCommunicator,
242  const Expression& rLocalNodesExpression,
243  TApplyFunctor&& rApplyFunctor)
244  {
245  KRATOS_TRY
246 
247  const auto& r_local_nodes = rCommunicator.LocalMesh().Nodes();
248  const auto& r_data_communicator = rCommunicator.GetDataCommunicator();
249  auto& r_ghost_nodes = rCommunicator.GhostMesh().Nodes();
250 
251  KRATOS_ERROR_IF_NOT(rLocalNodesExpression.NumberOfEntities() == r_local_nodes.size())
252  << "Local expression number of entities and local nodes size mismatch [ local nodes size = "
253  << r_local_nodes.size() << ", local expression number of entities = "
254  << rLocalNodesExpression.NumberOfEntities() << ", local expression = "
255  << rLocalNodesExpression << " ].\n";
256 
257  const IndexType number_of_ghost_nodes = r_ghost_nodes.size();
258 
259  std::vector<int> ghost_indices(number_of_ghost_nodes);
260  std::transform(r_ghost_nodes.begin(), r_ghost_nodes.end(), ghost_indices.begin(), [](const auto& rNode) { return rNode.Id(); });
261  auto gp_list = GlobalPointerUtilities::RetrieveGlobalIndexedPointers(r_local_nodes, ghost_indices, r_data_communicator);
262 
263  GlobalPointerCommunicator<ModelPart::NodeType> pointer_comm(r_data_communicator, gp_list.ptr_begin(), gp_list.ptr_end());
264 
265  const IndexType number_of_components = rLocalNodesExpression.GetItemComponentCount();
266 
267  // since pointer_comm.Apply is not OpenMP parallelized and works on ghost nodes only,
268  // we can avoid allocating values vector in each run, and allocate once and pass
269  // it as a lambda function capture. At the point of return from the lambda
270  // function, it is returned as a copy.
271  std::vector<double> values(number_of_components);
272 
273  auto values_proxy = pointer_comm.Apply(
274  [&rLocalNodesExpression, number_of_components, &r_local_nodes, &values](GlobalPointer<ModelPart::NodeType>& rGP) -> std::vector<double> {
275  const auto p_itr = r_local_nodes.find(rGP->Id());
276  if (p_itr != r_local_nodes.end()) {
277  const IndexType local_index = std::distance(r_local_nodes.begin(), p_itr);
278  const IndexType enitity_data_begin_index = local_index * number_of_components;
279  for (IndexType i = 0; i < number_of_components; ++i) {
280  values[i] = rLocalNodesExpression.Evaluate(local_index, enitity_data_begin_index, i);
281  }
282  } else {
283  KRATOS_ERROR << "The node with id " << rGP->Id() << " not found in the owning rank.";
284  }
285 
286  return values;
287  }
288  );
289 
290  IndexPartition<IndexType>(number_of_ghost_nodes).for_each([&r_ghost_nodes, &values_proxy, &rApplyFunctor, &gp_list](const IndexType Index){
291  // since ghost_indices passed to RetrieveGlobalIndexedPointers keeps the same order
292  // when returning gp_list containing global pointers list, the corresponding ghost node
293  // for proxy evaluated value can be correlated with indices.
294  auto& r_ghost_node = *(r_ghost_nodes.begin() + Index);
295  const auto& r_ghost_node_expression_evaluated_values = values_proxy.Get(gp_list(Index));
296 
297  rApplyFunctor(r_ghost_node, r_ghost_node_expression_evaluated_values);
298  });
299 
300  KRATOS_CATCH("");
301  }
302 
304 
305 };
306 
307 } // namespace VariableExpressionIOHelperUtilities
The Commmunicator class manages communication for distributed ModelPart instances.
Definition: communicator.h:67
virtual bool SynchronizeNonHistoricalVariable(Variable< int > const &rThisVariable)
Definition: communicator.cpp:407
MeshType & GhostMesh()
Returns the reference to the mesh storing all ghost entities.
Definition: communicator.cpp:251
virtual bool SynchronizeVariable(Variable< int > const &rThisVariable)
Definition: communicator.cpp:357
virtual const DataCommunicator & GetDataCommunicator() const
Definition: communicator.cpp:340
MeshType & InterfaceMesh()
Returns the reference to the mesh storing all interface entities.
Definition: communicator.cpp:257
MeshType & LocalMesh()
Returns the reference to the mesh storing all local entities.
Definition: communicator.cpp:245
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
Base class or all the expression types.
Definition: expression.h:38
IndexType size() const
Definition: expression.cpp:113
virtual const std::vector< IndexType > GetItemShape() const =0
Get the Shape of the expression.
IndexType GetItemComponentCount() const
Get the Local Size of the expression.
Definition: expression.cpp:104
IndexType NumberOfEntities() const
Get the maximum number of entities allowed for this expression.
Definition: expression.h:181
Kratos::intrusive_ptr< Expression > Pointer
Definition: expression.h:44
Definition: expression_io_utils.h:36
static ModelPart::MeshType & GetMesh(Communicator &rCommunicator, MeshType rMeshType)
Definition: expression_io_utils.h:177
static Expression::Pointer ReadToExpression(const TContainerType &rContainer, TVariableType pVariable, const DataCommunicator &rDataCommunicator)
Definition: expression_io_utils.h:42
static void WriteFromExpression(TContainerType &rContainer, Communicator &rCommunicator, const Expression &rExpression, TVariableType pVariable)
Definition: expression_io_utils.h:110
static void EvaluateExpressionOnGhostNodes(Communicator &rCommunicator, const Expression &rLocalNodesExpression, TApplyFunctor &&rApplyFunctor)
Evaluates a local expression on ghost nodes.
Definition: expression_io_utils.h:240
static const ModelPart::MeshType & GetMesh(const Communicator &rCommunicator, MeshType rMeshType)
Definition: expression_io_utils.h:201
A template class for handling communication related to global pointers.
Definition: pointer_communicator.h:178
ResultsProxy< TPointerDataType, TFunctorType > Apply(TFunctorType &&UserFunctor)
Applies a user-provided function to the global pointers and return a proxy to the results.
Definition: pointer_communicator.h:266
This class is a wrapper for a pointer to a data that is located in a different rank.
Definition: global_pointer.h:44
static GlobalPointersVector< typename TContainerType::value_type > RetrieveGlobalIndexedPointers(const TContainerType &rContainer, const std::vector< int > &rIdList, const DataCommunicator &rDataCommunicator)
Retrieve global indexed pointers from container and data communicator.
Definition: global_pointer_utilities.h:329
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
static LiteralFlatExpression< TRawDataType >::Pointer Create(const IndexType NumberOfEntities, const std::vector< IndexType > &rShape)
A specific create method is used in here to return a pointer to the LiteralFlatExpression.
Definition: literal_flat_expression.cpp:45
NodesContainerType & Nodes()
Definition: mesh.h:346
Construct class to read into expressions from templated data values and write in to templated data va...
Definition: variable_expression_data_io.h:35
void Assign(TDataType &rOutput, const Expression &rExpression, const IndexType EntityIndex) const
Evaluate the expression and assign the values to rOutput at the given index.
Definition: variable_expression_data_io.cpp:234
void Read(RawLiteralFlatExpression &rExpression, const IndexType EntityIndex, const TDataType &Value) const
Read into expression the values from given value.
Definition: variable_expression_data_io.cpp:257
const std::vector< IndexType > GetItemShape() const
Get the shape of the data type.
Definition: variable_expression_data_io.h:132
This class implements a set of auxiliar, already parallelized, methods to perform some common tasks r...
Definition: variable_utils.h:63
void SetNonHistoricalVariable(const TVarType &rVariable, const TType &Value, TContainerType &rContainer)
Sets the container value of any type of non historical variable.
Definition: variable_utils.h:790
void SetNonHistoricalVariableToZero(const Variable< TType > &rVariable, TContainerType &rContainer)
Sets the nodal value of any variable to zero.
Definition: variable_utils.h:724
void SetVariable(const TVarType &rVariable, const TDataType &rValue, NodesContainerType &rNodes, const unsigned int Step=0)
Sets the nodal value of a scalar variable.
Definition: variable_utils.h:675
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
Parameters GetValue(Parameters &rParameters, const std::string &rEntry)
Definition: add_kratos_parameters_to_python.cpp:53
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
MeshType
Definition: traits.h:19
@ Local
Definition: traits.h:20
@ Ghost
Definition: traits.h:21
@ Interface
Definition: traits.h:22
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
list values
Definition: bombardelli_test.py:42
def SetValue(entity, variable, value)
Definition: coupling_interface_data.py:256
v
Definition: generate_convection_diffusion_explicit_element.py:114
def Index()
Definition: hdf5_io_tools.py:38