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.
simple_steady_sensitivity_builder_scheme.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 #if !defined(KRATOS_SIMPLE_STEADY_SENSITIVITY_BUILDER_SCHEME_H_INCLUDED)
14 #define KRATOS_SIMPLE_STEADY_SENSITIVITY_BUILDER_SCHEME_H_INCLUDED
15 
16 // System includes
17 #include <unordered_map>
18 
19 // External includes
20 
21 // Project includes
24 #include "includes/define.h"
26 #include "includes/model_part.h"
32 #include "utilities/openmp_utils.h"
35 
36 // Application includes
38 
39 namespace Kratos
40 {
43 
45 {
46 public:
49 
51 
53 
55 
57 
59 
60  using IndexType = std::size_t;
61 
65 
68  const IndexType Dimension,
69  const IndexType BlockSize)
71  mDimension(Dimension),
72  mBlockSize(BlockSize),
73  mRotationalTool(Dimension, mBlockSize)
74  {
76 
77  // Allocate auxiliary memory.
78  // This needs to be done in the constructor because, this scheme
79  // is used to calculate sensitivities w.r.t. element quantities
80  // and in there we don't usually pass the model part. Hence, we
81  // can not call SimpleSteadySensitivityBuilderScheme::Initialize
82  // method.
83  const int number_of_threads = ParallelUtilities::GetNumThreads();
84  mAuxVectors.resize(number_of_threads);
85  mAuxMatrices.resize(number_of_threads);
86  mRotatedSensitivityMatrices.resize(number_of_threads);
87  mSensitivityMatrices.resize(number_of_threads);
88 
89  if (Dimension == 2) {
90  this->mAddNodalRotationDerivativesMethod = &SimpleSteadySensitivityBuilderScheme::TemplatedAddNodalRotationDerivatives<2>;
91  this->mAddNodalApplySlipConditionDerivativesMethod = &SimpleSteadySensitivityBuilderScheme::TemplatedAddNodalApplySlipConditionDerivatives<2>;
92  } else if (Dimension == 3) {
93  this->mAddNodalRotationDerivativesMethod = &SimpleSteadySensitivityBuilderScheme::TemplatedAddNodalRotationDerivatives<3>;
94  this->mAddNodalApplySlipConditionDerivativesMethod = &SimpleSteadySensitivityBuilderScheme::TemplatedAddNodalApplySlipConditionDerivatives<3>;
95  } else {
96  KRATOS_ERROR << "Unsupported dimensionality requested. Only 2D and 3D "
97  "supported. [ Dimension = "
98  << Dimension << " ].\n";
99  }
100 
101  KRATOS_INFO(this->Info()) << this->Info() << " created [ Dimensionality = " << mDimension << ", BlockSize = " << mBlockSize << " ].\n";
102 
103  KRATOS_CATCH("");
104  }
105 
108 
112 
114  ModelPart& rModelPart,
115  ModelPart& rSensitivityModelPart,
116  AdjointResponseFunction& rResponseFunction) override
117  {
118  KRATOS_TRY
119 
120  if (!mIsNodalNormalShapeDerivativesComputed) {
121  mIsNodalNormalShapeDerivativesComputed = true;
122 
123  // Find nodal neighbors for conditions
125  rModelPart,
126  NEIGHBOUR_CONDITION_NODES);
127  neighbor_process.Execute();
128  mNodalNeighboursMap = neighbor_process.GetNeighbourIds(rModelPart.Nodes());
129 
130  // Assign condition normal derivatives to corresponding nodes
131  // NORMAL_SHAPE_DERIVATIVE on conditions should already be available before
132  // executing the following command. (This is done in adjoint_vmsmonolithic_solver.py)
133  SensitivityUtilities::AssignEntityDerivativesToNodes<ModelPart::ConditionsContainerType>(
134  rModelPart, mDimension, NORMAL_SHAPE_DERIVATIVE,
135  mNodalNeighboursMap, 1.0 / mDimension, SLIP);
136  }
137 
138  BaseType::InitializeSolutionStep(rModelPart, rSensitivityModelPart, rResponseFunction);
139 
140  KRATOS_CATCH("");
141  }
142 
161  ElementType& rCurrentElement,
162  AdjointResponseFunction& rResponseFunction,
163  Vector& rSensitivity,
164  GlobalPointersVector<NodeType>& rGPSensitivityVector,
165  const Variable<double>& rVariable,
166  const ProcessInfo& rCurrentProcessInfo) override
167  {
168  CalculateLocalSensitivityAndGlobalPointersVector(
169  rCurrentElement, rResponseFunction, rSensitivity,
170  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
171  }
172 
191  ElementType& rCurrentElement,
192  AdjointResponseFunction& rResponseFunction,
193  Vector& rSensitivity,
194  GlobalPointersVector<ElementType>& rGPSensitivityVector,
195  const Variable<double>& rVariable,
196  const ProcessInfo& rCurrentProcessInfo) override
197  {
198  CalculateLocalSensitivityAndGlobalPointersVector(
199  rCurrentElement, rResponseFunction, rSensitivity,
200  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
201  }
202 
221  ConditionType& rCurrentCondition,
222  AdjointResponseFunction& rResponseFunction,
223  Vector& rSensitivity,
224  GlobalPointersVector<NodeType>& rGPSensitivityVector,
225  const Variable<double>& rVariable,
226  const ProcessInfo& rCurrentProcessInfo) override
227  {
228  CalculateLocalSensitivityAndGlobalPointersVector(
229  rCurrentCondition, rResponseFunction, rSensitivity,
230  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
231  }
232 
251  ConditionType& rCurrentCondition,
252  AdjointResponseFunction& rResponseFunction,
253  Vector& rSensitivity,
254  GlobalPointersVector<ConditionType>& rGPSensitivityVector,
255  const Variable<double>& rVariable,
256  const ProcessInfo& rCurrentProcessInfo) override
257  {
258  CalculateLocalSensitivityAndGlobalPointersVector(
259  rCurrentCondition, rResponseFunction, rSensitivity,
260  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
261  }
262 
281  ElementType& rCurrentElement,
282  AdjointResponseFunction& rResponseFunction,
283  Vector& rSensitivity,
284  GlobalPointersVector<NodeType>& rGPSensitivityVector,
285  const Variable<array_1d<double, 3>>& rVariable,
286  const ProcessInfo& rCurrentProcessInfo) override
287  {
288  CalculateLocalSensitivityAndGlobalPointersVector(
289  rCurrentElement, rResponseFunction, rSensitivity,
290  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
291  }
292 
311  ElementType& rCurrentElement,
312  AdjointResponseFunction& rResponseFunction,
313  Vector& rSensitivity,
314  GlobalPointersVector<ElementType>& rGPSensitivityVector,
315  const Variable<array_1d<double, 3>>& rVariable,
316  const ProcessInfo& rCurrentProcessInfo) override
317  {
318  CalculateLocalSensitivityAndGlobalPointersVector(
319  rCurrentElement, rResponseFunction, rSensitivity,
320  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
321  }
322 
341  ConditionType& rCurrentCondition,
342  AdjointResponseFunction& rResponseFunction,
343  Vector& rSensitivity,
344  GlobalPointersVector<NodeType>& rGPSensitivityVector,
345  const Variable<array_1d<double, 3>>& rVariable,
346  const ProcessInfo& rCurrentProcessInfo) override
347  {
348  CalculateLocalSensitivityAndGlobalPointersVector(
349  rCurrentCondition, rResponseFunction, rSensitivity,
350  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
351  }
352 
371  ConditionType& rCurrentCondition,
372  AdjointResponseFunction& rResponseFunction,
373  Vector& rSensitivity,
374  GlobalPointersVector<ConditionType>& rGPSensitivityVector,
375  const Variable<array_1d<double, 3>>& rVariable,
376  const ProcessInfo& rCurrentProcessInfo) override
377  {
378  CalculateLocalSensitivityAndGlobalPointersVector(
379  rCurrentCondition, rResponseFunction, rSensitivity,
380  rGPSensitivityVector, rVariable, rCurrentProcessInfo);
381  }
382 
384  ElementType& rElement,
385  Vector& rAdjointValues,
386  Matrix& rOutput,
387  GlobalPointersVector<NodeType>& rGPSensitivityVector,
388  const Variable<array_1d<double, 3>>& rVariable,
389  const ProcessInfo& rCurrentProcessInfo)
390  {
391  const auto k = OpenMPUtils::ThisThread();
392  CalculateResidualSensitivityMatrix<ElementType, array_1d<double, 3>>(
393  rElement, rAdjointValues, mSensitivityMatrices[k], rOutput, rGPSensitivityVector, rVariable,
394  rCurrentProcessInfo);
395  }
396 
398  ConditionType& rCondition,
399  Vector& rAdjointValues,
400  Matrix& rOutput,
401  GlobalPointersVector<NodeType>& rGPSensitivityVector,
402  const Variable<array_1d<double, 3>>& rVariable,
403  const ProcessInfo& rCurrentProcessInfo)
404  {
405  const auto k = OpenMPUtils::ThisThread();
406  CalculateResidualSensitivityMatrix<ConditionType, array_1d<double, 3>>(
407  rCondition, rAdjointValues, mSensitivityMatrices[k], rOutput, rGPSensitivityVector, rVariable,
408  rCurrentProcessInfo);
409  }
410 
411  void Clear() override
412  {
413  BaseType::Clear();
414  mAuxVectors.clear();
415  mAuxMatrices.clear();
416  mRotatedSensitivityMatrices.clear();
417  mSensitivityMatrices.clear();
418  }
419 
423 
425  std::string Info() const override
426  {
427  return "SimpleSteadySensitivityBuilderScheme";
428  }
429 
431 
432 protected:
435 
436  virtual void CalculateLHSAndRHS(
437  ElementType& rElement,
438  Matrix& rLHS,
439  Vector& rRHS,
440  const ProcessInfo& rProcessInfo)
441  {
442  // following calls uses the same method calls as in the primal scheme to be consistent
443  rElement.CalculateLocalSystem(rLHS, rRHS, rProcessInfo);
444  rElement.CalculateLocalVelocityContribution(rLHS, rRHS, rProcessInfo);
445  }
446 
447  virtual void CalculateLHSAndRHS(
448  ConditionType& rCondition,
449  Matrix& rLHS,
450  Vector& rRHS,
451  const ProcessInfo& rProcessInfo)
452  {
453  // following calls uses the same method calls as in the primal scheme to be consistent
454  rCondition.CalculateLocalSystem(rLHS, rRHS, rProcessInfo);
455  rCondition.CalculateLocalVelocityContribution(rLHS, rRHS, rProcessInfo);
456  }
457 
459 
460 private:
463 
464  const IndexType mDimension;
465  const IndexType mBlockSize;
466 
467  bool mIsNodalNormalShapeDerivativesComputed = false;
468  std::vector<Matrix> mAuxMatrices;
469  std::vector<Vector> mAuxVectors;
470  std::vector<Matrix> mRotatedSensitivityMatrices;
471  std::vector<Matrix> mSensitivityMatrices;
472 
473  std::unordered_map<int, std::vector<int>> mNodalNeighboursMap;
474 
476 
477  void (SimpleSteadySensitivityBuilderScheme::*mAddNodalRotationDerivativesMethod)(
478  Matrix&,
479  const Matrix&,
480  const Vector&,
481  const IndexType,
482  const std::unordered_map<IndexType, IndexType>&,
483  const NodeType&) const;
484 
485  void (SimpleSteadySensitivityBuilderScheme::*mAddNodalApplySlipConditionDerivativesMethod)(
486  Matrix&,
487  const IndexType,
488  const std::unordered_map<IndexType, IndexType>&,
489  const NodeType&) const;
490 
494 
495  template <typename TEntityType, typename TDerivativeEntityType, typename TDataType>
496  void CalculateLocalSensitivityAndGlobalPointersVector(
497  TEntityType& rEntity,
498  AdjointResponseFunction& rResponseFunction,
499  Vector& rSensitivityVector,
500  GlobalPointersVector<TDerivativeEntityType>& rGPSensitivityVector,
501  const Variable<TDataType>& rVariable,
502  const ProcessInfo& rProcessInfo)
503  {
504  KRATOS_TRY;
505 
506  const auto k = OpenMPUtils::ThisThread();
507 
508  rEntity.CalculateSensitivityMatrix(rVariable, mSensitivityMatrices[k], rProcessInfo);
509  rEntity.GetValuesVector(mAdjointVectors[k]);
510 
511  KRATOS_ERROR_IF(mAdjointVectors[k].size() != mSensitivityMatrices[k].size2())
512  << "mAdjointVectors.size(): " << mAdjointVectors[k].size()
513  << " incompatible with mSensitivityMatrices[k].size1(): "
514  << mSensitivityMatrices[k].size2() << ". Variable: " << rVariable << std::endl;
515 
516  rResponseFunction.CalculatePartialSensitivity(
517  rEntity, rVariable, mSensitivityMatrices[k], mPartialSensitivity[k], rProcessInfo);
518 
519  KRATOS_ERROR_IF(mPartialSensitivity[k].size() != mSensitivityMatrices[k].size1())
520  << "mPartialSensitivity.size(): " << mPartialSensitivity[k].size()
521  << " incompatible with mSensitivityMatrices.size1(): "
522  << mSensitivityMatrices[k].size1() << ". Variable: " << rVariable << std::endl;
523 
524  if (rSensitivityVector.size() != mSensitivityMatrices[k].size1()) {
525  rSensitivityVector.resize(mSensitivityMatrices[k].size1(), false);
526  }
527 
528  noalias(rSensitivityVector) = prod(mSensitivityMatrices[k], mAdjointVectors[k]) + mPartialSensitivity[k];
529 
530  if (rGPSensitivityVector.size() != 1) {
531  rGPSensitivityVector.resize(1);
532  }
533 
534  rGPSensitivityVector(0) = GlobalPointer<TDerivativeEntityType>(&rEntity, mRank);
535 
536  KRATOS_CATCH("");
537  }
538 
539  template <typename TEntityType, typename TDataType>
540  void CalculateLocalSensitivityAndGlobalPointersVector(
541  TEntityType& rEntity,
542  AdjointResponseFunction& rResponseFunction,
543  Vector& rSensitivityVector,
544  GlobalPointersVector<NodeType>& rGPSensitivityVector,
545  const Variable<TDataType>& rVariable,
546  const ProcessInfo& rProcessInfo)
547  {
548  KRATOS_TRY;
549 
550  const auto k = OpenMPUtils::ThisThread();
551 
552  auto& adjoint_vector = mAdjointVectors[k];
553  auto& rotated_sensitivity_matrix = mRotatedSensitivityMatrices[k];
554  auto& sensitivity_matrix = mSensitivityMatrices[k];
555 
556  // get adjoint solution vector
557  rEntity.GetValuesVector(adjoint_vector);
558  const IndexType residuals_size = adjoint_vector.size();
559 
560  if (residuals_size != 0) {
561  this->CalculateResidualSensitivityMatrix<TEntityType, TDataType>(
562  rEntity, adjoint_vector, sensitivity_matrix, rotated_sensitivity_matrix,
563  rGPSensitivityVector, rVariable, rProcessInfo);
564 
565  if (rSensitivityVector.size() != rotated_sensitivity_matrix.size1()) {
566  rSensitivityVector.resize(rotated_sensitivity_matrix.size1(), false);
567  }
568  noalias(rSensitivityVector) = prod(rotated_sensitivity_matrix, adjoint_vector);
569 
570  // add objective derivative contributions
571  auto& objective_partial_sensitivity = mPartialSensitivity[k];
572  rResponseFunction.CalculatePartialSensitivity(
573  rEntity, rVariable, sensitivity_matrix,
574  objective_partial_sensitivity, rProcessInfo);
575 
576  KRATOS_DEBUG_ERROR_IF(objective_partial_sensitivity.size() >
577  rSensitivityVector.size())
578  << "rSensitivityVector does not have sufficient rows to add "
579  "objective partial sensitivity. [ rSensitivityVector.size() "
580  "= "
581  << rSensitivityVector.size() << ", PartialSensitivityVectorSize = "
582  << objective_partial_sensitivity.size() << " ].\n";
583 
584  // this assumes objective_partial_sensitivity also follows the same order of gps given by
585  // gp_index_map. This has to be done in this way because AdjointResponseFunction does not have
586  // an interface to pass a gp_vector.
587  // may be we can extend AdjointResponseFunction interface?
588  for (IndexType c = 0; c < objective_partial_sensitivity.size(); ++c) {
589  rSensitivityVector[c] += objective_partial_sensitivity[c];
590  }
591  }
592 
593  KRATOS_CATCH("");
594  }
595 
596  template <typename TEntityType, typename TDataType>
598  TEntityType& rEntity,
599  Vector& rAdjointValues,
600  Matrix& rEntityResidualDerivatives,
601  Matrix& rEntityRotatedResidualDerivatives,
602  GlobalPointersVector<NodeType>& rGPSensitivityVector,
603  const Variable<TDataType>& rVariable,
604  const ProcessInfo& rProcessInfo)
605  {
606  KRATOS_TRY;
607 
608  using DofsVectorType = std::vector<Dof<double>::Pointer>;
609 
610  const auto k = OpenMPUtils::ThisThread();
611 
612  auto& aux_vector = mAuxVectors[k];
613  auto& aux_matrix = mAuxMatrices[k];
614 
615  // get adjoint solution vector
616  rEntity.GetValuesVector(rAdjointValues);
617  const IndexType residuals_size = rAdjointValues.size();
618 
619  // calculate entity residual derivatives
620  rEntity.CalculateSensitivityMatrix(rVariable, rEntityResidualDerivatives, rProcessInfo);
621 
622  KRATOS_ERROR_IF(residuals_size != rEntityResidualDerivatives.size2())
623  << "mAdjointVectors.size(): " << residuals_size
624  << " incompatible with rEntityResidualDerivatives.size1(): "
625  << rEntityResidualDerivatives.size2() << ". Variable: " << rVariable << std::endl;
626 
627  // a map to store node id as key and the node order as the value
628  // dofs are used in here, because if wall distance is calculated in the condition
629  // then there will be derivative contributions coming to domain internal node as well
630  // hence, list of dofs are used in here.
631  DofsVectorType dofs;
632  rEntity.GetDofList(dofs, rProcessInfo);
633 
634  // get derivative node ids
635  std::vector<int> derivative_node_ids;
636  for (IndexType i = 0; i < dofs.size(); ++i) {
637  if (std::find(derivative_node_ids.begin(), derivative_node_ids.end(), dofs[i]->Id()) == derivative_node_ids.end()) {
638  derivative_node_ids.push_back(dofs[i]->Id());
639  }
640  }
641 
642  std::unordered_map<IndexType, IndexType> gp_index_map;
643  auto& r_geometry = rEntity.GetGeometry();
644  const IndexType number_of_nodes = r_geometry.PointsNumber();
645  const IndexType number_of_derivative_nodes = derivative_node_ids.size();
646 
647  if (rGPSensitivityVector.size() != number_of_derivative_nodes) {
648  rGPSensitivityVector.resize(number_of_derivative_nodes);
649  }
650 
651  // add geometry gps
652  for (IndexType i = 0; i < number_of_derivative_nodes; ++i) {
653  auto& r_gp = this->mGlobalPointerNodalMap[derivative_node_ids[i]];
654  rGPSensitivityVector(i) = r_gp;
655  gp_index_map[derivative_node_ids[i]] = i;
656  }
657 
658  if (rVariable == SHAPE_SENSITIVITY) {
659  KRATOS_DEBUG_ERROR_IF(number_of_derivative_nodes * mDimension != rEntityResidualDerivatives.size1())
660  << "Entity sensitivity matrix size mismatch. [ rEntityResidualDerivatives.size = ( " << rEntityResidualDerivatives.size1()
661  << ", " << rEntityResidualDerivatives.size2() << " ), required size = ( " << (number_of_derivative_nodes * mDimension)
662  << ", " << residuals_size << " ) ].\n";
663 
664  // add relevant neighbour gps
665  bool found_slip = false;
666  IndexType local_index = number_of_derivative_nodes;
667  for (IndexType i = 0; i < number_of_nodes; ++i) {
668  const auto& r_node = r_geometry[i];
669  if (r_node.Is(SLIP)) {
670  found_slip = true;
671  const auto& neighbour_gps = r_node.GetValue(NEIGHBOUR_CONDITION_NODES);
672  const auto& neighbour_ids = mNodalNeighboursMap[r_node.Id()];
673  for (IndexType i = 0; i < neighbour_ids.size(); ++i) {
674  const auto neighbour_id = neighbour_ids[i];
675  const auto p_itr = gp_index_map.find(neighbour_id);
676  if (p_itr == gp_index_map.end()) {
677  rGPSensitivityVector.push_back(neighbour_gps(i));
678  gp_index_map[neighbour_id] = local_index++;
679  }
680  }
681  }
682  }
683 
684  const IndexType derivatives_size = local_index * mDimension;
685  if (rEntityRotatedResidualDerivatives.size1() != derivatives_size || rEntityRotatedResidualDerivatives.size2() != residuals_size) {
686  rEntityRotatedResidualDerivatives.resize(derivatives_size, residuals_size, false);
687  }
688  rEntityRotatedResidualDerivatives.clear();
689 
690  if (found_slip) {
691  // calculate entity residual.
692  // following methods will throw an error in old adjoint elements/conditions since
693  // they does not support SLIP condition based primal solutions
694  this->CalculateLHSAndRHS(rEntity, aux_matrix, aux_vector, rProcessInfo);
695  }
696 
697  // add residual derivative contributions
698  for (IndexType a = 0; a < number_of_nodes; ++a) {
699  const auto& r_node = r_geometry[a];
700  const IndexType block_index = a * mBlockSize;
701  if (r_node.Is(SLIP)) {
702  AddNodalRotationDerivatives(rEntityRotatedResidualDerivatives, rEntityResidualDerivatives, aux_vector, block_index, gp_index_map, r_node);
703  AddNodalApplySlipConditionDerivatives(rEntityRotatedResidualDerivatives, block_index, gp_index_map, r_node);
704  } else {
705  AddNodalResidualDerivatives(rEntityRotatedResidualDerivatives, rEntityResidualDerivatives, block_index);
706  }
707  }
708  } else {
709  const IndexType derivatives_size = number_of_nodes * mDimension;
710  if (rEntityRotatedResidualDerivatives.size1() != derivatives_size || rEntityRotatedResidualDerivatives.size2() != residuals_size) {
711  rEntityRotatedResidualDerivatives.resize(derivatives_size, residuals_size, false);
712  }
713  noalias(rEntityRotatedResidualDerivatives) = rEntityResidualDerivatives;
714  }
715 
716  KRATOS_CATCH("");
717  }
718 
719  void AddNodalRotationDerivatives(
720  Matrix& rOutput,
721  const Matrix& rResidualDerivatives,
722  const Vector& rResiduals,
723  const IndexType NodeStartIndex,
724  const std::unordered_map<IndexType, IndexType>& rDerivativesMap,
725  const NodeType& rNode) const
726  {
727  (this->*(this->mAddNodalRotationDerivativesMethod))(rOutput, rResidualDerivatives, rResiduals, NodeStartIndex, rDerivativesMap, rNode);
728  }
729 
730  template<unsigned int TDim>
731  void TemplatedAddNodalRotationDerivatives(
732  Matrix& rOutput,
733  const Matrix& rResidualDerivatives,
734  const Vector& rResiduals,
735  const IndexType NodeStartIndex,
736  const std::unordered_map<IndexType, IndexType>& rDerivativesMap,
737  const NodeType& rNode) const
738  {
739  KRATOS_TRY
740 
741  // // get the residual relevant for rNode
742  BoundedVector<double, TDim> residual, residual_derivative, aux_vector;
743  FluidCalculationUtilities::ReadSubVector<TDim>(residual, rResiduals, NodeStartIndex);
744 
745  // get the rotation matrix relevant for rNode
746  BoundedMatrix<double, TDim, TDim> rotation_matrix;
747  mRotationalTool.LocalRotationOperatorPure(rotation_matrix, rNode);
748 
749  // add rotated residual derivative contributions
750  for (IndexType c = 0; c < rResidualDerivatives.size1(); ++c) {
751  // get the residual derivative relevant for node
752  FluidCalculationUtilities::ReadSubVector<TDim>(
753  residual_derivative, row(rResidualDerivatives, c), NodeStartIndex);
754 
755  // rotate residual derivative
756  noalias(aux_vector) = prod(rotation_matrix, residual_derivative);
757 
758  // add rotated residual derivative to local matrix
759  FluidCalculationUtilities::AddSubVector<TDim>(
760  rOutput, aux_vector, c, NodeStartIndex);
761 
762  // add rest of the equation derivatives
763  for (IndexType a = TDim; a < mBlockSize; ++a) {
764  rOutput(c, NodeStartIndex + a) +=
765  rResidualDerivatives(c, NodeStartIndex + a);
766  }
767  }
768 
769  // first add rotation matrix derivative contributions w.r.t. rNode
770  BoundedMatrix<double, TDim, TDim> rotation_matrix_derivative;
771  const int current_node_index = rDerivativesMap.find(rNode.Id())->second * TDim;
772  for (IndexType k = 0; k < TDim; ++k) {
774  rotation_matrix_derivative, 0, k, rNode);
775 
776  noalias(aux_vector) = prod(rotation_matrix_derivative, residual);
777  FluidCalculationUtilities::AddSubVector<TDim>(
778  rOutput, aux_vector, current_node_index + k, NodeStartIndex);
779  }
780 
781  // add rotation matrix derivative contributions w.r.t. rNode neighbors
782  const auto& r_neighbour_ids = mNodalNeighboursMap.find(rNode.Id())->second;
783  for (IndexType b = 0; b < r_neighbour_ids.size(); ++b) {
784  const int derivative_node_index =
785  rDerivativesMap.find(r_neighbour_ids[b])->second * TDim;
786  for (IndexType k = 0; k < TDim; ++k) {
788  rotation_matrix_derivative, b + 1, k, rNode);
789 
790  noalias(aux_vector) = prod(rotation_matrix_derivative, residual);
791  FluidCalculationUtilities::AddSubVector<TDim>(
792  rOutput, aux_vector, derivative_node_index + k, NodeStartIndex);
793  }
794  }
795 
796  KRATOS_CATCH("");
797  }
798 
799  void AddNodalApplySlipConditionDerivatives(
800  Matrix& rOutput,
801  const IndexType NodeStartIndex,
802  const std::unordered_map<IndexType, IndexType>& rDerivativesMap,
803  const NodeType& rNode) const
804  {
805  (this->*(this->mAddNodalApplySlipConditionDerivativesMethod))(rOutput, NodeStartIndex, rDerivativesMap, rNode);
806  }
807 
808  template<unsigned int TDim>
809  void TemplatedAddNodalApplySlipConditionDerivatives(
810  Matrix& rOutput,
811  const IndexType NodeStartIndex,
812  const std::unordered_map<IndexType, IndexType>& rDerivativesMap,
813  const NodeType& rNode) const
814  {
815  KRATOS_TRY
816 
817  // Apply slip condition in primal scheme makes first momentum dof
818  // fixed, making the velocity in the normal direction as rhs.
819 
820  // first clear the residual derivative
821  for (IndexType c = 0; c < rOutput.size1(); ++c) {
822  rOutput(c, NodeStartIndex) = 0.0;
823  }
824 
825  array_1d<double, TDim> effective_velocity, normal;
826  for (IndexType i = 0; i < TDim; ++i) {
827  effective_velocity[i] = rNode.FastGetSolutionStepValue(MESH_VELOCITY)[i];
828  effective_velocity[i] -= rNode.FastGetSolutionStepValue(VELOCITY)[i];
829  normal[i] = rNode.FastGetSolutionStepValue(NORMAL)[i];
830  }
831  const double normal_magnitude = norm_2(normal);
832  const Matrix& normal_shape_derivatives = rNode.GetValue(NORMAL_SHAPE_DERIVATIVE);
833 
834  // add unit normal derivative w.r.t. current node
835  const int current_node_index = rDerivativesMap.find(rNode.Id())->second * TDim;
836  for (IndexType k = 0; k < TDim; ++k) {
837  const auto& nodal_normal_derivative = row(normal_shape_derivatives, k);
838 
839  double value = 0.0;
840  value += inner_prod(nodal_normal_derivative, effective_velocity) / normal_magnitude;
841  value -= inner_prod(normal, effective_velocity) *
842  inner_prod(normal, nodal_normal_derivative) /
843  std::pow(normal_magnitude, 3);
844 
845  rOutput(current_node_index + k, NodeStartIndex) = value;
846  }
847 
848  // add unit normal derivative w.r.t. neighbour nodes
849  const auto& r_neighbour_ids = mNodalNeighboursMap.find(rNode.Id())->second;
850  for (IndexType b = 0; b < r_neighbour_ids.size(); ++b) {
851  const int derivative_node_index =
852  rDerivativesMap.find(r_neighbour_ids[b])->second * TDim;
853  for (IndexType k = 0; k < TDim; ++k) {
854  const auto& nodal_normal_derivative =
855  row(normal_shape_derivatives, (b + 1) * TDim + k);
856 
857  double value = 0.0;
858  value += inner_prod(nodal_normal_derivative, effective_velocity) / normal_magnitude;
859  value -= inner_prod(normal, effective_velocity) *
860  inner_prod(normal, nodal_normal_derivative) /
861  std::pow(normal_magnitude, 3);
862 
863  rOutput(derivative_node_index + k, NodeStartIndex) = value;
864  }
865  }
866 
867  KRATOS_CATCH("");
868  }
869 
870  void AddNodalResidualDerivatives(
871  Matrix& rOutput,
872  const Matrix& rResidualDerivatives,
873  const IndexType NodeStartIndex) const
874  {
875  KRATOS_TRY
876 
877  // add non-rotated residual derivative contributions
878  for (IndexType c = 0; c < rResidualDerivatives.size1(); ++c) {
879  for (IndexType i = 0; i < mBlockSize; ++i) {
880  rOutput(c, NodeStartIndex + i) +=
881  rResidualDerivatives(c, NodeStartIndex + i);
882  }
883  }
884 
885  KRATOS_CATCH("");
886  }
887 
889 
890 }; /* Class SimpleSteadySensitivityBuilderScheme */
891 
893 
894 } /* namespace Kratos.*/
895 
896 #endif /* KRATOS_SIMPLE_STEADY_SENSITIVITY_BUILDER_SCHEME_H_INCLUDED defined */
A base class for adjoint response functions.
Definition: adjoint_response_function.h:39
virtual void CalculatePartialSensitivity(Element &rAdjointElement, const Variable< double > &rVariable, const Matrix &rSensitivityMatrix, Vector &rSensitivityGradient, const ProcessInfo &rProcessInfo)
Calculate the partial sensitivity w.r.t. design variable.
Definition: adjoint_response_function.h:185
Base class for all Conditions.
Definition: condition.h:59
virtual void CalculateLocalVelocityContribution(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo)
Definition: condition.h:922
virtual void CalculateLocalSystem(MatrixType &rLeftHandSideMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo)
Definition: condition.h:408
Definition: coordinate_transformation_utilities.h:57
void LocalRotationOperatorPure(BoundedMatrix< double, 3, 3 > &rRot, const GeometryType::PointType &rThisPoint) const
Definition: coordinate_transformation_utilities.h:138
virtual void CalculateRotationOperatorPureShapeSensitivities(TLocalMatrixType &rRotationMatrixShapeDerivative, const std::size_t DerivativeNodeIndex, const std::size_t DerivativeDirectionIndex, const GeometryType::PointType &rThisPoint) const
Calculates rotation nodal matrix shape sensitivities.
Definition: coordinate_transformation_utilities.h:216
Base class for all Elements.
Definition: element.h:60
virtual void CalculateLocalVelocityContribution(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo)
Definition: element.h:972
virtual void CalculateLocalSystem(MatrixType &rLeftHandSideMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo)
Definition: element.h:405
Short class definition.
Definition: find_global_nodal_neighbours_for_entities_process.h:41
std::unordered_map< int, std::vector< int > > GetNeighbourIds(NodesContainerType &rNodes) const
Definition: find_global_nodal_neighbours_for_entities_process.h:99
void Execute() override
Execute method is used to execute the Process algorithms.
Definition: find_global_nodal_neighbours_for_entities_process.cpp:76
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
size_type size() const
Definition: global_pointers_vector.h:307
void resize(size_type new_dim) const
Definition: global_pointers_vector.h:366
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
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class defines the node.
Definition: node.h:65
TVariableType::Type & FastGetSolutionStepValue(const TVariableType &rThisVariable)
Definition: node.h:435
IndexType Id() const
Definition: node.h:262
TVariableType::Type & GetValue(const TVariableType &rThisVariable)
Definition: node.h:466
static int ThisThread()
Wrapper for omp_get_thread_num().
Definition: openmp_utils.h:108
static int GetNumThreads()
Returns the current number of threads.
Definition: parallel_utilities.cpp:34
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
Scheme used in the Sensitivity Builder.
Definition: sensitivity_builder_scheme.h:53
std::vector< Vector > mPartialSensitivity
Definition: sensitivity_builder_scheme.h:526
virtual void Clear()
Definition: sensitivity_builder_scheme.h:144
std::vector< Vector > mAdjointVectors
Definition: sensitivity_builder_scheme.h:525
const int mRank
Definition: sensitivity_builder_scheme.h:529
virtual void InitializeSolutionStep(ModelPart &rModelPart, ModelPart &rSensitivityModelPart, AdjointResponseFunction &rResponseFunction)
Definition: sensitivity_builder_scheme.h:120
ModelPart::ConditionType ConditionType
Definition: sensitivity_builder_scheme.h:62
ModelPart::NodeType NodeType
Definition: sensitivity_builder_scheme.h:60
ModelPart::ElementType ElementType
Definition: sensitivity_builder_scheme.h:64
std::unordered_map< int, GlobalPointer< ModelPart::NodeType > > mGlobalPointerNodalMap
Definition: sensitivity_builder_scheme.h:528
SensitivityBuilderScheme()
Constructor.
Definition: sensitivity_builder_scheme.h:71
Definition: simple_steady_sensitivity_builder_scheme.h:45
void CalculateSensitivity(ElementType &rCurrentElement, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< double > &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given element.
Definition: simple_steady_sensitivity_builder_scheme.h:160
void CalculateSensitivity(ConditionType &rCurrentCondition, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< ConditionType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given condition.
Definition: simple_steady_sensitivity_builder_scheme.h:370
virtual void CalculateLHSAndRHS(ElementType &rElement, Matrix &rLHS, Vector &rRHS, const ProcessInfo &rProcessInfo)
Definition: simple_steady_sensitivity_builder_scheme.h:436
~SimpleSteadySensitivityBuilderScheme()=default
Destructor.
KRATOS_CLASS_POINTER_DEFINITION(SimpleSteadySensitivityBuilderScheme)
std::size_t IndexType
Definition: simple_steady_sensitivity_builder_scheme.h:60
void CalculateSensitivity(ConditionType &rCurrentCondition, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given condition.
Definition: simple_steady_sensitivity_builder_scheme.h:340
virtual void CalculateLHSAndRHS(ConditionType &rCondition, Matrix &rLHS, Vector &rRHS, const ProcessInfo &rProcessInfo)
Definition: simple_steady_sensitivity_builder_scheme.h:447
void InitializeSolutionStep(ModelPart &rModelPart, ModelPart &rSensitivityModelPart, AdjointResponseFunction &rResponseFunction) override
Definition: simple_steady_sensitivity_builder_scheme.h:113
std::string Info() const override
Turn back information as a string.
Definition: simple_steady_sensitivity_builder_scheme.h:425
void CalculateResidualSensitivityMatrix(ConditionType &rCondition, Vector &rAdjointValues, Matrix &rOutput, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo)
Definition: simple_steady_sensitivity_builder_scheme.h:397
void CalculateSensitivity(ConditionType &rCurrentCondition, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< double > &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given condition.
Definition: simple_steady_sensitivity_builder_scheme.h:220
void CalculateSensitivity(ConditionType &rCurrentCondition, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< ConditionType > &rGPSensitivityVector, const Variable< double > &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given condition.
Definition: simple_steady_sensitivity_builder_scheme.h:250
SimpleSteadySensitivityBuilderScheme(const IndexType Dimension, const IndexType BlockSize)
Constructor.
Definition: simple_steady_sensitivity_builder_scheme.h:67
void CalculateSensitivity(ElementType &rCurrentElement, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< ElementType > &rGPSensitivityVector, const Variable< double > &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given element.
Definition: simple_steady_sensitivity_builder_scheme.h:190
void CalculateResidualSensitivityMatrix(ElementType &rElement, Vector &rAdjointValues, Matrix &rOutput, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo)
Definition: simple_steady_sensitivity_builder_scheme.h:383
void CalculateSensitivity(ElementType &rCurrentElement, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< ElementType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given element.
Definition: simple_steady_sensitivity_builder_scheme.h:310
void Clear() override
Definition: simple_steady_sensitivity_builder_scheme.h:411
void CalculateSensitivity(ElementType &rCurrentElement, AdjointResponseFunction &rResponseFunction, Vector &rSensitivity, GlobalPointersVector< NodeType > &rGPSensitivityVector, const Variable< array_1d< double, 3 >> &rVariable, const ProcessInfo &rCurrentProcessInfo) override
Calculates sensitivity from a given element.
Definition: simple_steady_sensitivity_builder_scheme.h:280
#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(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
#define KRATOS_INFO(label)
Definition: logger.h:250
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
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
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
dofs
Enforced auxTangentSlipNonObjective = delta_time * gap_time_derivative_non_objective....
Definition: generate_frictional_mortar_condition.py:210
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
residual
Definition: hinsberg_optimization_4.py:433
int k
Definition: quadrature.py:595
integer i
Definition: TensorModule.f:17