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.
vms_adjoint_element.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: Jordi Cotela
11 // Michael Andre
12 //
13 
14 #if !defined(KRATOS_VMS_ADJOINT_ELEMENT_H_INCLUDED)
15 #define KRATOS_VMS_ADJOINT_ELEMENT_H_INCLUDED
16 
17 // System includes
18 #include <string>
19 #include <iostream>
20 #include <cmath>
21 #include <array>
22 
23 // Project includes
24 #include "includes/define.h"
25 #include "includes/kratos_flags.h"
26 #include "includes/element.h"
28 #include "includes/cfd_variables.h"
31 #include "includes/serializer.h"
32 #include "utilities/geometry_utilities.h"
35 
36 // Application includes
39 
40 namespace Kratos {
41 
44 
47 
53 template< unsigned int TDim >
54 class KRATOS_API(FLUID_DYNAMICS_APPLICATION) VMSAdjointElement: public Element
55 {
56  class ThisExtensions : public AdjointExtensions
57  {
58  Element* mpElement;
59 
60  public:
61  explicit ThisExtensions(Element* pElement)
62  : mpElement{pElement}
63  {
64  }
65 
66  void GetFirstDerivativesVector(
67  std::size_t NodeId,
68  std::vector<IndirectScalar<double>>& rVector,
69  std::size_t Step) override
70  {
71  auto& r_node = mpElement->GetGeometry()[NodeId];
72  rVector.resize(mpElement->GetGeometry().WorkingSpaceDimension() + 1);
73  std::size_t index = 0;
74  rVector[index++] = MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_2_X, Step);
75  rVector[index++] = MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_2_Y, Step);
76  if (mpElement->GetGeometry().WorkingSpaceDimension() == 3) {
77  rVector[index++] =
78  MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_2_Z, Step);
79  }
80  rVector[index] = IndirectScalar<double>{}; // pressure
81  }
82 
83  void GetSecondDerivativesVector(
84  std::size_t NodeId,
85  std::vector<IndirectScalar<double>>& rVector,
86  std::size_t Step) override
87  {
88  auto& r_node = mpElement->GetGeometry()[NodeId];
89  rVector.resize(mpElement->GetGeometry().WorkingSpaceDimension() + 1);
90  std::size_t index = 0;
91  rVector[index++] = MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_3_X, Step);
92  rVector[index++] = MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_3_Y, Step);
93  if (mpElement->GetGeometry().WorkingSpaceDimension() == 3) {
94  rVector[index++] =
95  MakeIndirectScalar(r_node, ADJOINT_FLUID_VECTOR_3_Z, Step);
96  }
97  rVector[index] = IndirectScalar<double>{}; // pressure
98  }
99 
100  void GetAuxiliaryVector(
101  std::size_t NodeId,
102  std::vector<IndirectScalar<double>>& rVector,
103  std::size_t Step) override
104  {
105  auto& r_node = mpElement->GetGeometry()[NodeId];
106  rVector.resize(mpElement->GetGeometry().WorkingSpaceDimension() + 1);
107  std::size_t index = 0;
108  rVector[index++] =
109  MakeIndirectScalar(r_node, AUX_ADJOINT_FLUID_VECTOR_1_X, Step);
110  rVector[index++] =
111  MakeIndirectScalar(r_node, AUX_ADJOINT_FLUID_VECTOR_1_Y, Step);
112  if (mpElement->GetGeometry().WorkingSpaceDimension() == 3) {
113  rVector[index++] =
114  MakeIndirectScalar(r_node, AUX_ADJOINT_FLUID_VECTOR_1_Z, Step);
115  }
116  rVector[index] = IndirectScalar<double>{}; // pressure
117  }
118 
119  void GetFirstDerivativesVariables(std::vector<VariableData const*>& rVariables) const override
120  {
121  rVariables.resize(1);
122  rVariables[0] = &ADJOINT_FLUID_VECTOR_2;
123  }
124 
125  void GetSecondDerivativesVariables(std::vector<VariableData const*>& rVariables) const override
126  {
127  rVariables.resize(1);
128  rVariables[0] = &ADJOINT_FLUID_VECTOR_3;
129  }
130 
131  void GetAuxiliaryVariables(std::vector<VariableData const*>& rVariables) const override
132  {
133  rVariables.resize(1);
134  rVariables[0] = &AUX_ADJOINT_FLUID_VECTOR_1;
135  }
136  };
137 
138 public:
139 
142 
145 
146  constexpr static unsigned int TNumNodes = TDim + 1;
147 
148  constexpr static unsigned int TBlockSize = TDim + 1;
149 
150  constexpr static unsigned int TFluidLocalSize = TBlockSize * TNumNodes;
151 
152  constexpr static unsigned int TCoordLocalSize = TDim * TNumNodes;
153 
155 
157 
159 
161 
163 
165 
166  typedef std::array<double, TFluidLocalSize> ArrayType;
167 
169 
171 
172  typedef std::array<Dof<double>::Pointer, TFluidLocalSize> DofsArrayType;
173 
175 
176  typedef std::array<std::size_t, TFluidLocalSize> EquationIdArrayType;
177 
180 
182 
184 
188 
190  : Element(NewId)
191  {
192  }
193 
195  IndexType NewId,
196  GeometryType::Pointer pGeometry)
197  : Element(NewId, pGeometry)
198  {
199  }
200 
202  IndexType NewId,
203  GeometryType::Pointer pGeometry,
204  PropertiesType::Pointer pProperties)
205  : Element(NewId, pGeometry, pProperties)
206  {
207  }
208 
210  {}
211 
215 
216  void Initialize(const ProcessInfo& rCurrentProcessInfo) override
217  {
218  this->SetValue(ADJOINT_EXTENSIONS, Kratos::make_shared<ThisExtensions>(this));
219  }
220 
226  Element::Pointer Create(
227  IndexType NewId,
228  NodesArrayType const& ThisNodes,
229  PropertiesType::Pointer pProperties) const override
230  {
231  KRATOS_TRY
232 
233  return Kratos::make_intrusive<VMSAdjointElement<TDim>>(
234  NewId, this->GetGeometry().Create(ThisNodes), pProperties);
235 
236  KRATOS_CATCH("")
237  }
238 
239  Element::Pointer Create(
240  IndexType NewId,
241  GeometryType::Pointer pGeom,
242  PropertiesType::Pointer pProperties) const override
243  {
244  KRATOS_TRY
245 
246  return Kratos::make_intrusive<VMSAdjointElement<TDim>>(
247  NewId, pGeom, pProperties);
248 
249  KRATOS_CATCH("")
250  }
251 
257  int Check(const ProcessInfo& rProcessInfo) const override
258  {
259  KRATOS_TRY
260 
261  // Check the element id and geometry.
262  int value = Element::Check(rProcessInfo);
263 
264  // Check if the nodes have adjoint and fluid variables and adjoint dofs.
265  for (IndexType i_node = 0; i_node < this->GetGeometry().size(); ++i_node) {
266  const auto& r_node = this->GetGeometry()[i_node];
267  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ADJOINT_FLUID_VECTOR_1, r_node);
268  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ADJOINT_FLUID_VECTOR_2, r_node);
269  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ADJOINT_FLUID_VECTOR_3, r_node);
270  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ADJOINT_FLUID_SCALAR_1, r_node);
271  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY, r_node);
272  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ACCELERATION, r_node);
273  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(PRESSURE, r_node);
274 
275  KRATOS_CHECK_DOF_IN_NODE(ADJOINT_FLUID_VECTOR_1_X, r_node);
276  KRATOS_CHECK_DOF_IN_NODE(ADJOINT_FLUID_VECTOR_1_Y, r_node);
277  KRATOS_CHECK_DOF_IN_NODE(ADJOINT_FLUID_VECTOR_1_Z, r_node);
278  KRATOS_CHECK_DOF_IN_NODE(ADJOINT_FLUID_SCALAR_1, r_node);
279  }
280 
281  // For OSS: Add projection of residuals to RHS
282  if (rProcessInfo[OSS_SWITCH] == 1) {
284  << "OSS projections are not yet supported with VMS adjoints.\n";
285  }
286 
287  return value;
288 
289  KRATOS_CATCH("")
290  }
291 
294  VectorType& rValues,
295  int Step = 0) const override
296  {
298  this->GetValuesArray(values, Step);
299  if (rValues.size() != TFluidLocalSize) {
300  rValues.resize(TFluidLocalSize, false);
301  }
302  std::copy(values.begin(), values.end(), rValues.begin());
303  }
304 
306  ArrayType& rValues,
307  const int Step = 0) const
308  {
309  const auto& r_geometry = this->GetGeometry();
310  IndexType local_index = 0;
311  for (IndexType i_node = 0; i_node < TNumNodes; ++i_node) {
312  const auto& r_node = r_geometry[i_node];
313  const auto& r_velocity = r_node.FastGetSolutionStepValue(ADJOINT_FLUID_VECTOR_1, Step);
314  for (IndexType d = 0; d < TDim; ++d) {
315  rValues[local_index++] = r_velocity[d];
316  }
317  rValues[local_index++] = r_node.FastGetSolutionStepValue(ADJOINT_FLUID_SCALAR_1, Step);
318  }
319  }
320 
323  VectorType& rValues,
324  int Step = 0) const override
325  {
326  if (rValues.size() != TFluidLocalSize) {
327  rValues.resize(TFluidLocalSize, false);
328  }
329  rValues.clear();
330  }
331 
333  ArrayType& rValues,
334  int Step = 0) const
335  {
336  std::fill(rValues.begin(), rValues.end(), 0.0);
337  }
338 
341  VectorType& rValues,
342  int Step = 0) const override
343  {
345  this->GetSecondDerivativesArray(values, Step);
346  if (rValues.size() != TFluidLocalSize) {
347  rValues.resize(TFluidLocalSize, false);
348  }
349  std::copy(values.begin(), values.end(), rValues.begin());
350  }
351 
353  ArrayType& rValues,
354  int Step = 0) const
355  {
356  const auto& r_geometry = this->GetGeometry();
357  IndexType local_index = 0;
358  for (IndexType i_node = 0; i_node < TNumNodes; ++i_node) {
359  const auto& r_acceleration = r_geometry[i_node].FastGetSolutionStepValue(
360  ADJOINT_FLUID_VECTOR_3, Step);
361  for (IndexType d = 0; d < TDim; ++d) {
362  rValues[local_index++] = r_acceleration[d];
363  }
364  rValues[local_index++] = 0.0; // pressure dof
365  }
366  }
367 
369  MatrixType& rLeftHandSideMatrix,
370  VectorType& rRightHandSideVector,
371  const ProcessInfo& rCurrentProcessInfo) override
372  {
373  KRATOS_TRY
374 
375  // Check sizes and initialize matrix
376  if (rLeftHandSideMatrix.size1() != TFluidLocalSize ||
377  rLeftHandSideMatrix.size2() != TFluidLocalSize)
378  rLeftHandSideMatrix.resize(TFluidLocalSize, TFluidLocalSize, false);
379 
380  noalias(rLeftHandSideMatrix) = ZeroMatrix(TFluidLocalSize, TFluidLocalSize);
381 
382  if (rRightHandSideVector.size() != TFluidLocalSize)
383  rRightHandSideVector.resize(TFluidLocalSize, false);
384 
385  noalias(rRightHandSideVector) = ZeroVector(TFluidLocalSize);
386 
387  // Calculate RHS
388  // Calculate this element's geometric parameters
389  double gauss_weight;
392  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, gauss_weight);
393 
394  // Calculate this element's fluid properties
395  double density;
397  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
398  std::tie(density, DENSITY),
399  std::tie(body_force, BODY_FORCE));
400 
401  double coeff = density * gauss_weight;
402 
403  // Add the results to the velocity components (Local Dofs are vx, vy, [vz,] p for each node)
404  int local_index = 0;
405 
406  for (unsigned int i_node = 0; i_node < TNumNodes; ++i_node) {
407  for (unsigned int d = 0; d < TDim; ++d) {
408  rRightHandSideVector[local_index++] +=
409  coeff * N[i_node] * body_force[d];
410  }
411  ++local_index; // Skip pressure Dof
412  }
413 
414  KRATOS_CATCH("");
415  }
416 
418  MatrixType& rDampingMatrix,
419  VectorType& rRightHandSideVector,
420  const ProcessInfo& rCurrentProcessInfo) override
421  {
422  // Resize and set to zero the matrix
423  // Note that we don't clean the RHS because it will already contain body force (and stabilization) contributions
424  if (rDampingMatrix.size1() != TFluidLocalSize)
425  rDampingMatrix.resize(TFluidLocalSize, TFluidLocalSize, false);
426 
427  noalias(rDampingMatrix) = ZeroMatrix(TFluidLocalSize, TFluidLocalSize);
428 
429  const auto& r_geometry = this->GetGeometry();
430 
431  // Get this element's geometric properties
432  double gauss_weight;
436 
437  // Calculate this element's fluid properties
438  double density, viscosity;
441  r_geometry, N, std::tie(density, DENSITY),
442  std::tie(velocity, VELOCITY),
443  std::tie(mesh_velocity, MESH_VELOCITY),
444  std::tie(viscosity, VISCOSITY),
445  std::tie(body_force, BODY_FORCE));
446 
447  viscosity *= density;
448 
449  const double element_size = this->CalculateElementSize(gauss_weight);
450 
451  // Get Advective velocity
452  const array_1d<double, TDim> effective_velocity = velocity - mesh_velocity;
453 
454  // stabilization parameters
455  double tau_one, tau_two;
456  this->CalculateStabilizationParameters(tau_one, tau_two, norm_2(effective_velocity),
457  element_size, density, viscosity,
458  rCurrentProcessInfo);
459 
460  this->AddIntegrationPointVelocityContribution(
461  rDampingMatrix, rRightHandSideVector, density, viscosity,
462  effective_velocity, body_force, tau_one, tau_two, N, DN_DX, gauss_weight);
463 
464  // Now calculate an additional contribution to the residual: r -= rDampingMatrix * (u,p)
465  VectorType values = ZeroVector(TFluidLocalSize);
466  int local_index = 0;
467 
468  for (unsigned int i_node = 0; i_node < TNumNodes; ++i_node) {
469  const auto& r_node = r_geometry[i_node];
470  const auto& velocity = r_node.FastGetSolutionStepValue(VELOCITY);
471  for (unsigned int d = 0; d < TDim; ++d) {
472  values[local_index++] = velocity[d];
473  }
474  values[local_index++] = r_node.FastGetSolutionStepValue(PRESSURE);
475  }
476 
477  noalias(rRightHandSideVector) -= prod(rDampingMatrix, values);
478  }
479 
481  MatrixType& rLeftHandSideMatrix,
482  const ProcessInfo& rCurrentProcessInfo) override
483  {
484  if (rLeftHandSideMatrix.size1() != TFluidLocalSize ||
485  rLeftHandSideMatrix.size2() != TFluidLocalSize)
486  rLeftHandSideMatrix.resize(TFluidLocalSize, TFluidLocalSize, false);
487 
488  rLeftHandSideMatrix.clear();
489  }
490 
492  VectorType& rRightHandSideVector,
493  const ProcessInfo& rCurrentProcessInfo) override
494  {
495  KRATOS_TRY
496 
497  KRATOS_ERROR << "this function is not implemented.";
498 
499  KRATOS_CATCH("")
500  }
501 
520  MatrixType& rLeftHandSideMatrix,
521  const ProcessInfo& rCurrentProcessInfo) override
522  {
524  this->CalculateFirstDerivativesLHS(LHS, rCurrentProcessInfo);
525  rLeftHandSideMatrix.resize(LHS.size1(), LHS.size2());
526  noalias(rLeftHandSideMatrix) = LHS;
527  }
528 
531  const ProcessInfo& rCurrentProcessInfo)
532  {
533  this->CalculatePrimalGradientOfVMSSteadyTerm(rLeftHandSideMatrix, rCurrentProcessInfo);
534  this->AddPrimalGradientOfVMSMassTerm(rLeftHandSideMatrix, ACCELERATION,
535  -1.0, rCurrentProcessInfo);
536  rLeftHandSideMatrix = trans(rLeftHandSideMatrix); // transpose
537  }
538 
551  MatrixType& rLeftHandSideMatrix,
552  const ProcessInfo& rCurrentProcessInfo) override
553  {
555  this->CalculateSecondDerivativesLHS(LHS, rCurrentProcessInfo);
556  rLeftHandSideMatrix.resize(LHS.size1(), LHS.size2(), false);
557  noalias(rLeftHandSideMatrix) = LHS;
558  }
559 
562  const ProcessInfo& rCurrentProcessInfo)
563  {
564  this->CalculateVMSMassMatrix(rLeftHandSideMatrix, rCurrentProcessInfo);
565  rLeftHandSideMatrix = -trans(rLeftHandSideMatrix); // transpose
566  }
567 
569  MatrixType& rMassMatrix,
570  const ProcessInfo& rCurrentProcessInfo) override
571  {
572  // Resize and set to zero
573  if (rMassMatrix.size1() != TFluidLocalSize)
574  rMassMatrix.resize(TFluidLocalSize, TFluidLocalSize, false);
575 
576  rMassMatrix = ZeroMatrix(TFluidLocalSize, TFluidLocalSize);
577 
578  const auto& r_geometry = this->GetGeometry();
579 
580  // Get the element's geometric parameters
581  double Area;
584  GeometryUtils::CalculateGeometryData(r_geometry, DN_DX, N, Area);
585 
586  double density, viscosity;
587  array_1d<double, TDim> velocity, mesh_velocity;
589  r_geometry, N,
590  std::tie(density, DENSITY),
591  std::tie(velocity, VELOCITY),
592  std::tie(mesh_velocity, MESH_VELOCITY),
593  std::tie(viscosity, VISCOSITY));
594 
595  viscosity *= density;
596 
597  // Add 'classical' mass matrix (lumped)
598  double Coeff = density * Area / TNumNodes; //Optimize!
599  unsigned int DofIndex = 0;
600  for (unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
601  {
602  for (unsigned int d = 0; d < TDim; ++d)
603  {
604  rMassMatrix(DofIndex, DofIndex) += Coeff;
605  ++DofIndex;
606  }
607  ++DofIndex; // Skip pressure Dof
608  }
609 
610  // Get Advective velocity
611  const array_1d<double, TDim> effective_velocity = velocity - mesh_velocity;
612 
613  // stabilization parameters
614  const double ElemSize = this->CalculateElementSize(Area);
615  double TauOne, TauTwo;
616  this->CalculateStabilizationParameters(TauOne, TauTwo, norm_2(effective_velocity), ElemSize, density,
617  viscosity, rCurrentProcessInfo);
618 
619  // Add dynamic stabilization terms ( all terms involving a delta(u) )
620  this->AddMassStabTerms(rMassMatrix, density, effective_velocity, TauOne, N, DN_DX, Area);
621  }
622 
624  MatrixType& rDampingMatrix,
625  const ProcessInfo& rProcessInfo) override
626  {
627  KRATOS_TRY
628 
629  KRATOS_ERROR << "this function is not implemented.";
630 
631  KRATOS_CATCH("")
632  }
633 
643  const Variable<array_1d<double, 3>>& rSensitivityVariable,
644  Matrix& rOutput,
645  const ProcessInfo& rCurrentProcessInfo) override
646  {
648  this->AuxiliaryCalculateSensitivityMatrix(rSensitivityVariable, local_matrix, rCurrentProcessInfo);
649  rOutput.resize(local_matrix.size1(), local_matrix.size2(), false);
650  noalias(rOutput) = local_matrix;
651  }
652 
653 
654  void Calculate(
655  const Variable<Vector>& rVariable,
656  Vector& rOutput,
657  const ProcessInfo& rCurrentProcessInfo) override
658  {
659  KRATOS_TRY
660 
661  if (rVariable == PRIMAL_RELAXED_SECOND_DERIVATIVE_VALUES) {
662  if (rOutput.size() != TFluidLocalSize) {
663  rOutput.resize(TFluidLocalSize, false);
664  }
665 
666  const auto& r_geometry = this->GetGeometry();
667 
668  IndexType local_index = 0;
669  for (IndexType i = 0; i < TNumNodes; ++i) {
670  // VMS adjoint uses old way of getting relaxed accelration
671  // hence this also uses the old way to be consistent
672  // Eventually to be removed.
673  const auto& value = r_geometry[i].FastGetSolutionStepValue(ACCELERATION);
674  for (IndexType j = 0; j < TDim; ++j) {
675  rOutput[local_index++] = value[j];
676  }
677  // skip pressure dof
678  rOutput[local_index++] = 0.0;
679  }
680  } else {
681  KRATOS_ERROR << "Unsupported variable type is requested. [ rVariable.Name() = " << rVariable.Name() << " ].\n";
682  }
683 
684  KRATOS_CATCH("")
685  }
686 
688  DofsVectorType& rElementalDofList,
689  const ProcessInfo& rCurrentProcessInfo) const override
690  {
692  this->GetDofArray(dofs, rCurrentProcessInfo);
693  if (rElementalDofList.size() != dofs.size()) {
694  rElementalDofList.resize(dofs.size());
695  }
696  std::copy(dofs.begin(), dofs.end(), rElementalDofList.begin());
697  }
698 
700  DofsArrayType& rElementalDofList,
701  const ProcessInfo& rCurrentProcessInfo) const;
702 
704  EquationIdVectorType& rResult,
705  const ProcessInfo& rCurrentProcessInfo) const override
706  {
708  this->EquationIdArray(ids, rCurrentProcessInfo);
709  if (rResult.size() != ids.size()) {
710  rResult.resize(ids.size());
711  }
712  std::copy(ids.begin(), ids.end(), rResult.begin());
713  }
714 
716  EquationIdArrayType& rResult,
717  const ProcessInfo& rProcessInfo) const;
718 
722 
723  std::string Info() const override
724  {
725  std::stringstream buffer;
726  buffer << "VMSAdjointElement" << this->GetGeometry().WorkingSpaceDimension()
727  << "D #" << this->Id();
728  return buffer.str();
729  }
730 
731  void PrintInfo(std::ostream& rOStream) const override
732  {
733  rOStream << "VMSAdjointElement"
734  << this->GetGeometry().WorkingSpaceDimension() << "D #"
735  << this->Id() << std::endl;
736  rOStream << "Number of Nodes: " << this->GetGeometry().PointsNumber()
737  << std::endl;
738  }
739 
740  void PrintData(std::ostream& rOStream) const override
741  {
742  this->PrintInfo(rOStream);
743  rOStream << "Geometry Data: " << std::endl;
744  this->GetGeometry().PrintData(rOStream);
745  }
746 
748 
749 protected:
750 
753 
755  MatrixType& rLHSMatrix,
756  const double Density,
757  const array_1d<double, TDim> & rAdvVel,
758  const double TauOne,
759  const array_1d<double, TNumNodes>& rShapeFunc,
760  const BoundedMatrix<double, TNumNodes, TDim>& rShapeDeriv,
761  const double Weight)
762  {
763  const unsigned int BlockSize = TDim + 1;
764 
765  double Coef = Weight * TauOne;
766  unsigned int FirstRow(0), FirstCol(0);
767  double K; // Temporary results
768 
769  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
770  const array_1d<double, TNumNodes> AGradN = prod(rShapeDeriv, rAdvVel);
771 
772  // Note: Dof order is (vx,vy,[vz,]p) for each node
773  for (unsigned int i = 0; i < TNumNodes; ++i)
774  {
775  // Loop over columns
776  for (unsigned int j = 0; j < TNumNodes; ++j)
777  {
778  // Delta(u) * TauOne * [ AdvVel * Grad(v) ] in velocity block
779  K = Coef * Density * AGradN[i] * Density * rShapeFunc[j];
780 
781  for (unsigned int d = 0; d < TDim; ++d) // iterate over dimensions for velocity Dofs in this node combination
782  {
783  rLHSMatrix(FirstRow + d, FirstCol + d) += K;
784  // Delta(u) * TauOne * Grad(q) in q * Div(u) block
785  rLHSMatrix(FirstRow + TDim, FirstCol + d) += Coef * Density * rShapeDeriv(i, d) * rShapeFunc[j];
786  }
787  // Update column index
788  FirstCol += BlockSize;
789  }
790  // Update matrix indices
791  FirstRow += BlockSize;
792  FirstCol = 0;
793  }
794  }
795 
797  MatrixType& rDampingMatrix,
798  VectorType& rDampRHS,
799  const double Density,
800  const double Viscosity,
801  const array_1d<double, TDim>& rAdvVel,
802  const array_1d<double, TDim>& rBodyForce,
803  const double TauOne,
804  const double TauTwo,
805  const array_1d<double, TNumNodes>& rShapeFunc,
806  const BoundedMatrix<double, TNumNodes, TDim>& rShapeDeriv,
807  const double Weight)
808  {
809  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
810  const array_1d<double, TNumNodes> AGradN = prod(rShapeDeriv, rAdvVel);
811 
812  // Build the local matrix and RHS
813  unsigned int FirstRow(0),
814  FirstCol(0); // position of the first term of the local matrix that corresponds to each node combination
815  double K, G, PDivV, L, qF; // Temporary results
816 
817  array_1d<double, TDim> BodyForce = rBodyForce * Density;
818 
819  for (unsigned int i = 0; i < TNumNodes; ++i) // iterate over rows
820  {
821  for (unsigned int j = 0; j < TNumNodes; ++j) // iterate over columns
822  {
823  // Calculate the part of the contributions that is constant for each node combination
824 
825  // Velocity block
826  K = Density * rShapeFunc[i] * AGradN[j]; // Convective term: v * ( a * Grad(u) )
827  K += TauOne * Density * AGradN[i] * Density *
828  AGradN[j]; // Stabilization: (a * Grad(v)) * TauOne * (a * Grad(u))
829  K *= Weight;
830 
831  // q-p stabilization block (reset result)
832  L = 0;
833 
834  for (unsigned int m = 0; m < TDim; ++m) // iterate over v components (vx,vy[,vz])
835  {
836  // Velocity block
837  // K += Weight * Viscosity * rShapeDeriv(i, m) * rShapeDeriv(j, m); // Diffusive term: Viscosity * Grad(v) * Grad(u)
838 
839  // v * Grad(p) block
840  G = TauOne * Density * AGradN[i] *
841  rShapeDeriv(j, m); // Stabilization: (a * Grad(v)) * TauOne * Grad(p)
842  PDivV = rShapeDeriv(i, m) * rShapeFunc[j]; // Div(v) * p
843 
844  // Write v * Grad(p) component
845  rDampingMatrix(FirstRow + m, FirstCol + TDim) += Weight * (G - PDivV);
846  // Use symmetry to write the q * Div(u) component
847  rDampingMatrix(FirstCol + TDim, FirstRow + m) += Weight * (G + PDivV);
848 
849  // q-p stabilization block
850  L += rShapeDeriv(i, m) * rShapeDeriv(j, m); // Stabilization: Grad(q) * TauOne * Grad(p)
851 
852  for (unsigned int n = 0; n < TDim; ++n) // iterate over u components (ux,uy[,uz])
853  {
854  // Velocity block
855  rDampingMatrix(FirstRow + m, FirstCol + n) +=
856  Weight * TauTwo * rShapeDeriv(i, m) * rShapeDeriv(j, n); // Stabilization: Div(v) * TauTwo * Div(u)
857  }
858  }
859 
860  // Write remaining terms to velocity block
861  for (unsigned int d = 0; d < TDim; ++d)
862  rDampingMatrix(FirstRow + d, FirstCol + d) += K;
863 
864  // Write q-p stabilization block
865  rDampingMatrix(FirstRow + TDim, FirstCol + TDim) += Weight * TauOne * L;
866 
867  // Update reference column index for next iteration
868  FirstCol += TBlockSize;
869  }
870 
871  // Operate on RHS
872  qF = 0.0;
873  for (unsigned int d = 0; d < TDim; ++d) {
874  rDampRHS[FirstRow + d] +=
875  Weight * TauOne * Density * AGradN[i] *
876  BodyForce[d]; // ( a * Grad(v) ) * TauOne * (Density * BodyForce)
877  qF += rShapeDeriv(i, d) * BodyForce[d];
878  }
879  rDampRHS[FirstRow + TDim] +=
880  Weight * TauOne * qF; // Grad(q) * TauOne * (Density * BodyForce)
881 
882  // Update reference indices
883  FirstRow += TBlockSize;
884  FirstCol = 0;
885  }
886 
888  ZeroMatrix(TFluidLocalSize, TFluidLocalSize);
889  this->AddViscousTerm(viscous_contribution, rShapeDeriv, Viscosity * Weight);
890  noalias(rDampingMatrix) += viscous_contribution;
891  }
892 
894  const Variable<array_1d<double, 3>>& rSensitivityVariable,
896  const ProcessInfo& rCurrentProcessInfo)
897  {
898  KRATOS_TRY
899 
900  if (rSensitivityVariable == SHAPE_SENSITIVITY) {
901  this->CalculateShapeGradientOfVMSSteadyTerm(rOutput, rCurrentProcessInfo);
902  this->AddShapeGradientOfVMSMassTerm(rOutput, ACCELERATION, -1.0, rCurrentProcessInfo);
903  } else {
904  KRATOS_ERROR << "Sensitivity variable " << rSensitivityVariable
905  << " not supported." << std::endl;
906  }
907 
908  KRATOS_CATCH("")
909  }
910 
914  const ProcessInfo& rCurrentProcessInfo) const
915  {
916  KRATOS_TRY
917 
918  rMassMatrix.clear();
919 
920  // Get shape functions, shape function gradients and element volume (area in
921  // 2D). Only one integration point is used so the volume is its weight.
924  double Volume;
925  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Volume);
926 
927  // Density
928  double Density, Viscosity;
929  array_1d<double, 3> Velocity;
930 
931  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
932  std::tie(Density, DENSITY),
933  std::tie(Viscosity, VISCOSITY),
934  std::tie(Velocity, VELOCITY));
935 
936  Viscosity *= Density;
937 
938  // u * Grad(N)
939  array_1d<double, TNumNodes> DensityVelGradN;
940  for (IndexType i = 0; i < TNumNodes; ++i) {
941  DensityVelGradN[i] = 0.0;
942  for (IndexType d = 0; d < TDim; ++d) {
943  DensityVelGradN[i] += Density * DN_DX(i, d) * Velocity[d];
944  }
945  }
946 
947  // Stabilization parameters
948  double VelNorm = 0.0;
949  for (IndexType d = 0; d < TDim; ++d) {
950  VelNorm += Velocity[d] * Velocity[d];
951  }
952 
953  VelNorm = std::sqrt(VelNorm);
954  const double ElemSize = this->CalculateElementSize(Volume);
955  double TauOne, TauTwo;
956  this->CalculateStabilizationParameters(TauOne, TauTwo, VelNorm, ElemSize, Density,
957  Viscosity, rCurrentProcessInfo);
958 
959  // Lumped mass
960  const double LumpedMass = Density * Volume / static_cast<double>(TNumNodes);
961  IndexType DofIndex = 0;
962  for (IndexType i = 0; i < TNumNodes; ++i) {
963  for (IndexType d = 0; d < TDim; ++d) {
964  rMassMatrix(DofIndex, DofIndex) += LumpedMass;
965  ++DofIndex;
966  }
967  ++DofIndex; // Skip pressure Dof
968  }
969 
970  // Stabilization, convection-acceleration
971  IndexType FirstRow(0), FirstCol(0);
972  for (IndexType i = 0; i < TNumNodes; ++i) {
973  for (IndexType j = 0; j < TNumNodes; ++j) {
974  const double diag = DensityVelGradN[i] * TauOne * Density * N[j];
975 
976  for (IndexType d = 0; d < TDim; ++d) {
977  rMassMatrix(FirstRow + d, FirstCol + d) += Volume * diag;
978  rMassMatrix(FirstRow + TDim, FirstCol + d) +=
979  Volume * DN_DX(i, d) * TauOne * Density * N[j];
980  }
981 
982  FirstCol += TBlockSize;
983  } // Node block columns
984 
985  FirstRow += TBlockSize;
986  FirstCol = 0;
987  } // Node block rows
988 
989  KRATOS_CATCH("")
990  }
991 
1003  const Variable<array_1d<double, 3>>& rVariable,
1004  double alpha,
1005  const ProcessInfo& rCurrentProcessInfo) const
1006  {
1007  KRATOS_TRY
1008 
1009  // Get shape functions, shape function gradients and element volume (area in
1010  // 2D). Only one integration point is used so the volume is its weight.
1013  double Volume;
1014  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Volume);
1015 
1016  // Density
1017  double Density, Viscosity;
1018  array_1d<double, TDim> Velocity, X;
1019 
1020  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
1021  std::tie(Density, DENSITY),
1022  std::tie(Viscosity, VISCOSITY),
1023  std::tie(Velocity, VELOCITY),
1024  std::tie(X, rVariable));
1025 
1026  Viscosity *= Density;
1027 
1028  // u * Grad(N)
1029  array_1d<double, TNumNodes> DensityVelGradN;
1030  for (IndexType i = 0; i < TNumNodes; ++i) {
1031  DensityVelGradN[i] = 0.0;
1032  for (IndexType d = 0; d < TDim; ++d) {
1033  DensityVelGradN[i] += Density * DN_DX(i, d) * Velocity[d];
1034  }
1035  }
1036 
1037  // Stabilization parameters
1038  double VelNorm = 0.0;
1039  for (IndexType d = 0; d < TDim; ++d) {
1040  VelNorm += Velocity[d] * Velocity[d];
1041  }
1042  VelNorm = std::sqrt(VelNorm);
1043  const double ElemSize = this->CalculateElementSize(Volume);
1044  double TauOne, TauTwo;
1045  this->CalculateStabilizationParameters(TauOne, TauTwo, VelNorm, ElemSize, Density,
1046  Viscosity, rCurrentProcessInfo);
1047 
1048  // Derivatives of TauOne, TauTwo w.r.t velocity. These definitions
1049  // depend on the definitions of TauOne and TauTwo and should be consistent
1050  // with the fluid element used to solve for VELOCITY and PRESSURE.
1053 
1054  if (VelNorm > 0.0) {
1055  const double CoefOne = -2.0 * Density * TauOne * TauOne / (ElemSize * VelNorm);
1056  const double CoefTwo = 0.5 * Density * ElemSize / VelNorm;
1057 
1058  for (IndexType i = 0; i < TNumNodes; ++i) {
1059  for (IndexType d = 0; d < TDim; ++d) {
1060  TauOneDeriv(i, d) = CoefOne * N[i] * Velocity[d];
1061  TauTwoDeriv(i, d) = CoefTwo * N[i] * Velocity[d];
1062  }
1063  }
1064  }
1065 
1066  // x * Grad(N)
1067  array_1d<double, TNumNodes> DensityXGradN;
1068  for (IndexType i = 0; i < TNumNodes; ++i) {
1069  DensityXGradN[i] = 0.0;
1070  for (IndexType d = 0; d < TDim; ++d) {
1071  DensityXGradN[i] += Density * DN_DX(i, d) * X[d];
1072  }
1073  }
1074 
1075  // Primal gradient of (lumped) VMS mass matrix multiplied with vector
1076  IndexType FirstRow(0), FirstCol(0);
1077  // Loop over nodes
1078  for (IndexType i = 0; i < TNumNodes; ++i) {
1079  for (IndexType j = 0; j < TNumNodes; ++j) {
1080  for (IndexType m = 0; m < TDim; ++m) {
1081  for (IndexType n = 0; n < TDim; ++n) {
1082  double valmn = 0.0;
1083 
1084  valmn += DensityVelGradN[i] * TauOneDeriv(j, n) * Density * X[m];
1085 
1086  valmn += Density * N[j] * DN_DX(i, n) * TauOne * Density * X[m];
1087 
1088  rOutputMatrix(FirstRow + m, FirstCol + n) += alpha * Volume * valmn;
1089  }
1090 
1091  rOutputMatrix(FirstRow + TDim, FirstCol + m) +=
1092  alpha * Volume * DensityXGradN[i] * TauOneDeriv(j, m);
1093  }
1094 
1095  FirstCol += TBlockSize;
1096  } // Node block columns
1097 
1098  FirstRow += TBlockSize;
1099  FirstCol = 0;
1100  } // Node block rows
1101 
1102  KRATOS_CATCH("")
1103  }
1104 
1116  const Variable<array_1d<double, 3>>& rVariable,
1117  double alpha,
1118  const ProcessInfo& rCurrentProcessInfo) const
1119  {
1120  KRATOS_TRY
1121 
1122  // Get shape functions, shape function gradients and element volume (area in
1123  // 2D). Only one integration point is used so the volume is its weight.
1126  double Volume;
1127  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Volume);
1128 
1129  // Density
1130  double Density, Viscosity;
1131  array_1d<double, TDim> Velocity;
1132 
1133  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
1134  std::tie(Density, DENSITY),
1135  std::tie(Viscosity, VISCOSITY),
1136  std::tie(Velocity, VELOCITY));
1137 
1138  Viscosity *= Density;
1139 
1140  // u * Grad(N)
1141  array_1d<double, TNumNodes> DensityVelGradN;
1142  noalias(DensityVelGradN) = Density * prod(DN_DX, Velocity);
1143 
1144  // Det(J)
1145  const double InvDetJ = 1.0 / this->GetGeometry().DeterminantOfJacobian(0);
1146  array_1d<double, TCoordLocalSize> DetJDerivatives;
1147  this->CalculateDeterminantOfJacobianDerivatives(DetJDerivatives);
1148 
1149  // Stabilization parameters TauOne, TauTwo
1150  double VelNorm = norm_2(Velocity);
1151  double ElemSize = this->CalculateElementSize(Volume);
1152  double TauOne, TauTwo;
1153  this->CalculateStabilizationParameters(TauOne, TauTwo, VelNorm, ElemSize, Density,
1154  Viscosity, rCurrentProcessInfo);
1155 
1156  // Vector values
1158  IndexType DofIndex = 0;
1159  for (IndexType i = 0; i < TNumNodes; ++i) {
1160  const auto& r_value =
1161  this->GetGeometry()[i].FastGetSolutionStepValue(rVariable);
1162  for (IndexType d = 0; d < TDim; ++d) {
1163  X[DofIndex++] = r_value[d];
1164  }
1165  X[DofIndex++] = 0.0; // pressure dof
1166  }
1167 
1169 
1170  // We compute the derivative w.r.t each coordinate of each node and
1171  // assign it to the corresponding row of the shape derivatives matrix.
1172  for (IndexType iCoord = 0; iCoord < TCoordLocalSize; ++iCoord) {
1173  // Det(J)'
1174  const double DetJDeriv = DetJDerivatives[iCoord];
1175 
1176  // DN_DX'
1178  for (IndexType i = 0; i < TNumNodes; ++i) {
1179  for (IndexType d = 0; d < TDim; ++d) {
1180  DN_DX_Deriv(i, d) = -DN_DX(iCoord / TDim, d) * DN_DX(i, iCoord % TDim);
1181  }
1182  }
1183 
1184  // Volume'
1185  double VolumeDeriv = Volume * InvDetJ * DetJDeriv;
1186 
1187  // u * Grad(N)'
1188  array_1d<double, TNumNodes> DensityVelGradNDeriv;
1189  noalias(DensityVelGradNDeriv) = Density * prod(DN_DX_Deriv, Velocity);
1190 
1191  // TauOne', TauTwo'
1192  double TauOneDeriv, TauTwoDeriv;
1193  this->CalculateStabilizationParametersDerivative(
1194  TauOneDeriv, TauTwoDeriv, TauOne, TauTwo, VelNorm, ElemSize,
1195  Density, Viscosity, DetJDeriv);
1196 
1199  for (IndexType i = 0; i < TFluidLocalSize; ++i) {
1200  RHS[i] = 0.0;
1201  for (IndexType j = 0; j < TFluidLocalSize; ++j) {
1202  LHS(i, j) = 0.0;
1203  }
1204  }
1205 
1206  // The usual lumped mass matrix
1207  const double LumpedMassDeriv = Density * VolumeDeriv / static_cast<double>(TNumNodes);
1208  IndexType DofIndex = 0;
1209  for (IndexType i_node = 0; i_node < TNumNodes; ++i_node) {
1210  for (IndexType d = 0; d < TDim; ++d) {
1211  LHS(DofIndex, DofIndex) += LumpedMassDeriv;
1212  ++DofIndex;
1213  }
1214  ++DofIndex; // Skip pressure Dof
1215  }
1216 
1217  // Stabilization, convection-acceleration
1218  IndexType FirstRow(0), FirstCol(0);
1219  for (IndexType i = 0; i < TNumNodes; ++i) {
1220  for (IndexType j = 0; j < TNumNodes; ++j) {
1221  double diag = 0.0;
1222  double ddiag = 0.0;
1223 
1224  diag += DensityVelGradN[i] * TauOne * Density * N[j];
1225  ddiag += DensityVelGradNDeriv[i] * TauOne * Density * N[j];
1226  ddiag += DensityVelGradN[i] * TauOneDeriv * Density * N[j];
1227 
1228  for (IndexType n = 0; n < TDim; ++n) {
1229  double valn = DN_DX(i, n) * TauOne * Density * N[j];
1230  double dvaln = 0.0;
1231  dvaln += DN_DX_Deriv(i, n) * TauOne * Density * N[j];
1232  dvaln += DN_DX(i, n) * TauOneDeriv * Density * N[j];
1233 
1234  LHS(FirstRow + n, FirstCol + n) +=
1235  VolumeDeriv * diag + Volume * ddiag;
1236 
1237  LHS(FirstRow + TDim, FirstCol + n) +=
1238  VolumeDeriv * valn + Volume * dvaln;
1239  }
1240 
1241  FirstCol += TBlockSize;
1242  } // Node block columns
1243 
1244  FirstRow += TBlockSize;
1245  FirstCol = 0;
1246  } // Node block rows
1247 
1248  // Assign the derivative w.r.t this coordinate to the
1249  // shape derivative mass matrix.
1250  noalias(Derivative) = prod(LHS, X);
1251  for (IndexType k = 0; k < TFluidLocalSize; ++k) {
1252  rOutputMatrix(iCoord, k) += alpha * Derivative[k];
1253  }
1254  }
1255  KRATOS_CATCH("")
1256  }
1257 
1271  const ProcessInfo& rCurrentProcessInfo) const
1272  {
1273  KRATOS_TRY
1274 
1275  rAdjointMatrix.clear();
1276 
1277  // Get shape functions, shape function gradients and element volume (area in
1278  // 2D). Only one integration point is used so the volume is its weight.
1281  double Volume;
1282 
1283  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Volume);
1284 
1285  // Density
1286  double Density, Viscosity;
1287  array_1d<double, TDim> Velocity, BodyForce;
1288 
1289  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
1290  std::tie(Density, DENSITY),
1291  std::tie(Viscosity, VISCOSITY),
1292  std::tie(Velocity, VELOCITY),
1293  std::tie(BodyForce, BODY_FORCE));
1294 
1295  Viscosity *= Density;
1296  BodyForce *= Density;
1297 
1298  // u * Grad(N)
1299  array_1d<double, TNumNodes> DensityVelGradN;
1300  noalias(DensityVelGradN) = Density * prod(DN_DX, Velocity);
1301 
1302  // Grad(u)
1303  BoundedMatrix<double, TDim, TDim> DensityGradVel;
1304  this->CalculateVelocityGradient(DensityGradVel, DN_DX);
1305 
1306  // Div(u)
1307  double DivVel = 0.0;
1308  for (IndexType d = 0; d < TDim; ++d) {
1309  DivVel += DensityGradVel(d, d);
1310  }
1311 
1312  DensityGradVel *= Density;
1313 
1314  // Grad(p)
1315  array_1d<double, TDim> GradP;
1316  this->CalculatePressureGradient(GradP, DN_DX);
1317 
1318  // ( Grad(u) * Grad(N) )^T
1319  BoundedMatrix<double, TNumNodes, TDim> DN_DX_DensityGradVel;
1320  noalias(DN_DX_DensityGradVel) = prod(DN_DX, DensityGradVel);
1321 
1322  // ( u * Grad(u) * Grad(N) )^T
1323  array_1d<double, TNumNodes> DN_DX_DensityGradVel_Vel;
1324  noalias(DN_DX_DensityGradVel_Vel) = prod(DN_DX_DensityGradVel, Velocity);
1325 
1326  // u * Grad(u)
1327  array_1d<double, TDim> DensityGradVel_Vel;
1328  noalias(DensityGradVel_Vel) = prod(DensityGradVel, Velocity);
1329 
1330  // Grad(N)^T * Grad(p)
1331  array_1d<double, TNumNodes> DN_DX_GradP;
1332  noalias(DN_DX_GradP) = prod(DN_DX, GradP);
1333 
1334  // Grad(N)^T * BodyForce
1335  array_1d<double, TNumNodes> DN_DX_BodyForce;
1336  noalias(DN_DX_BodyForce) = prod(DN_DX, BodyForce);
1337 
1338  // Stabilization parameters TauOne, TauTwo
1339  double VelNorm = norm_2(Velocity);
1340  double ElemSize = this->CalculateElementSize(Volume);
1341  double TauOne, TauTwo;
1342  this->CalculateStabilizationParameters(TauOne, TauTwo, VelNorm, ElemSize, Density,
1343  Viscosity, rCurrentProcessInfo);
1344 
1345  // Derivatives of TauOne, TauTwo w.r.t velocity. These definitions
1346  // depend on the definitions of TauOne and TauTwo and should be
1347  // consistent with the fluid element used to solve for VELOCITY and
1348  // PRESSURE.
1351 
1352  if (VelNorm > 0.0) {
1353  double CoefOne = -2.0 * Density * TauOne * TauOne / (ElemSize * VelNorm);
1354  double CoefTwo = 0.5 * Density * ElemSize / VelNorm;
1355 
1356  for (IndexType i = 0; i < TNumNodes; ++i) {
1357  for (IndexType d = 0; d < TDim; ++d) {
1358  TauOneDeriv(i, d) = CoefOne * N[i] * Velocity[d];
1359  TauTwoDeriv(i, d) = CoefTwo * N[i] * Velocity[d];
1360  }
1361  }
1362  }
1363 
1364  // Here, -(\partial R / \partial W) is calculated. This is the discrete
1365  // derivative of the fluid residual w.r.t the fluid variables and therefore
1366  // includes many of the terms defined in the fluid element. Neglecting the
1367  // transient terms of the fluid element, this matrix is identical to the
1368  // Jacobian of the fluid residual used for Newton-Raphson iterations. The
1369  // matrix is transposed at the end to get the adjoint system matrix.
1370 
1371  IndexType FirstRow(0), FirstCol(0);
1372  // Loop over nodes
1373  for (IndexType i = 0; i < TNumNodes; ++i) {
1374  for (IndexType j = 0; j < TNumNodes; ++j) {
1375  double diag = 0.0;
1376 
1377  // Convective term, v * (u * Grad(u))
1378  diag += N[i] * DensityVelGradN[j];
1379 
1380  // Stabilization, lsq convection
1381  // (u * Grad(v)) * TauOne * (u * Grad(u))
1382  diag += DensityVelGradN[i] * TauOne * DensityVelGradN[j];
1383 
1384  for (IndexType m = 0; m < TDim; ++m) {
1385  for (IndexType n = 0; n < TDim; ++n) {
1386  double valmn = 0.0;
1387 
1388  // Convective term, v * (u * Grad(u))
1389  valmn += N[i] * N[j] * DensityGradVel(m, n);
1390 
1391  // Stabilization, lsq convection
1392  // (u * Grad(v)) * TauOne * (u * Grad(u))
1393  valmn += DensityVelGradN[i] * TauOne * N[j] *
1394  DensityGradVel(m, n);
1395  valmn += DensityVelGradN[i] * TauOneDeriv(j, n) *
1396  DensityGradVel_Vel[m];
1397  valmn += Density * N[j] * DN_DX(i, n) * TauOne *
1398  DensityGradVel_Vel[m];
1399 
1400  // Stabilization, lsq divergence
1401  // Div(v) * TauTwo * Div(u)
1402  valmn += DN_DX(i, m) * TauTwo * DN_DX(j, n);
1403  valmn += DN_DX(i, m) * TauTwoDeriv(j, n) * DivVel;
1404 
1405  // Stabilization, convection-pressure
1406  // (u * Grad(v)) * TauOne * Grad(p)
1407  valmn += TauOneDeriv(j, n) * DensityVelGradN[i] * GradP[m];
1408  valmn += Density * TauOne * N[j] * DN_DX(i, n) * GradP[m];
1409 
1410  // Stabilization, convection-BodyForce
1411  // (u * Grad(v)) * TauOne * f
1412  valmn -= N[j] * DN_DX(i, n) * TauOne * Density * BodyForce[m];
1413  valmn -= DensityVelGradN[i] * TauOneDeriv(j, n) * BodyForce[m];
1414 
1415  rAdjointMatrix(FirstRow + m, FirstCol + n) += Volume * valmn;
1416  }
1417 
1418  rAdjointMatrix(FirstRow + m, FirstCol + m) += Volume * diag;
1419 
1420  double valmp = 0.0;
1421  double valpn = 0.0;
1422 
1423  // Pressure term
1424  // Div(v) * p
1425  valmp -= DN_DX(i, m) * N[j];
1426 
1427  // Stabilization, convection-pressure
1428  // (u * Grad(v)) * TauOne * Grad(p)
1429  valmp += TauOne * DensityVelGradN[i] * DN_DX(j, m);
1430 
1431  // Divergence term
1432  // q * Div(u)
1433  valpn += N[i] * DN_DX(j, m);
1434 
1435  // Stabilization, lsq pressure
1436  // TauOne * Grad(q) * Grad(p)
1437  valpn += DN_DX_GradP[i] * TauOneDeriv(j, m);
1438 
1439  // Stabilization, pressure-convection
1440  // Grad(q) * TauOne * (u * Grad(u))
1441  valpn += DN_DX(i, m) * TauOne * DensityVelGradN[j];
1442  valpn += DN_DX_DensityGradVel(i, m) * TauOne * N[j];
1443  valpn += DN_DX_DensityGradVel_Vel[i] * TauOneDeriv(j, m);
1444 
1445  // Stabilization, pressure-BodyForce
1446  // Grad(q) * TauOne * f
1447  valpn -= DN_DX_BodyForce[i] * TauOneDeriv(j, m);
1448 
1449  rAdjointMatrix(FirstRow + m, FirstCol + TDim) += Volume * valmp;
1450  rAdjointMatrix(FirstRow + TDim, FirstCol + m) += Volume * valpn;
1451  }
1452 
1453  // Stabilization, lsq pressure
1454  // TauOne * Grad(q) * Grad(p)
1455  double valpp = 0.0;
1456  for (IndexType d = 0; d < TDim; ++d) {
1457  valpp += DN_DX(i, d) * DN_DX(j, d);
1458  }
1459  valpp *= TauOne;
1460 
1461  rAdjointMatrix(FirstRow + TDim, FirstCol + TDim) += Volume * valpp;
1462 
1463  FirstCol += TBlockSize;
1464  } // Node block columns
1465 
1466  FirstRow += TBlockSize;
1467  FirstCol = 0;
1468  } // Node block rows
1469 
1470  // Viscous term
1471  this->AddViscousTerm(rAdjointMatrix, DN_DX, Viscosity * Volume);
1472 
1473  // change the sign for consistency with definition
1474  noalias(rAdjointMatrix) = -rAdjointMatrix;
1475 
1476  KRATOS_CATCH("")
1477  }
1478 
1495  const ProcessInfo& rCurrentProcessInfo) const
1496  {
1497  KRATOS_TRY
1498 
1499  // Get shape functions, shape function gradients and element volume (area in
1500  // 2D). Only one integration point is used so the volume is its weight.
1503  double Volume;
1504 
1505  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Volume);
1506 
1507  // Density
1508  double Density, Viscosity;
1509  array_1d<double, TDim> Velocity, BodyForce;
1510 
1511  FluidCalculationUtilities::EvaluateInPoint(this->GetGeometry(), N,
1512  std::tie(Density, DENSITY),
1513  std::tie(Viscosity, VISCOSITY),
1514  std::tie(Velocity, VELOCITY),
1515  std::tie(BodyForce, BODY_FORCE));
1516 
1517  BodyForce *= Density;
1518  Viscosity *= Density;
1519 
1520  // u * Grad(N)
1521  array_1d<double, TNumNodes> DensityVelGradN;
1522  noalias(DensityVelGradN) = Density * prod(DN_DX, Velocity);
1523 
1524  // Det(J)
1525  const double InvDetJ = 1.0 / this->GetGeometry().DeterminantOfJacobian(0);
1526  array_1d<double, TCoordLocalSize> DetJDerivatives;
1527  this->CalculateDeterminantOfJacobianDerivatives(DetJDerivatives);
1528 
1529  // Stabilization parameters TauOne, TauTwo
1530  double VelNorm = norm_2(Velocity);
1531  double ElemSize = this->CalculateElementSize(Volume);
1532  double TauOne, TauTwo;
1533  this->CalculateStabilizationParameters(TauOne, TauTwo, VelNorm, ElemSize, Density,
1534  Viscosity, rCurrentProcessInfo);
1535 
1536 
1538 
1539  IndexType DofIndex = 0;
1540  for (IndexType i_node = 0; i_node < TNumNodes; ++i_node) {
1541  const auto& r_velocity =
1542  this->GetGeometry()[i_node].FastGetSolutionStepValue(VELOCITY);
1543  for (IndexType d = 0; d < TDim; ++d) {
1544  FluidValues[DofIndex++] = r_velocity[d];
1545  }
1546  FluidValues[DofIndex++] =
1547  this->GetGeometry()[i_node].FastGetSolutionStepValue(PRESSURE);
1548  }
1549 
1550  // We compute the derivative of the residual w.r.t each coordinate of
1551  // each node and assign it to the corresponding row of the shape
1552  // derivatives matrix.
1553  for (IndexType iCoord = 0; iCoord < TCoordLocalSize; ++iCoord) {
1554  // Det(J)'
1555  const double DetJDeriv = DetJDerivatives[iCoord];
1556 
1557  // DN_DX'
1559  for (IndexType i = 0; i < TNumNodes; ++i) {
1560  for (IndexType d = 0; d < TDim; ++d) {
1561  DN_DX_Deriv(i, d) = -DN_DX(iCoord / TDim, d) * DN_DX(i, iCoord % TDim);
1562  }
1563  }
1564 
1565  // Volume'
1566  const double VolumeDeriv = Volume * InvDetJ * DetJDeriv;
1567 
1568  // u * Grad(N)'
1569  array_1d<double, TNumNodes> DensityVelGradNDeriv;
1570  noalias(DensityVelGradNDeriv) = Density * prod(DN_DX_Deriv, Velocity);
1571 
1572  // TauOne', TauTwo'
1573  double TauOneDeriv, TauTwoDeriv;
1574  this->CalculateStabilizationParametersDerivative(
1575  TauOneDeriv, TauTwoDeriv, TauOne, TauTwo, VelNorm, ElemSize,
1576  Density, Viscosity, DetJDeriv);
1577 
1580  for (IndexType i = 0; i < TFluidLocalSize; ++i) {
1581  RHS[i] = 0.0;
1582  for (IndexType j = 0; j < TFluidLocalSize; ++j) {
1583  LHS(i, j) = 0.0;
1584  }
1585  }
1586 
1587  for (IndexType i = 0; i < TNumNodes; ++i) {
1588  for (IndexType j = 0; j < TNumNodes; ++j) {
1589  // Left-hand side matrix
1590  double diag = 0.0;
1591  double ddiag = 0.0;
1592 
1593  // Convective term, v * (u * Grad(u))
1594  diag += N[i] * DensityVelGradN[j];
1595  ddiag += N[i] * DensityVelGradNDeriv[j];
1596 
1597  // Stabilization, lsq convection
1598  // (u * Grad(v)) * TauOne * (u * Grad(u))
1599  diag += DensityVelGradN[i] * TauOne * DensityVelGradN[j];
1600  ddiag += DensityVelGradNDeriv[i] * TauOne * DensityVelGradN[j] +
1601  DensityVelGradN[i] * TauOneDeriv * DensityVelGradN[j] +
1602  DensityVelGradN[i] * TauOne * DensityVelGradNDeriv[j];
1603 
1604  for (IndexType m = 0; m < TDim; ++m) {
1605  for (IndexType n = 0; n < TDim; ++n) {
1606  // Stabilization, lsq divergence
1607  // Div(v) * TauTwo * Div(u)
1608  double valmn = DN_DX(i, m) * TauTwo * DN_DX(j, n);
1609  double dvalmn = DN_DX_Deriv(i, m) * TauTwo * DN_DX(j, n) +
1610  DN_DX(i, m) * TauTwoDeriv * DN_DX(j, n) +
1611  DN_DX(i, m) * TauTwo * DN_DX_Deriv(j, n);
1612 
1613  LHS(i * TBlockSize + m, j * TBlockSize + n) +=
1614  VolumeDeriv * valmn + Volume * dvalmn;
1615  }
1616  LHS(i * TBlockSize + m, j * TBlockSize + m) +=
1617  VolumeDeriv * diag + Volume * ddiag;
1618 
1619  double valmp = 0.0;
1620  double dvalmp = 0.0;
1621  // Pressure term
1622  // Div(v) * p
1623  valmp -= DN_DX(i, m) * N[j];
1624  dvalmp -= DN_DX_Deriv(i, m) * N[j];
1625 
1626  // Stabilization, convection-pressure
1627  // (u * Grad(v)) * TauOne * Grad(p)
1628  valmp += TauOne * DensityVelGradN[i] * DN_DX(j, m);
1629  dvalmp += TauOneDeriv * DensityVelGradN[i] * DN_DX(j, m) +
1630  TauOne * DensityVelGradNDeriv[i] * DN_DX(j, m) +
1631  TauOne * DensityVelGradN[i] * DN_DX_Deriv(j, m);
1632 
1633  double valpn = 0.0;
1634  double dvalpn = 0.0;
1635  // Divergence term
1636  // q * Div(u)
1637  valpn += N[i] * DN_DX(j, m);
1638  dvalpn += N[i] * DN_DX_Deriv(j, m);
1639 
1640  // Stabilization, pressure-convection
1641  // Grad(q) * TauOne * (u * Grad(u))
1642  valpn += TauOne * DensityVelGradN[j] * DN_DX(i, m);
1643  dvalpn += TauOneDeriv * DensityVelGradN[j] * DN_DX(i, m) +
1644  TauOne * DensityVelGradNDeriv[j] * DN_DX(i, m) +
1645  TauOne * DensityVelGradN[j] * DN_DX_Deriv(i, m);
1646 
1647  LHS(i * TBlockSize + m, j * TBlockSize + TDim) +=
1648  VolumeDeriv * valmp + Volume * dvalmp;
1649  LHS(i * TBlockSize + TDim, j * TBlockSize + m) +=
1650  VolumeDeriv * valpn + Volume * dvalpn;
1651  }
1652 
1653  double valpp = 0.0;
1654  double dvalpp = 0.0;
1655  // Stabilization, lsq pressure
1656  // TauOne * Grad(q) * Grad(p)
1657  for (IndexType d = 0; d < TDim; ++d) {
1658  valpp += DN_DX(i, d) * DN_DX(j, d) * TauOne;
1659  dvalpp += DN_DX_Deriv(i, d) * DN_DX(j, d) * TauOne +
1660  DN_DX(i, d) * DN_DX_Deriv(j, d) * TauOne +
1661  DN_DX(i, d) * DN_DX(j, d) * TauOneDeriv;
1662  }
1663 
1664  LHS(i * TBlockSize + TDim, j * TBlockSize + TDim) +=
1665  VolumeDeriv * valpp + Volume * dvalpp;
1666  } // Node block columns
1667 
1668  // Right-hand side vector
1669  double DN_DX_BodyForce = 0.0;
1670  double DN_DX_BodyForceDeriv = 0.0;
1671  for (IndexType d = 0; d < TDim; ++d) {
1672  DN_DX_BodyForce += DN_DX(i, d) * BodyForce[d];
1673  DN_DX_BodyForceDeriv += DN_DX_Deriv(i, d) * BodyForce[d];
1674  }
1675 
1676  for (IndexType m = 0; m < TDim; ++m) {
1677  double valm = 0.0;
1678  double dvalm = 0.0;
1679 
1680  // External body force
1681  valm += N[i] * BodyForce[m];
1682 
1683  // Stabilization, convection-BodyForce
1684  // (u * Grad(v)) * TauOne * f
1685  valm += TauOne * DensityVelGradN[i] * BodyForce[m];
1686  dvalm += TauOneDeriv * DensityVelGradN[i] * BodyForce[m] +
1687  TauOne * DensityVelGradNDeriv[i] * BodyForce[m];
1688 
1689  RHS[i * TBlockSize + m] += VolumeDeriv * valm + Volume * dvalm;
1690  }
1691 
1692  double valp = TauOne * DN_DX_BodyForce;
1693  double dvalp = TauOneDeriv * DN_DX_BodyForce + TauOne * DN_DX_BodyForceDeriv;
1694 
1695  RHS[i * TBlockSize + TDim] += VolumeDeriv * valp + Volume * dvalp;
1696  } // Node block rows
1697 
1698  this->AddViscousTermDerivative(LHS, DN_DX, DN_DX_Deriv, Viscosity * Volume,
1699  Viscosity * VolumeDeriv);
1700 
1701  // Assign the derivative of the residual w.r.t this coordinate to
1702  // the shape derivatives matrix.
1703  array_1d<double, TFluidLocalSize> ResidualDerivative;
1704  noalias(ResidualDerivative) = RHS - prod(LHS, FluidValues);
1705  for (IndexType k = 0; k < TFluidLocalSize; ++k) {
1706  rShapeDerivativesMatrix(iCoord, k) = ResidualDerivative[k];
1707  }
1708  }
1709 
1710  KRATOS_CATCH("")
1711  }
1712 
1724  const ShapeFunctionDerivativesType& rDN_DX) const
1725  {
1726  const auto& r_geometry = this->GetGeometry();
1727  // node 0
1728  const auto& r_velocity = r_geometry[0].FastGetSolutionStepValue(VELOCITY, 0);
1729  for (IndexType m = 0; m < TDim; m++) {
1730  for (IndexType n = 0; n < TDim; n++) {
1731  rGradVel(m, n) = rDN_DX(0, n) * r_velocity[m];
1732  }
1733  }
1734 
1735  // node 1,2,...
1736  for (IndexType i_node = 1; i_node < TNumNodes; ++i_node) {
1737  const auto& r_velocity = r_geometry[i_node].FastGetSolutionStepValue(VELOCITY, 0);
1738  for (IndexType m = 0; m < TDim; m++) {
1739  for (IndexType n = 0; n < TDim; n++) {
1740  rGradVel(m, n) += rDN_DX(i_node, n) * r_velocity[m];
1741  }
1742  }
1743  }
1744  }
1745 
1753  array_1d<double, TDim>& rGradP,
1754  const ShapeFunctionDerivativesType& rDN_DX) const
1755  {
1756  const auto& r_geometry = this->GetGeometry();
1757  // node 0
1758  for (IndexType d = 0; d < TDim; ++d) {
1759  rGradP[d] = rDN_DX(0, d) * r_geometry[0].FastGetSolutionStepValue(PRESSURE);
1760  }
1761 
1762  // node 1,2,...
1763  for (IndexType i_node = 1; i_node < TNumNodes; ++i_node) {
1764  for (IndexType d = 0; d < TDim; ++d) {
1765  rGradP[d] += rDN_DX(i_node, d) *
1766  r_geometry[i_node].FastGetSolutionStepValue(PRESSURE);
1767  }
1768  }
1769  }
1770 
1776  double CalculateElementSize(const double Volume) const;
1777 
1791 
1803  double& rTauOne,
1804  double& rTauTwo,
1805  const double VelNorm,
1806  const double ElemSize,
1807  const double Density,
1808  const double Viscosity,
1809  const ProcessInfo& rCurrentProcessInfo) const
1810  {
1811  // assume DELTA_TIME < 0 !!!
1812  double tmp = -rCurrentProcessInfo[DYNAMIC_TAU] / rCurrentProcessInfo[DELTA_TIME];
1813  tmp += 2.0 * VelNorm / ElemSize;
1814  tmp *= Density;
1815  tmp += 4.0 * Viscosity / (ElemSize * ElemSize);
1816  rTauOne = 1.0 / tmp;
1817  rTauTwo = Viscosity + 0.5 * Density * ElemSize * VelNorm;
1818  }
1819 
1834  double& rTauOneDeriv,
1835  double& rTauTwoDeriv,
1836  const double TauOne,
1837  const double TauTwo,
1838  const double VelNorm,
1839  const double ElemSize,
1840  const double Density,
1841  const double Viscosity,
1842  const double DetJDeriv) const;
1843 
1853  const ShapeFunctionDerivativesType& rDN_DX,
1854  const double Weight) const;
1855 
1869  const ShapeFunctionDerivativesType& rDN_DX,
1870  const ShapeFunctionDerivativesType& rDN_DX_Deriv,
1871  const double Weight,
1872  const double WeightDeriv) const;
1873 
1875 
1876 private:
1877 
1880 
1884 
1885  friend class Serializer;
1886 
1887  void save(Serializer& rSerializer) const override
1888  {
1889  KRATOS_TRY;
1890 
1892 
1893  KRATOS_CATCH("");
1894  }
1895 
1896  void load(Serializer& rSerializer) override
1897  {
1898  KRATOS_TRY;
1899 
1901 
1902  KRATOS_CATCH("");
1903  }
1904 
1908 
1909  VMSAdjointElement& operator=(VMSAdjointElement const& rOther);
1910 
1911  VMSAdjointElement(VMSAdjointElement const& rOther);
1912 
1914 
1915 }; // class VMSAdjointElement
1916 
1918 
1921 
1923 template<unsigned int TDim>
1924 inline std::istream& operator >>(std::istream& rIStream,
1925  VMSAdjointElement<TDim>& rThis) {
1926  return rIStream;
1927 }
1928 
1930 template<unsigned int TDim>
1931 inline std::ostream& operator <<(std::ostream& rOStream,
1932  const VMSAdjointElement<TDim>& rThis) {
1933  rThis.PrintInfo(rOStream);
1934  rOStream << std::endl;
1935  rThis.PrintData(rOStream);
1936 
1937  return rOStream;
1938 }
1940 
1942 
1943 }// namespace Kratos
1944 
1945 #endif // KRATOS_VMS_ADJOINT_ELEMENT_H_INCLUDED defined
PeriodicInterfaceProcess & operator=(const PeriodicInterfaceProcess &)=delete
Interface extensions for adjoint elements and conditions.
Definition: adjoint_extensions.h:37
Base class for all Elements.
Definition: element.h:60
virtual void CalculateSecondDerivativesLHS(MatrixType &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo)
Definition: element.h:536
virtual void CalculateFirstDerivativesLHS(MatrixType &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo)
Definition: element.h:479
std::size_t SizeType
Definition: element.h:94
std::vector< DofType::Pointer > DofsVectorType
Definition: element.h:100
virtual int Check(const ProcessInfo &rCurrentProcessInfo) const
Definition: element.h:904
std::vector< std::size_t > EquationIdVectorType
Definition: element.h:98
std::size_t IndexType
Definition: element.h:92
std::size_t IndexType
Definition: flags.h:74
GeometryType & GetGeometry()
Returns the reference of the geometry.
Definition: geometrical_object.h:158
Geometry base class.
Definition: geometry.h:71
static void CalculateGeometryData(const GeometryType &rGeometry, BoundedMatrix< double, 4, 3 > &rDN_DX, array_1d< double, 4 > &rN, double &rVolume)
This function is designed to compute the shape function derivatives, shape functions and volume in 3D...
Definition: geometry_utilities.h:176
Wrapper for a function which behaves like an arithmetic type.
Definition: indirect_scalar.h:45
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
void clear()
Definition: amatrix_interface.h:284
iterator begin()
Definition: amatrix_interface.h:241
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
A sorted associative container similar to an STL set, but uses a vector to store pointers to its data...
Definition: pointer_vector_set.h:72
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
Properties encapsulates data shared by different Elements or Conditions. It can store any type of dat...
Definition: properties.h:69
The serialization consists in storing the state of an object into a storage format like data file or ...
Definition: serializer.h:123
An adjoint element for discrete shape sensitivity of VMS fluid element.
Definition: vms_adjoint_element.h:55
void CalculateShapeGradientOfVMSSteadyTerm(BoundedMatrix< double, TCoordLocalSize, TFluidLocalSize > &rShapeDerivativesMatrix, const ProcessInfo &rCurrentProcessInfo) const
Calculate the partial derivatives of damping term w.r.t. shape parameters.
Definition: vms_adjoint_element.h:1493
Element::MatrixType MatrixType
Definition: vms_adjoint_element.h:168
void GetValuesArray(ArrayType &rValues, const int Step=0) const
Definition: vms_adjoint_element.h:305
Element::Pointer Create(IndexType NewId, NodesArrayType const &ThisNodes, PropertiesType::Pointer pProperties) const override
Creates a new element of this type.
Definition: vms_adjoint_element.h:226
void GetSecondDerivativesArray(ArrayType &rValues, int Step=0) const
Definition: vms_adjoint_element.h:352
void AddPrimalGradientOfVMSMassTerm(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rOutputMatrix, const Variable< array_1d< double, 3 >> &rVariable, double alpha, const ProcessInfo &rCurrentProcessInfo) const
Adds primal gradient of the VMS mass matrix multiplied by a vector.
Definition: vms_adjoint_element.h:1001
void CalculateFirstDerivativesLHS(MatrixType &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo) override
Calculates the adjoint matrix for velocity and pressure.
Definition: vms_adjoint_element.h:519
void GetFirstDerivativesArray(ArrayType &rValues, int Step=0) const
Definition: vms_adjoint_element.h:332
void CalculateStabilizationParametersDerivative(double &rTauOneDeriv, double &rTauTwoDeriv, const double TauOne, const double TauTwo, const double VelNorm, const double ElemSize, const double Density, const double Viscosity, const double DetJDeriv) const
Returns stabilization parameters derived w.r.t a node's coordinate.
Element::GeometryType GeometryType
Definition: vms_adjoint_element.h:158
void GetDofList(DofsVectorType &rElementalDofList, const ProcessInfo &rCurrentProcessInfo) const override
Definition: vms_adjoint_element.h:687
~VMSAdjointElement() override
Definition: vms_adjoint_element.h:209
Element::DofsVectorType DofsVectorType
Definition: vms_adjoint_element.h:170
void CalculatePrimalGradientOfVMSSteadyTerm(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rAdjointMatrix, const ProcessInfo &rCurrentProcessInfo) const
Calculates the elemental contribution to the steady adjoint system matrix.
Definition: vms_adjoint_element.h:1269
void EquationIdVector(EquationIdVectorType &rResult, const ProcessInfo &rCurrentProcessInfo) const override
Definition: vms_adjoint_element.h:703
void AddViscousTerm(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rResult, const ShapeFunctionDerivativesType &rDN_DX, const double Weight) const
Adds viscous contributions to adjoint system matrix.
void CalculateDampingMatrix(MatrixType &rDampingMatrix, const ProcessInfo &rProcessInfo) override
Definition: vms_adjoint_element.h:623
void CalculateLeftHandSide(MatrixType &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:480
VMSAdjointElement(IndexType NewId=0)
Definition: vms_adjoint_element.h:189
void CalculateLocalSystem(MatrixType &rLeftHandSideMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:368
Element::NodesArrayType NodesArrayType
Definition: vms_adjoint_element.h:162
void AddShapeGradientOfVMSMassTerm(BoundedMatrix< double, TCoordLocalSize, TFluidLocalSize > &rOutputMatrix, const Variable< array_1d< double, 3 >> &rVariable, double alpha, const ProcessInfo &rCurrentProcessInfo) const
Adds shape gradient of the VMS mass matrix multiplied by a vector.
Definition: vms_adjoint_element.h:1114
Element::IndexType IndexType
Definition: vms_adjoint_element.h:154
Element::VectorType VectorType
Definition: vms_adjoint_element.h:164
void GetFirstDerivativesVector(VectorType &rValues, int Step=0) const override
Returns the adjoint velocity values stored in this element's nodes.
Definition: vms_adjoint_element.h:322
int Check(const ProcessInfo &rProcessInfo) const override
Checks for proper element geometry, nodal variables and dofs.
Definition: vms_adjoint_element.h:257
void AddMassStabTerms(MatrixType &rLHSMatrix, const double Density, const array_1d< double, TDim > &rAdvVel, const double TauOne, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Definition: vms_adjoint_element.h:754
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: vms_adjoint_element.h:740
Element::Pointer Create(IndexType NewId, GeometryType::Pointer pGeom, PropertiesType::Pointer pProperties) const override
It creates a new element pointer.
Definition: vms_adjoint_element.h:239
std::string Info() const override
Turn back information as a string.
Definition: vms_adjoint_element.h:723
void CalculatePressureGradient(array_1d< double, TDim > &rGradP, const ShapeFunctionDerivativesType &rDN_DX) const
Returns the pressure gradient.
Definition: vms_adjoint_element.h:1752
VMSAdjointElement(IndexType NewId, GeometryType::Pointer pGeometry)
Definition: vms_adjoint_element.h:194
void GetSecondDerivativesVector(VectorType &rValues, int Step=0) const override
Returns the adjoint acceleration values stored in this element's nodes.
Definition: vms_adjoint_element.h:340
VMSAdjointElement(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties)
Definition: vms_adjoint_element.h:201
void CalculateFirstDerivativesLHS(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo)
Definition: vms_adjoint_element.h:529
std::array< Dof< double >::Pointer, TFluidLocalSize > DofsArrayType
Definition: vms_adjoint_element.h:172
KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(VMSAdjointElement)
Pointer definition.
std::array< std::size_t, TFluidLocalSize > EquationIdArrayType
Definition: vms_adjoint_element.h:176
void CalculateMassMatrix(MatrixType &rMassMatrix, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:568
void Calculate(const Variable< Vector > &rVariable, Vector &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:654
Element::PropertiesType PropertiesType
Definition: vms_adjoint_element.h:160
void GetDofArray(DofsArrayType &rElementalDofList, const ProcessInfo &rCurrentProcessInfo) const
void EquationIdArray(EquationIdArrayType &rResult, const ProcessInfo &rProcessInfo) const
void AddViscousTermDerivative(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rResult, const ShapeFunctionDerivativesType &rDN_DX, const ShapeFunctionDerivativesType &rDN_DX_Deriv, const double Weight, const double WeightDeriv) const
Adds derivative of viscous term w.r.t a node's coordinate.
std::array< double, TFluidLocalSize > ArrayType
Definition: vms_adjoint_element.h:166
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: vms_adjoint_element.h:731
void CalculateSecondDerivativesLHS(MatrixType &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo) override
Calculates the adjoint matrix for acceleration.
Definition: vms_adjoint_element.h:550
void CalculateVMSMassMatrix(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rMassMatrix, const ProcessInfo &rCurrentProcessInfo) const
Calculate VMS-stabilized (lumped) mass matrix.
Definition: vms_adjoint_element.h:912
void AddIntegrationPointVelocityContribution(MatrixType &rDampingMatrix, VectorType &rDampRHS, const double Density, const double Viscosity, const array_1d< double, TDim > &rAdvVel, const array_1d< double, TDim > &rBodyForce, const double TauOne, const double TauTwo, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Definition: vms_adjoint_element.h:796
void Initialize(const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:216
void CalculateDeterminantOfJacobianDerivatives(array_1d< double, TCoordLocalSize > &rDetJDerivatives) const
Returns derivatives of determinant of Jacobian w.r.t coordinates.
void AuxiliaryCalculateSensitivityMatrix(const Variable< array_1d< double, 3 >> &rSensitivityVariable, BoundedMatrix< double, TCoordLocalSize, TFluidLocalSize > &rOutput, const ProcessInfo &rCurrentProcessInfo)
Definition: vms_adjoint_element.h:893
double CalculateElementSize(const double Volume) const
Returns the element's size.
void GetValuesVector(VectorType &rValues, int Step=0) const override
Returns the adjoint values stored in this element's nodes.
Definition: vms_adjoint_element.h:293
void CalculateSensitivityMatrix(const Variable< array_1d< double, 3 >> &rSensitivityVariable, Matrix &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Calculates the sensitivity matrix.
Definition: vms_adjoint_element.h:642
void CalculateVelocityGradient(BoundedMatrix< double, TDim, TDim > &rGradVel, const ShapeFunctionDerivativesType &rDN_DX) const
Returns the gradient matrix of the velocity.
Definition: vms_adjoint_element.h:1722
Element::SizeType SizeType
Definition: vms_adjoint_element.h:156
Element::EquationIdVectorType EquationIdVectorType
Definition: vms_adjoint_element.h:174
void CalculateSecondDerivativesLHS(BoundedMatrix< double, TFluidLocalSize, TFluidLocalSize > &rLeftHandSideMatrix, const ProcessInfo &rCurrentProcessInfo)
Definition: vms_adjoint_element.h:560
BoundedMatrix< double, TNumNodes, TDim > ShapeFunctionDerivativesType
Definition: vms_adjoint_element.h:179
void CalculateStabilizationParameters(double &rTauOne, double &rTauTwo, const double VelNorm, const double ElemSize, const double Density, const double Viscosity, const ProcessInfo &rCurrentProcessInfo) const
Returns the VMS stabilization parameters.
Definition: vms_adjoint_element.h:1802
void CalculateLocalVelocityContribution(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:417
void CalculateRightHandSide(VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo) override
Definition: vms_adjoint_element.h:491
const std::string & Name() const
Definition: variable_data.h:201
Variable class contains all information needed to store and retrive data from a data container.
Definition: variable.h:63
#define KRATOS_SERIALIZE_SAVE_BASE_CLASS(Serializer, BaseType)
Definition: define.h:812
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_SERIALIZE_LOAD_BASE_CLASS(Serializer, BaseType)
Definition: define.h:815
static void EvaluateInPoint(const GeometryType &rGeometry, const Vector &rShapeFunction, const int Step, const TRefVariableValuePairArgs &... rValueVariablePairs)
Evaluates given list of variable pairs at gauss point locations at step.
Definition: fluid_calculation_utilities.h:75
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_CHECK_DOF_IN_NODE(TheVariable, TheNode)
Definition: checks.h:176
#define KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(TheVariable, TheNode)
Definition: checks.h:171
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
IndirectScalar< typename TVariableType::Type > MakeIndirectScalar(Node &rNode, const TVariableType &rVariable)
Definition: indirect_scalar.h:120
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
float velocity
Definition: PecletTest.py:54
list coeff
Definition: bombardelli_test.py:41
list values
Definition: bombardelli_test.py:42
def SetValue(entity, variable, value)
Definition: coupling_interface_data.py:256
float viscosity
Definition: edgebased_var.py:8
float density
Definition: face_heat.py:56
gauss_weight
Definition: generate_axisymmetric_navier_stokes_element.py:33
alpha
Definition: generate_convection_diffusion_explicit_element.py:113
dofs
Enforced auxTangentSlipNonObjective = delta_time * gap_time_derivative_non_objective....
Definition: generate_frictional_mortar_condition.py:210
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
def load(f)
Definition: ode_solve.py:307
int L
Definition: ode_solve.py:390
int d
Definition: ode_solve.py:397
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int m
Definition: run_marine_rain_substepping.py:8
body_force
Definition: script_ELASTIC.py:102
N
Definition: sensitivityMatrix.py:29
K
Definition: sensitivityMatrix.py:73
integer i
Definition: TensorModule.f:17