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.
topology_filtering_utilities.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: Philipp Hofer, https://github.com/PhiHo-eng
11 // Erich Wehrle, https://github.com/e-dub
12 // based on original file from
13 // Baumgärtner Daniel, https://github.com/dbaumgaertner
14 // Octaviano Malfavón Farías
15 // Eric Gonzales
16 //
17 // ==============================================================================
18 
19 #if !defined(KRATOS_TOPOLOGY_FILTERING_UTILITIES_H_INCLUDED)
20 #define KRATOS_TOPOLOGY_FILTERING_UTILITIES_H_INCLUDED
21 
22 // System includes
23 
24 // External includes
25 
26 
27 // Project includes
28 
29 // Application includes
32 #include "custom_utilities/filter_function.h"
34 
35 
36 namespace Kratos
37 {
38 
41 
45 
46 
50 
54 
58 
60 
65 {
66 public:
67 
68  // Define an auxiliary structure to hold a pointer to the element of interest and a position in space to be searched for.
69  // This is needed to know the neighbours and where the element is for the filter.
70 
71  class ElementPositionItem: public Point
72  {
73  public:
74 
76 
77  ElementPositionItem(): // This Constructor is used by the tree
78  Point(),
79  mpElement()
80  {
81  }
82 
83  ElementPositionItem(array_1d<double,3> Coords, Element::Pointer pElement):
84  Point(Coords),
85  mpElement(pElement)
86  {}
87 
88  Element::Pointer GetOriginElement()
89  {
90  return mpElement; // TEST FUNCTION
91  }
92 
93 
94  private:
95  Element::Pointer mpElement;
96 
97  };
98 
101 
102  // Element declarations to be used for the Filter (Determine elements location)
106 
111 
112  // For ApplyFilter()
114  typedef ElementPositionItem::Pointer PointTypePointer;
115  typedef std::vector<PointType::Pointer> ElementPositionVector;
116  typedef std::vector<PointType::Pointer>::iterator ElementPositionIterator;
117  typedef std::vector<double> DistanceVector;
118  typedef std::vector<double>::iterator DistanceIterator;
119 
122 
125 
129 
131  TopologyFilteringUtilities( ModelPart& model_part, const double SearchRadius, const int MaxElementsAffected )
132  : mrModelPart(model_part),
133  mSearchRadius(SearchRadius),
134  mMaxElementsAffected(MaxElementsAffected)
135  {
136  }
137 
140  {
141  }
142 
143 
147 
148 
152 
153  // ---------------------------------------------------------------------------------------------------------------------------------------------
154  // --------------------------------- FILTER SENSITIVITIES -------------------------------------------------------------------------------------
155  // ---------------------------------------------------------------------------------------------------------------------------------------------
156 
158  void ApplyFilterSensitivity( char FilterType[], char FilterFunctionType[] )
159  {
160 
161  KRATOS_TRY;
162 
163  // Create object of filter function
164  FilterFunction FilterFunc(FilterFunctionType, mSearchRadius);
165 
166  // Function to Filter Sensitivities
167  if ( strcmp( FilterType , "sensitivity" ) == 0 ){
169  KRATOS_INFO("[TopOpt]") << " Sensitivity filter chosen as filter for sensitivities" << std::endl;
170 
171  if ( strcmp( FilterFunctionType , "linear" ) == 0 )
172  KRATOS_INFO("[TopOpt]") << " Linear filter kernel selected" << std::endl;
173  else
174  KRATOS_ERROR << "No valid FilterFunction selected for the simulation. Selected one: " << FilterFunctionType << std::endl;
175 
176  // IMPORTANT: Tree data structure is re-created on each loop, although this has little impact in simulation time/computation,
177  // it is recommended to declare it in the constructor of the class (i.e. would be calculated just one time)
178 
179  // Create placeholder for any element in model. We can assign the center of the element as coordinates to the placeholder
180  ElementPositionVector PositionList;
181  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin(); elem_i!=mrModelPart.ElementsEnd(); elem_i++)
182  {
183  // Find the center of the element
184  array_1d<double,3> center_coord = ZeroVector(3);
185  Geometry< Node >& geom = elem_i->GetGeometry();
186  for(unsigned int i=0; i<geom.size(); i++)
187  noalias(center_coord) += (geom[i].GetInitialPosition());
188  center_coord /= static_cast<double>(geom.size());
189 
190  // new "ElementPositionItem" for every element and assigns a pointer to the base element *it.base()
191  PointTypePointer pGP = PointTypePointer(new ElementPositionItem( center_coord, *elem_i.base() ) );
192  PositionList.push_back( pGP );
193  }
194 
195  // Creates a tree space search structure - It will use a copy of mGaussPoinList (a std::vector which contains pointers)
196  // Note that PositionList will be reordered by the tree for efficiency reasons
197  const int BucketSize = 4;
198  tree MyTree(PositionList.begin(),PositionList.end(),BucketSize);
199 
200  ElementPositionVector Results(mMaxElementsAffected);
201  std::vector<double> resulting_squared_distances(mMaxElementsAffected);
202 
203  BuiltinTimer timer_tree;
204  KRATOS_INFO("[TopOpt]") << " Filtered tree created [ spent time = " << timer_tree.ElapsedSeconds() << " ] " << std::endl;
205 
206  // Compute filtered sensitivities
207  Vector dcdx_filtered;
208  dcdx_filtered.resize(mrModelPart.NumberOfElements());
209  int i = 0;
210  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin(); elem_i!=mrModelPart.ElementsEnd(); elem_i++)
211  {
212  // Find the center of the element
213  array_1d<double,3> center_coord = ZeroVector(3);
214  Geometry< Node >& geom = elem_i->GetGeometry();
215  array_1d<double,3> disp = ZeroVector(3);
216  for(unsigned int i=0; i<geom.size(); i++)
217  noalias(center_coord) += (geom[i].GetInitialPosition());
218  center_coord /= static_cast<double>(geom.size());
219 
220  ElementPositionItem ElemPositionItem(center_coord,*elem_i.base());
221 
222  // This is broken. Bug found when using ResultingSquaredDistances, so we calculate our own distances
223  const int num_nodes_found = MyTree.SearchInRadius(ElemPositionItem,mSearchRadius,Results.begin(),resulting_squared_distances.begin(),mMaxElementsAffected);
224 
225 
226 
227  double Hxdc = 0.0;
228  double Hxdc_sum = 0;
229  double H = 0.0;
230  double H_sum = 0;
231  array_1d<double,3> elemental_distance;
232  double distance = 0.0;
233 
234  for(int ElementPositionItem_j = 0; ElementPositionItem_j < num_nodes_found; ElementPositionItem_j++)
235  {
236  // Calculate distances
237  elemental_distance = ZeroVector(3);
238  elemental_distance = *Results[ElementPositionItem_j] - center_coord;
239  distance = std::sqrt(inner_prod(elemental_distance,elemental_distance));
240 
241  // Creation of mesh independent convolution operator (weight factors)
242  H = FilterFunc.ComputeWeight(distance);
243  Hxdc = H*(Results[ElementPositionItem_j]->GetOriginElement()->GetValue(DCDX))
244  *(Results[ElementPositionItem_j]->GetOriginElement()->GetValue(X_PHYS));
245  H_sum += H;
246  Hxdc_sum += Hxdc;
247  }
248 
249  // Calculate filtered sensitivities and assign to the elements
250  dcdx_filtered[i++] = Hxdc_sum / (H_sum*std::max(0.001,elem_i->GetValue(X_PHYS)) );
251  }
252 
253  // Overwrite sensitivities with filtered sensitivities
254  i = 0;
255  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin();
256  elem_i!=mrModelPart.ElementsEnd(); elem_i++)
257  elem_i->SetValue(DCDX,dcdx_filtered[i++]);
258 
259  KRATOS_INFO("[TopOpt]") << " Filtered sensitivities calculated [ spent time = " << timer.ElapsedSeconds() << " ] " << std::endl;
260  }
261  else
262  KRATOS_ERROR << "No valid FilterType selected for the simulation. Selected one: " << FilterType << std::endl;
263 
264  KRATOS_CATCH("");
265 
266  }
267 
268  void ApplyFilterDensity( char FilterType[], char FilterFunctionType[], int Opt_iter )
269  {
270 
271  KRATOS_TRY;
272 
273  // Create object of filter function
274  FilterFunction FilterFunc(FilterFunctionType, mSearchRadius);
275 
276  // Function to Filter Sensitivities
277  if ( strcmp( FilterType , "density" ) == 0 ){
279  KRATOS_INFO("[TopOpt]") << " Density filter chosen as filter for densities" << std::endl;
280 
281  if ( strcmp( FilterFunctionType , "linear" ) == 0 )
282  KRATOS_INFO("[TopOpt]") << " Linear filter kernel selected" << std::endl;
283  else
284  KRATOS_ERROR << "No valid FilterFunction selected for the simulation. Selected one: " << FilterFunctionType << std::endl;
285 
286  // IMPORTANT: Tree data structure is re-created on each loop, although this has little impact in simulation time/computation,
287  // it is recommended to declare it in the constructor of the class (i.e. would be calculated just one time)
288 
289  // Create placeholder for any element in model. We can assign the center of the element as coordinates to the placeholder
290  ElementPositionVector PositionList;
291  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin(); elem_i!=mrModelPart.ElementsEnd(); elem_i++)
292  {
293  // Find the center of the element
294  array_1d<double,3> center_coord = ZeroVector(3);
295  Geometry< Node >& geom = elem_i->GetGeometry();
296  for(unsigned int i=0; i<geom.size(); i++)
297  noalias(center_coord) += (geom[i].GetInitialPosition());
298  center_coord /= static_cast<double>(geom.size());
299 
300  // new "ElementPositionItem" for every element and assigns a pointer to the base element *it.base()
301  PointTypePointer pGP = PointTypePointer(new ElementPositionItem( center_coord, *elem_i.base() ) );
302  PositionList.push_back( pGP );
303  }
304 
305  // Creates a tree space search structure - It will use a copy of mGaussPoinList (a std::vector which contains pointers)
306  // Note that PositionList will be reordered by the tree for efficiency reasons
307  const int BucketSize = 4;
308  tree MyTree(PositionList.begin(),PositionList.end(),BucketSize);
309 
310  ElementPositionVector Results(mMaxElementsAffected);
311  std::vector<double> resulting_squared_distances(mMaxElementsAffected);
312 
313  BuiltinTimer timer_tree;
314  KRATOS_INFO("[TopOpt]") << " Filtered tree created [ spent time = " << timer_tree.ElapsedSeconds() << " ] " << std::endl;
315 
316  // Compute filtered densities
317  Vector x_phys_filtered;
318  x_phys_filtered.resize(mrModelPart.NumberOfElements());
319  int i = 0;
320  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin(); elem_i!=mrModelPart.ElementsEnd(); elem_i++)
321  {
322  // Find the center of the element
323  array_1d<double,3> center_coord = ZeroVector(3);
324  Geometry< Node >& geom = elem_i->GetGeometry();
325  array_1d<double,3> disp = ZeroVector(3);
326  for(unsigned int i=0; i<geom.size(); i++)
327  noalias(center_coord) += (geom[i].GetInitialPosition());
328  center_coord /= static_cast<double>(geom.size());
329 
330  ElementPositionItem ElemPositionItem(center_coord,*elem_i.base());
331 
332  // This is broken. Bug found when using ResultingSquaredDistances, so we calculate our own distances
333  int num_nodes_found = 0;
334 
335  num_nodes_found = MyTree.SearchInRadius(ElemPositionItem,mSearchRadius,Results.begin(),resulting_squared_distances.begin(),mMaxElementsAffected);
336 
337 
338  double Hxdx = 0.0;
339  double Hxdx_sum = 0;
340  double H = 0.0;
341  double H_sum = 0;
342  array_1d<double,3> elemental_distance;
343  double distance = 0.0;
344  double beta_0= 1;
345  double beta_max = 150;
346  double tau = 50;
347  double nu = 0.5;
348 
349  for(int ElementPositionItem_j = 0; ElementPositionItem_j < num_nodes_found; ElementPositionItem_j++)
350  {
351  // Calculate distances
352  elemental_distance = ZeroVector(3);
353  elemental_distance = *Results[ElementPositionItem_j] - center_coord;
354  distance = std::sqrt(inner_prod(elemental_distance,elemental_distance));
355 
356  // Creation of mesh independent convolution operator (weight factors)
357  H = FilterFunc.ComputeWeight(distance);
358  Hxdx = H*(Results[ElementPositionItem_j]->GetOriginElement()->GetValue(X_PHYS));
359  H_sum += H;
360  Hxdx_sum += Hxdx;
361  }
362 
363  // Calculate filtered densities and assign to the elements
364 
365  // Heavyside Projection
366  double x_try = 0;
367  x_try = Hxdx_sum / (H_sum);
368  double beta = std::min(beta_max,beta_0*pow(2,((Opt_iter-1)/tau)));
369  x_phys_filtered[i++]= ((std::tanh(beta*nu)+std::tanh(beta*(x_try-nu)))/(std::tanh(beta*nu)+std::tanh(beta*(1-nu))));
370  }
371 
372  // Overwrite sensitivities with filtered densities
373  i = 0;
374  for(ModelPart::ElementsContainerType::iterator elem_i = mrModelPart.ElementsBegin();
375  elem_i!=mrModelPart.ElementsEnd(); elem_i++)
376  elem_i->SetValue(X_PHYS, x_phys_filtered[i++]);
377 
378  KRATOS_INFO("[TopOpt]") << " Filtered densities calculated [ spent time = " << timer.ElapsedSeconds() << " ] " << std::endl;
379  }
380  else
381  KRATOS_ERROR << "No valid FilterType selected for the simulation. Selected one: " << FilterType << std::endl;
382 
383  KRATOS_CATCH("");
384 
385  }
386 
387 
391 
392 
396 
397 
401 
403  virtual std::string Info() const
404  {
405  return "TopologyFilteringUtilities";
406  }
407 
409  virtual void PrintInfo(std::ostream& rOStream) const
410  {
411  rOStream << "TopologyFilteringUtilities";
412  }
413 
415  virtual void PrintData(std::ostream& rOStream) const
416  {
417  }
418 
419 
423 
424 
426 
427 protected:
430 
431 
435 
436 
440 
441 
445 
446 
450 
451 
455 
456 
460 
461 
463 
464 private:
467 
468 
472 
473  ModelPart& mrModelPart;
474  const double mSearchRadius;
475  const int mMaxElementsAffected;
476 
480 
481 
485 
486 
490 
491 
495 
496 
500 
502  //TopologyFilteringUtilities& operator=(TopologyFilteringUtilities const& rOther);
503 
505  //TopologyFilteringUtilities(TopologyFilteringUtilities const& rOther);
506 
507 
509 
510 }; // Class TopologyFilteringUtilities
511 
513 
516 
517 
521 
523 
524 
525 } // namespace Kratos.
526 
527 #endif /* KRATOS_TOPOLOGY_FILTERING_UTILITIES_H_INCLUDED */
Short class definition.
Definition: bucket.h:57
Definition: builtin_timer.h:26
double ElapsedSeconds() const
Definition: builtin_timer.h:40
Short class definition.
Definition: filter_function.h:37
double ComputeWeight(const Array3DType &ICoord, const Array3DType &JCoord, const double Radius) const
Definition: filter_function.cpp:63
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ElementIterator ElementsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1169
MeshType::ConditionsContainerType ConditionsContainerType
Condintions container. A vector set of Conditions with their Id's as key.
Definition: model_part.h:183
MeshType::ElementsContainerType ElementsContainerType
Element container. A vector set of Elements with their Id's as key.
Definition: model_part.h:168
SizeType NumberOfElements(IndexType ThisIndex=0) const
Definition: model_part.h:1027
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
ElementIterator ElementsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1179
MeshType::ElementIterator ElementIterator
Definition: model_part.h:174
Point class.
Definition: point.h:59
Definition: topology_filtering_utilities.h:72
ElementPositionItem()
Definition: topology_filtering_utilities.h:77
Element::Pointer GetOriginElement()
Definition: topology_filtering_utilities.h:88
ElementPositionItem(array_1d< double, 3 > Coords, Element::Pointer pElement)
Definition: topology_filtering_utilities.h:83
Solution utility to filter results.
Definition: topology_filtering_utilities.h:65
ModelPart::ConditionsContainerType ConditionsArrayType
Definition: topology_filtering_utilities.h:110
KRATOS_CLASS_POINTER_DEFINITION(TopologyFilteringUtilities)
Pointer definition of TopologyFilteringUtilities.
Tree< KDTreePartition< BucketType > > tree
Definition: topology_filtering_utilities.h:121
TopologyFilteringUtilities(ModelPart &model_part, const double SearchRadius, const int MaxElementsAffected)
Default constructor.
Definition: topology_filtering_utilities.h:131
ModelPart::NodesContainerType NodesContainerType
Definition: topology_filtering_utilities.h:107
ModelPart::ElementsContainerType ElementsArrayType
Definition: topology_filtering_utilities.h:104
Bucket< 3ul, PointType, ElementPositionVector, PointTypePointer, ElementPositionIterator, DistanceIterator > BucketType
Definition: topology_filtering_utilities.h:120
virtual std::string Info() const
Turn back information as a string.
Definition: topology_filtering_utilities.h:403
std::vector< PointType::Pointer >::iterator ElementPositionIterator
Definition: topology_filtering_utilities.h:116
ModelPart::NodeIterator NodeIterator
Definition: topology_filtering_utilities.h:109
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: topology_filtering_utilities.h:415
std::vector< double >::iterator DistanceIterator
Definition: topology_filtering_utilities.h:118
ModelPart::ElementIterator ElementIterator
Definition: topology_filtering_utilities.h:105
ElementPositionItem::Pointer PointTypePointer
Definition: topology_filtering_utilities.h:114
ModelPart::NodesContainerType NodesArrayType
Definition: topology_filtering_utilities.h:108
ElementPositionItem PointType
Definition: topology_filtering_utilities.h:113
virtual ~TopologyFilteringUtilities()
Destructor.
Definition: topology_filtering_utilities.h:139
std::vector< double > DistanceVector
Definition: topology_filtering_utilities.h:117
ModelPart::ElementsContainerType ElementsContainerType
Definition: topology_filtering_utilities.h:103
void ApplyFilterSensitivity(char FilterType[], char FilterFunctionType[])
With the calculated sensitivities, an additional filter to avoid checkerboard effects is used here.
Definition: topology_filtering_utilities.h:158
void ApplyFilterDensity(char FilterType[], char FilterFunctionType[], int Opt_iter)
Definition: topology_filtering_utilities.h:268
std::vector< PointType::Pointer > ElementPositionVector
Definition: topology_filtering_utilities.h:115
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: topology_filtering_utilities.h:409
A generic tree data structure for spatial partitioning.
Definition: tree.h:190
SizeType SearchInRadius(PointType const &ThisPoint, CoordinateType Radius, IteratorType Results, DistanceIteratorType ResultsDistances, SizeType MaxNumberOfResults)
Search for points within a given radius of a point.
Definition: tree.h:434
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_INFO(label)
Definition: logger.h:250
static double max(double a, double b)
Definition: GeometryFunctions.h:79
static double min(double a, double b)
Definition: GeometryFunctions.h:71
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
model_part
Definition: face_heat.py:14
tau
Definition: generate_convection_diffusion_explicit_element.py:115
H
Definition: generate_droplet_dynamics.py:257
nu
Definition: isotropic_damage_automatic_differentiation.py:135
integer i
Definition: TensorModule.f:17
Definition: timer.py:1