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.
compressible_navier_stokes_explicit.h
Go to the documentation of this file.
1 
2 // | / |
3 // ' / __| _` | __| _ \ __|
4 // . \ | ( | | ( |\__ `
5 // _|\_\_| \__,_|\__|\___/ ____/
6 // Multi-Physics
7 //
8 // License: BSD License
9 // Kratos default license: kratos/license.txt
10 //
11 // Main authors: Ruben Zorrilla
12 //
13 
14 #if !defined(KRATOS_COMPRESSIBLE_NAVIER_STOKES_EXPLICIT_H_INCLUDED)
15 #define KRATOS_COMPRESSIBLE_NAVIER_STOKES_EXPLICIT_H_INCLUDED
16 
17 // System includes
18 
19 
20 // External includes
21 
22 
23 // Project includes
24 #include "includes/define.h"
25 #include "includes/element.h"
26 #include "includes/variables.h"
27 #include "includes/serializer.h"
28 #include "utilities/geometry_utilities.h"
29 #include "includes/cfd_variables.h"
32 
33 // Application includes
35 
36 
37 namespace Kratos
38 {
39 
42 
46 
50 
54 
58 
69 template< unsigned int TDim, unsigned int TNumNodes>
71 {
72 public:
75 
77  constexpr static unsigned int Dim = TDim;
78  constexpr static unsigned int NumNodes = TNumNodes;
79  constexpr static unsigned int BlockSize = Dim + 2;
80  constexpr static unsigned int DofSize = NumNodes * BlockSize;
81 
84 
86  {
98 
101 
102  double h; // Element size
103  double volume; // In 2D: element area. In 3D: element volume
104  double mu; // Dynamic viscosity
105  double nu; // Kinematic viscosity
106  double nu_sc; // Kinematic viscosity (shock capturing)
107  double lambda; // Heat conductivity
108  double lambda_sc; // Heat conductivity (shock capturing)
109  double c_v; // Heat capacity at constant volume
110  double gamma; // Heat capacity ratio
111 
112  bool UseOSS; // Use orthogonal subscales
113  bool ShockCapturing; // Activate shock capturing
114  };
115 
119 
122  IndexType NewId,
123  GeometryType::Pointer pGeometry)
124  : Element(NewId, pGeometry)
125  {}
126 
128  IndexType NewId,
129  GeometryType::Pointer pGeometry,
130  PropertiesType::Pointer pProperties)
131  : Element(NewId, pGeometry, pProperties)
132  {}
133 
135  ~CompressibleNavierStokesExplicit() override = default;
136 
140 
141 
145 
146  Element::Pointer Create(
147  IndexType NewId,
148  NodesArrayType const& rThisNodes,
149  PropertiesType::Pointer pProperties) const override
150  {
151  KRATOS_TRY
152  return Kratos::make_intrusive< CompressibleNavierStokesExplicit < TDim, TNumNodes > >(NewId, this->GetGeometry().Create(rThisNodes), pProperties);
153  KRATOS_CATCH("");
154  }
155 
156  Element::Pointer Create(
157  IndexType NewId,
158  GeometryType::Pointer pGeom,
159  PropertiesType::Pointer pProperties) const override
160  {
161  KRATOS_TRY
162  return Kratos::make_intrusive< CompressibleNavierStokesExplicit < TDim, TNumNodes > >(NewId, pGeom, pProperties);
163  KRATOS_CATCH("");
164  }
165 
177  MatrixType& rLeftHandSideMatrix,
178  VectorType& rRightHandSideVector,
179  const ProcessInfo& rCurrentProcessInfo) override
180  {
181  KRATOS_TRY
182 
183  KRATOS_ERROR << "Calling the CalculateLocalSystem() method for the explicit compressible Navier-Stokes element.";
184 
185  KRATOS_CATCH("")
186  }
187 
198  VectorType &rRightHandSideVector,
199  const ProcessInfo &rCurrentProcessInfo) override
200  {
201  KRATOS_TRY
202 
203  KRATOS_ERROR << "Calling the CalculateRightHandSide() method for the explicit compressible Navier-Stokes element. Call the CalculateRightHandSideInternal() instead.";
204 
205  KRATOS_CATCH("")
206  }
207 
218  void AddExplicitContribution(const ProcessInfo &rCurrentProcessInfo) override;
219 
226  virtual void CalculateMassMatrix(
227  MatrixType &rMassMatrix,
228  const ProcessInfo &rCurrentProcessInfo) override;
229 
238  VectorType& rLumpedMassVector,
239  const ProcessInfo& rCurrentProcessInfo) const override;
240 
249  int Check(const ProcessInfo& rCurrentProcessInfo) const override;
250 
251  void Calculate(
252  const Variable<double>& rVariable,
253  double& Output,
254  const ProcessInfo& rCurrentProcessInfo) override;
255 
256  void Calculate(
257  const Variable<array_1d<double, 3 > >& rVariable,
258  array_1d<double, 3 > & Output,
259  const ProcessInfo& rCurrentProcessInfo) override;
260 
261  void Calculate(
262  const Variable<Matrix>& rVariable,
263  Matrix & Output,
264  const ProcessInfo& rCurrentProcessInfo) override;
265 
267  const Variable<double>& rVariable,
268  std::vector<double>& rOutput,
269  const ProcessInfo& rCurrentProcessInfo) override;
270 
272  const Variable<array_1d<double,3>>& rVariable,
273  std::vector<array_1d<double,3>>& rOutput,
274  const ProcessInfo& rCurrentProcessInfo) override;
275 
279 
280 
284 
285 
289 
290  const Parameters GetSpecifications() const override;
291 
293  std::string Info() const override
294  {
295  return "CompressibleNavierStokesExplicit #";
296  }
297 
299  void PrintInfo(std::ostream& rOStream) const override
300  {
301  rOStream << Info() << Id();
302  }
303 
305  void PrintData(std::ostream& rOStream) const override
306  {
307  pGetGeometry()->PrintData(rOStream);
308  }
309 
313 
314 
316 protected:
319 
320 
324 
331  EquationIdVectorType &rResult,
332  const ProcessInfo &rCurrentProcessInfo) const override;
333 
340  DofsVectorType &ElementalDofList,
341  const ProcessInfo &rCurrentProcessInfo) const override;
342 
346 
348 
352 
360  ElementDataStruct& rData,
361  const ProcessInfo& rCurrentProcessInfo);
362 
371  BoundedVector<double, BlockSize * TNumNodes>& rRightHandSideBoundedVector,
372  const ProcessInfo& rCurrentProcessInfo);
373 
381  void CalculateMomentumProjection(const ProcessInfo& rCurrentProcessInfo);
382 
390  void CalculateDensityProjection(const ProcessInfo& rCurrentProcessInfo);
391 
399  void CalculateTotalEnergyProjection(const ProcessInfo& rCurrentProcessInfo);
400 
404 
405 
409 
410 
414 
415 
417 private:
420 
421 
425 
426 
430 
431  friend class Serializer;
432 
433  void save(Serializer& rSerializer) const override
434  {
436  }
437 
438  void load(Serializer& rSerializer) override
439  {
441  }
442 
446 
447  GeometryData::IntegrationMethod GetIntegrationMethod() const override;
448 
454  double CalculateMidPointVelocityDivergence() const;
455 
461  double CalculateMidPointSoundVelocity() const;
462 
468  array_1d<double,3> CalculateMidPointDensityGradient() const;
469 
475  array_1d<double,3> CalculateMidPointTemperatureGradient() const;
476 
482  array_1d<double,3> CalculateMidPointVelocityRotational() const;
483 
489  BoundedMatrix<double, 3, 3> CalculateMidPointVelocityGradient() const;
490 
494 
495 
499 
500 
504 
506 };
510 
511 
515 
516 
518 
519 
521 
522 template <unsigned int TDim, unsigned int TNumNodes>
524 {
525  KRATOS_TRY
526 
527  // Perform basic element checks
528  int ErrorCode = Kratos::Element::Check(rCurrentProcessInfo);
529  if (ErrorCode != 0) {
530  return ErrorCode;
531  }
532 
533  // Check that the element's nodes contain all required SolutionStepData and Degrees of freedom
534  for (unsigned int i = 0; i < TNumNodes; ++i) {
535  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].SolutionStepsDataHas(DENSITY)) << "Missing DENSITY variable on solution step data for node " << this->GetGeometry()[i].Id();
536  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].SolutionStepsDataHas(MOMENTUM)) << "Missing MOMENTUM variable on solution step data for node " << this->GetGeometry()[i].Id();
537  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].SolutionStepsDataHas(TOTAL_ENERGY)) << "Missing TOTAL_ENERGY variable on solution step data for node " << this->GetGeometry()[i].Id();
538  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].SolutionStepsDataHas(BODY_FORCE)) << "Missing BODY_FORCE variable on solution step data for node " << this->GetGeometry()[i].Id();
539  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].SolutionStepsDataHas(HEAT_SOURCE)) << "Missing HEAT_SOURCE variable on solution step data for node " << this->GetGeometry()[i].Id();
540 
541  // Activate as soon as we start using the explicit DOF based strategy
542  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].HasDofFor(DENSITY)) << "Missing DENSITY DOF in node ", this->GetGeometry()[i].Id();
543  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].HasDofFor(MOMENTUM_X) || this->GetGeometry()[i].HasDofFor(MOMENTUM_Y)) << "Missing MOMENTUM component DOF in node ", this->GetGeometry()[i].Id();
544  if constexpr (TDim == 3) {
545  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].HasDofFor(MOMENTUM_Z)) << "Missing MOMENTUM component DOF in node ", this->GetGeometry()[i].Id();
546  }
547  KRATOS_ERROR_IF_NOT(this->GetGeometry()[i].HasDofFor(TOTAL_ENERGY)) << "Missing TOTAL_ENERGY DOF in node ", this->GetGeometry()[i].Id();
548  }
549 
550  return 0;
551 
552  KRATOS_CATCH("");
553 }
554 
555 template <unsigned int TDim, unsigned int TNumNodes>
557  const Variable<double>& rVariable,
558  double& Output,
559  const ProcessInfo& rCurrentProcessInfo)
560 {
561  // Lumped projection terms
562  if (rVariable == DENSITY_PROJECTION) {
563  CalculateDensityProjection(rCurrentProcessInfo);
564  } else if (rVariable == TOTAL_ENERGY_PROJECTION) {
565  CalculateTotalEnergyProjection(rCurrentProcessInfo);
566  } else if (rVariable == VELOCITY_DIVERGENCE) {
567  Output = CalculateMidPointVelocityDivergence();
568  } else if (rVariable == SOUND_VELOCITY) {
569  Output = CalculateMidPointSoundVelocity();
570  } else {
571  KRATOS_ERROR << "Variable not implemented." << std::endl;
572  }
573 }
574 
575 template <unsigned int TDim, unsigned int TNumNodes>
577  const Variable<array_1d<double, 3 > >& rVariable,
578  array_1d<double, 3 > & Output,
579  const ProcessInfo& rCurrentProcessInfo)
580 {
581  if (rVariable == DENSITY_GRADIENT) {
582  Output = CalculateMidPointDensityGradient();
583  } else if (rVariable == TEMPERATURE_GRADIENT) {
584  Output = CalculateMidPointTemperatureGradient();
585  } else if (rVariable == VELOCITY_ROTATIONAL) {
586  Output = CalculateMidPointVelocityRotational();
587  } else if (rVariable == MOMENTUM_PROJECTION) {
588  CalculateMomentumProjection(rCurrentProcessInfo);
589  } else {
590  KRATOS_ERROR << "Variable not implemented." << std::endl;
591  }
592 }
593 
594 
595 template <unsigned int TDim, unsigned int TNumNodes>
597  const Variable<Matrix>& rVariable,
598  Matrix & Output,
599  const ProcessInfo& rCurrentProcessInfo)
600 {
601  if (rVariable == VELOCITY_GRADIENT) {
602  Output = CalculateMidPointVelocityGradient();
603  } else {
604  KRATOS_ERROR << "Variable not implemented." << std::endl;
605  }
606 }
607 
608 template <unsigned int TDim, unsigned int TNumNodes>
610  const Variable<double>& rVariable,
611  std::vector<double>& rOutput,
612  const ProcessInfo& rCurrentProcessInfo)
613 {
614  const auto& r_geometry = GetGeometry();
615  const auto& r_integration_points = r_geometry.IntegrationPoints();
616  if (rOutput.size() != r_integration_points.size()) {
617  rOutput.resize( r_integration_points.size() );
618  }
619 
620  if (rVariable == SHOCK_SENSOR) {
621  const double sc = this->GetValue(SHOCK_SENSOR);
622  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
623  rOutput[i_gauss] = sc;
624  }
625  } else if (rVariable == SHEAR_SENSOR) {
626  const double sc = this->GetValue(SHEAR_SENSOR);
627  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
628  rOutput[i_gauss] = sc;
629  }
630  } else if (rVariable == THERMAL_SENSOR) {
631  const double sc = this->GetValue(THERMAL_SENSOR);
632  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
633  rOutput[i_gauss] = sc;
634  }
635  } else if (rVariable == ARTIFICIAL_CONDUCTIVITY) {
636  const double k_star = this->GetValue(ARTIFICIAL_CONDUCTIVITY);
637  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
638  rOutput[i_gauss] = k_star;
639  }
640  } else if (rVariable == ARTIFICIAL_BULK_VISCOSITY) {
641  const double beta_star = this->GetValue(ARTIFICIAL_BULK_VISCOSITY);
642  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
643  rOutput[i_gauss] = beta_star;
644  }
645  } else if (rVariable == VELOCITY_DIVERGENCE) {
646  const double div_v = CalculateMidPointVelocityDivergence();
647  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
648  rOutput[i_gauss] = div_v;
649  }
650  } else {
651  KRATOS_ERROR << "Variable not implemented." << std::endl;
652  }
653 }
654 
655 template <unsigned int TDim, unsigned int TNumNodes>
657  const Variable<array_1d<double,3>>& rVariable,
658  std::vector<array_1d<double,3>>& rOutput,
659  const ProcessInfo& rCurrentProcessInfo)
660 {
661  const auto& r_geometry = GetGeometry();
662  const auto& r_integration_points = r_geometry.IntegrationPoints();
663  if (rOutput.size() != r_integration_points.size()) {
664  rOutput.resize( r_integration_points.size() );
665  }
666 
667  if (rVariable == DENSITY_GRADIENT) {
668  const array_1d<double,3> rho_grad = CalculateMidPointDensityGradient();
669  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
670  rOutput[i_gauss] = rho_grad;
671  }
672  } else if (rVariable == TEMPERATURE_GRADIENT) {
673  const array_1d<double,3> temp_grad = CalculateMidPointTemperatureGradient();
674 
675  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
676  rOutput[i_gauss] = temp_grad;
677  }
678  } else if (rVariable == VELOCITY_ROTATIONAL) {
679  const array_1d<double,3> rot_v = CalculateMidPointVelocityRotational();
680  for (unsigned int i_gauss = 0; i_gauss < r_integration_points.size(); ++i_gauss) {
681  rOutput[i_gauss] = rot_v;
682  }
683  } else {
684  KRATOS_ERROR << "Variable not implemented." << std::endl;
685  }
686 }
687 
702 namespace CompressibleNavierStokesExplicitInternal
703 {
704  template<unsigned int TDim, unsigned int TNumNodes>
706 
707 
708  constexpr bool IsSimplex(const unsigned int dimensions, const unsigned int nnodes)
709  {
710  return dimensions == nnodes-1;
711  }
712 
713  // Specialization for simplex geometries
714  template<unsigned int TDim, unsigned int TNumNodes>
715  static typename std::enable_if<IsSimplex(TDim, TNumNodes), void>::type ComputeGeometryData(
716  const Geometry<Node> & rGeometry,
718  {
719  GeometryUtils::CalculateGeometryData(rGeometry, rData.DN_DX, rData.N, rData.volume);
721  }
722 
728  template<unsigned int TDim, unsigned int TNumNodes>
729  static typename std::enable_if<!IsSimplex(TDim, TNumNodes), void>::type ComputeGeometryData(
730  const Geometry<Node> & rGeometry,
732  {
733  rData.volume = rGeometry.DomainSize();
735  }
736 }
737 
738 
739 template <unsigned int TDim, unsigned int TNumNodes>
741  ElementDataStruct &rData,
742  const ProcessInfo &rCurrentProcessInfo)
743 {
744  // Getting data for the given geometry
745  const auto& r_geometry = GetGeometry();
746 
747  // Loads shape function info only if jacobian is uniform
748  CompressibleNavierStokesExplicitInternal::ComputeGeometryData<TDim, TNumNodes>(r_geometry, rData);
749 
750  // Database access to all of the variables needed
751  Properties &r_properties = this->GetProperties();
752  rData.mu = r_properties.GetValue(DYNAMIC_VISCOSITY);
753  rData.lambda = r_properties.GetValue(CONDUCTIVITY);
754  rData.c_v = r_properties.GetValue(SPECIFIC_HEAT); // TODO: WE SHOULD SPECIFY WHICH ONE --> CREATE SPECIFIC_HEAT_CONSTANT_VOLUME
755  rData.gamma = r_properties.GetValue(HEAT_CAPACITY_RATIO);
756 
757  rData.UseOSS = rCurrentProcessInfo[OSS_SWITCH];
758  rData.ShockCapturing = rCurrentProcessInfo[SHOCK_CAPTURING_SWITCH];
759 
760  // Magnitudes to calculate the time derivatives
761  const double time_step = rCurrentProcessInfo[DELTA_TIME];
762  const double theta = rCurrentProcessInfo[TIME_INTEGRATION_THETA];
763  const double aux_theta = theta > 0 ? 1.0 / (theta * time_step) : 0.0;
764 
765  // Get nodal values
766  if (rData.UseOSS) {
767  for (unsigned int i = 0; i < TNumNodes; ++i) {
768  const auto& r_node = r_geometry[i];
769  // Vector data
770  const array_1d<double,3>& r_momentum = r_node.FastGetSolutionStepValue(MOMENTUM);
771  const array_1d<double,3>& r_momentum_old = r_node.FastGetSolutionStepValue(MOMENTUM, 1);
772  const array_1d<double,3>& r_momentum_projection = r_node.GetValue(MOMENTUM_PROJECTION);
773  const array_1d<double,3> mom_inc = r_momentum - r_momentum_old;
774  const auto& r_body_force = r_node.FastGetSolutionStepValue(BODY_FORCE);
775  for (unsigned int k = 0; k < TDim; ++k) {
776  rData.U(i, k + 1) = r_momentum[k];
777  rData.dUdt(i, k + 1) = aux_theta * mom_inc[k];
778  rData.ResProj(i, k + 1) = r_momentum_projection[k];
779  rData.f_ext(i, k) = r_body_force[k];
780  }
781  // Density data
782  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
783  const double& r_rho_old = r_node.FastGetSolutionStepValue(DENSITY, 1);
784  const double rho_inc = r_rho - r_rho_old;
785  rData.U(i, 0) = r_rho;
786  rData.dUdt(i, 0) = aux_theta * rho_inc;
787  rData.ResProj(i, 0) = r_node.GetValue(DENSITY_PROJECTION);
788  // Total energy data
789  const double& r_tot_ener = r_node.FastGetSolutionStepValue(TOTAL_ENERGY);
790  const double& r_tot_ener_old = r_node.FastGetSolutionStepValue(TOTAL_ENERGY, 1);
791  const double tot_ener_inc = r_tot_ener - r_tot_ener_old;
792  rData.U(i, TDim + 1) = r_tot_ener;
793  rData.dUdt(i, TDim + 1) = aux_theta * tot_ener_inc;
794  rData.ResProj(i, TDim + 1) = r_node.GetValue(TOTAL_ENERGY_PROJECTION);
795  // Source data
796  rData.r_ext(i) = r_node.FastGetSolutionStepValue(HEAT_SOURCE);
797  rData.m_ext(i) = r_node.FastGetSolutionStepValue(MASS_SOURCE);
798  // Shock capturing data
799  rData.alpha_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_MASS_DIFFUSIVITY);
800  rData.mu_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_DYNAMIC_VISCOSITY);
801  rData.beta_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_BULK_VISCOSITY);
802  rData.lamb_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_CONDUCTIVITY);
803  }
804  } else {
805  for (unsigned int i = 0; i < TNumNodes; ++i) {
806  const auto& r_node = r_geometry[i];
807  // Vector data
808  const array_1d<double,3>& r_momentum = r_node.FastGetSolutionStepValue(MOMENTUM);
809  const array_1d<double,3>& r_momentum_old = r_node.FastGetSolutionStepValue(MOMENTUM, 1);
810  const array_1d<double,3> mom_inc = r_momentum - r_momentum_old;
811  const auto& r_body_force = r_node.FastGetSolutionStepValue(BODY_FORCE);
812  for (unsigned int k = 0; k < TDim; ++k) {
813  rData.U(i, k + 1) = r_momentum[k];
814  rData.dUdt(i, k + 1) = aux_theta * mom_inc[k];
815  rData.f_ext(i, k) = r_body_force[k];
816  }
817  // Density data
818  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
819  const double& r_rho_old = r_node.FastGetSolutionStepValue(DENSITY, 1);
820  rData.U(i, 0) = r_rho;
821  rData.dUdt(i, 0) = aux_theta * (r_rho - r_rho_old);
822  // Total energy data
823  const double& r_tot_ener = r_node.FastGetSolutionStepValue(TOTAL_ENERGY);
824  const double& r_tot_ener_old = r_node.FastGetSolutionStepValue(TOTAL_ENERGY, 1);
825  rData.U(i, TDim + 1) = r_tot_ener;
826  rData.dUdt(i, TDim + 1) = aux_theta * (r_tot_ener - r_tot_ener_old);
827  // Source data
828  rData.r_ext(i) = r_node.FastGetSolutionStepValue(HEAT_SOURCE);
829  rData.m_ext(i) = r_node.FastGetSolutionStepValue(MASS_SOURCE);
830  // Shock capturing data
831  rData.alpha_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_MASS_DIFFUSIVITY);
832  rData.mu_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_DYNAMIC_VISCOSITY);
833  rData.beta_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_BULK_VISCOSITY);
834  rData.lamb_sc_nodes(i) = r_node.GetValue(ARTIFICIAL_CONDUCTIVITY);
835  }
836  }
837 }
838 
839 template <unsigned int TDim, unsigned int TNumNodes>
841 {
842  // Get geometry data
843  const auto& r_geom = GetGeometry();
844  const unsigned int NumNodes = r_geom.PointsNumber();
846  r_geom.ShapeFunctionsIntegrationPointsGradients(dNdX_container, GeometryData::IntegrationMethod::GI_GAUSS_1);
847  const auto& r_dNdX = dNdX_container[0];
848 
849  // Calculate midpoint magnitudes
850  array_1d<double,3> midpoint_grad_rho = ZeroVector(3);
851  for (unsigned int i_node = 0; i_node < NumNodes; ++i_node) {
852  auto& r_node = r_geom[i_node];
853  const auto node_dNdX = row(r_dNdX, i_node);
854  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
855  for (unsigned int d1 = 0; d1 < TDim; ++d1) {
856  midpoint_grad_rho[d1] += node_dNdX(d1) * r_rho;
857  }
858  }
859 
860  return midpoint_grad_rho;
861 }
862 
863 // TODO: IN HERE WE HAVE LINEARIZED THE DERIVATIVE... CHECK IF WE SHOULD PROPERLY COMPUTE IT
864 template <unsigned int TDim, unsigned int TNumNodes>
865 array_1d<double,3> CompressibleNavierStokesExplicit<TDim, TNumNodes>::CalculateMidPointTemperatureGradient() const
866 {
867  // Get geometry data
868  const auto& r_geom = GetGeometry();
869  const unsigned int NumNodes = r_geom.PointsNumber();
871  r_geom.ShapeFunctionsIntegrationPointsGradients(dNdX_container, GeometryData::IntegrationMethod::GI_GAUSS_1);
872  const auto& r_dNdX = dNdX_container[0];
873 
874  // Calculate midpoint magnitudes
875  const double c_v = GetProperties()[SPECIFIC_HEAT];
876  array_1d<double,3> midpoint_grad_temp = ZeroVector(3);
877  for (unsigned int i_node = 0; i_node < NumNodes; ++i_node) {
878  auto& r_node = r_geom[i_node];
879  const auto node_dNdX = row(r_dNdX, i_node);
880  const auto& r_mom = r_node.FastGetSolutionStepValue(MOMENTUM);
881  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
882  const double& r_tot_ener = r_node.FastGetSolutionStepValue(TOTAL_ENERGY);
883  const array_1d<double, 3> vel = r_mom / r_rho;
884  const double temp = (r_tot_ener / r_rho - 0.5 * inner_prod(vel, vel)) / c_v;
885  for (unsigned int d1 = 0; d1 < TDim; ++d1) {
886  midpoint_grad_temp[d1] += node_dNdX(d1) * temp;
887  }
888  }
889 
890  return midpoint_grad_temp;
891 }
892 
893 template <unsigned int TDim, unsigned int TNumNodes>
894 double CompressibleNavierStokesExplicit<TDim, TNumNodes>::CalculateMidPointSoundVelocity() const
895 {
896  // Get geometry data
897  const auto& r_geom = GetGeometry();
898  const unsigned int NumNodes = r_geom.PointsNumber();
899 
900  // Calculate midpoint magnitudes
901  double midpoint_rho = 0.0;
902  double midpoint_tot_ener = 0.0;
903  array_1d<double,TDim> midpoint_mom = ZeroVector(TDim);
904  for (unsigned int i_node = 0; i_node < NumNodes; ++i_node) {
905  auto& r_node = r_geom[i_node];
906  const auto& r_mom = r_node.FastGetSolutionStepValue(MOMENTUM);
907  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
908  const double& r_tot_ener = r_node.FastGetSolutionStepValue(TOTAL_ENERGY);
909  midpoint_rho += r_rho;
910  midpoint_tot_ener += r_tot_ener;
911  for (unsigned int d1 = 0; d1 < TDim; ++d1) {
912  midpoint_mom[d1] += r_mom(d1);
913  }
914  }
915  midpoint_rho /= NumNodes;
916  midpoint_mom /= NumNodes;
917  midpoint_tot_ener /= NumNodes;
918 
919  // Calculate midpoint speed of sound
920  const auto& r_prop = GetProperties();
921  const double c_v = r_prop.GetValue(SPECIFIC_HEAT);
922  const double gamma = r_prop.GetValue(HEAT_CAPACITY_RATIO);
923  const double temp = (midpoint_tot_ener / midpoint_rho - inner_prod(midpoint_mom, midpoint_mom) / (2 * std::pow(midpoint_rho, 2))) / c_v;
924  double midpoint_c = std::sqrt(gamma * (gamma - 1.0) * c_v * temp);
925  return midpoint_c;
926 }
927 
928 template <unsigned int TDim, unsigned int TNumNodes>
929 double CompressibleNavierStokesExplicit<TDim, TNumNodes>::CalculateMidPointVelocityDivergence() const
930 {
931  // Get geometry data
932  const auto& r_geom = GetGeometry();
933  const unsigned int NumNodes = r_geom.PointsNumber();
935  r_geom.ShapeFunctionsIntegrationPointsGradients(dNdX_container, GeometryData::IntegrationMethod::GI_GAUSS_1);
936  const auto& r_dNdX = dNdX_container[0];
937 
938  // Calculate midpoint magnitudes
939  double midpoint_rho = 0.0;
940  double midpoint_div_mom = 0.0;
941  array_1d<double,TDim> midpoint_mom = ZeroVector(TDim);
942  array_1d<double,TDim> midpoint_grad_rho = ZeroVector(TDim);
943  for (unsigned int i_node = 0; i_node < NumNodes; ++i_node) {
944  auto& r_node = r_geom[i_node];
945  const auto node_dNdX = row(r_dNdX, i_node);
946  const auto& r_mom = r_node.FastGetSolutionStepValue(MOMENTUM);
947  const double& r_rho = r_node.FastGetSolutionStepValue(DENSITY);
948  midpoint_rho += r_rho;
949  for (unsigned int d1 = 0; d1 < TDim; ++d1) {
950  midpoint_mom[d1] += r_mom(d1);
951  midpoint_div_mom += node_dNdX(d1) * r_mom(d1);
952  midpoint_grad_rho[d1] += node_dNdX(d1) * r_rho;
953  }
954  }
955  midpoint_rho /= NumNodes;
956  midpoint_mom /= NumNodes;
957 
958  // Calculate velocity divergence
959  // Note that the formulation is written in conservative variables. Hence we do div(mom/rho).
960  double midpoint_div_v = (midpoint_rho * midpoint_div_mom - inner_prod(midpoint_mom, midpoint_grad_rho)) / std::pow(midpoint_rho, 2);
961  return midpoint_div_v;
962 }
963 
964 template <unsigned int TDim, unsigned int TNumNodes>
966  VectorType& rLumpedMassVector,
967  const ProcessInfo& rCurrentProcessInfo) const
968 {
969  // Initialize the lumped mass vector
970  constexpr IndexType size = TNumNodes * BlockSize;
971  if (rLumpedMassVector.size() != BlockSize) {
972  rLumpedMassVector.resize(size, false);
973  }
974 
975  // Fill the lumped mass vector
976  const double nodal_mass = GetGeometry().DomainSize() / TNumNodes;
977  std::fill(rLumpedMassVector.begin(),rLumpedMassVector.end(),nodal_mass);
978 }
979 
980 
981 template <unsigned int TDim, unsigned int TNumNodes>
983 {
984  // Calculate the explicit residual vector
986  CalculateRightHandSideInternal(rhs, rCurrentProcessInfo);
987 
988  // Add the residual contribution
989  // Note that the reaction is indeed the formulation residual
990  auto& r_geometry = GetGeometry();
991 
992  for (IndexType i_node = 0; i_node < NumNodes; ++i_node)
993  {
994  auto& r_node = r_geometry[i_node];
995 
996  IndexType i_dof = BlockSize * i_node;
997 
998  AtomicAdd(r_node.FastGetSolutionStepValue(REACTION_DENSITY), rhs[i_dof++]);
999 
1000  for (IndexType d = 0; d < Dim; ++d)
1001  {
1002  AtomicAdd(r_node.FastGetSolutionStepValue(REACTION)[d], rhs[i_dof++]);
1003  }
1004 
1005  AtomicAdd(r_node.FastGetSolutionStepValue(REACTION_ENERGY), rhs[i_dof]);
1006  }
1007 }
1008 
1009 template <unsigned int TDim, unsigned int TNumNodes>
1011 {
1012  const Parameters specifications = Parameters(R"({
1013  "time_integration" : ["explicit"],
1014  "framework" : "eulerian",
1015  "symmetric_lhs" : false,
1016  "positive_definite_lhs" : true,
1017  "output" : {
1018  "gauss_point" : ["SHOCK_SENSOR","SHEAR_SENSOR","THERMAL_SENSOR","ARTIFICIAL_CONDUCTIVITY","ARTIFICIAL_BULK_VISCOSITY","VELOCITY_DIVERGENCE"],
1019  "nodal_historical" : ["DENSITY","MOMENTUM","TOTAL_ENERGY"],
1020  "nodal_non_historical" : ["ARTIFICIAL_MASS_DIFFUSIVITY","ARTIFICIAL_DYNAMIC_VISCOSITY","ARTIFICIAL_BULK_VISCOSITY","ARTIFICIAL_CONDUCTIVITY","DENSITY_PROJECTION","MOMENTUM_PROJECTION","TOTAL_ENERGY_PROJECTION"],
1021  "entity" : []
1022  },
1023  "required_variables" : ["DENSITY","MOMENTUM","TOTAL_ENERGY","BODY_FORCE","HEAT_SOURCE"],
1024  "required_dofs" : [],
1025  "flags_used" : [],
1026  "compatible_geometries" : ["Triangle2D3","Quadrilateral2D4","Tetrahedra3D4"],
1027  "element_integrates_in_time" : true,
1028  "compatible_constitutive_laws": {
1029  "type" : [],
1030  "dimension" : [],
1031  "strain_size" : []
1032  },
1033  "required_polynomial_degree_of_geometry" : 1,
1034  "documentation" :
1035  "This element implements a compressible Navier-Stokes formulation written in conservative variables. A Variational MultiScales (VMS) stabilization technique, both with Algebraic SubGrid Scales (ASGS) and Orthogonal Subgrid Scales (OSS), is used. This element is compatible with both entropy-based and physics-based shock capturing techniques."
1036  })");
1037 
1038  if constexpr (TDim == 2) {
1039  std::vector<std::string> dofs_2d({"DENSITY","MOMENTUM_X","MOMENTUM_Y","TOTAL_ENERGY"});
1040  specifications["required_dofs"].SetStringArray(dofs_2d);
1041  } else {
1042  std::vector<std::string> dofs_3d({"DENSITY","MOMENTUM_X","MOMENTUM_Y","MOMENTUM_Z","TOTAL_ENERGY"});
1043  specifications["required_dofs"].SetStringArray(dofs_3d);
1044  }
1045 
1046  return specifications;
1047 }
1048 
1049 } // namespace Kratos.
1050 
1051 #endif // KRATOS_COMPRESSIBLE_NAVIER_STOKES_EXPLICIT_H_INCLUDED defined
Compressible Navier-Stokes explicit element This element implements a compressible Navier-Stokes expl...
Definition: compressible_navier_stokes_explicit.h:71
constexpr static unsigned int DofSize
Definition: compressible_navier_stokes_explicit.h:80
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: compressible_navier_stokes_explicit.h:305
void GetDofList(DofsVectorType &ElementalDofList, const ProcessInfo &rCurrentProcessInfo) const override
void CalculateDensityProjection(const ProcessInfo &rCurrentProcessInfo)
Calculate the density projection Auxiliary method to calculate the denstiy projections for the OSS....
void Calculate(const Variable< array_1d< double, 3 > > &rVariable, array_1d< double, 3 > &Output, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:576
void CalculateTotalEnergyProjection(const ProcessInfo &rCurrentProcessInfo)
Calculate the total energy projection Auxiliary method to calculate the total energy projections for ...
virtual void CalculateMassMatrix(MatrixType &rMassMatrix, const ProcessInfo &rCurrentProcessInfo) override
void Calculate(const Variable< Matrix > &rVariable, Matrix &Output, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:596
void CalculateOnIntegrationPoints(const Variable< array_1d< double, 3 >> &rVariable, std::vector< array_1d< double, 3 >> &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:656
void CalculateRightHandSideInternal(BoundedVector< double, BlockSize *TNumNodes > &rRightHandSideBoundedVector, const ProcessInfo &rCurrentProcessInfo)
Internal CalculateRightHandSide() method This auxiliary RHS calculated method is created to bypass th...
void EquationIdVector(EquationIdVectorType &rResult, const ProcessInfo &rCurrentProcessInfo) const override
Element::Pointer Create(IndexType NewId, NodesArrayType const &rThisNodes, PropertiesType::Pointer pProperties) const override
It creates a new element pointer.
Definition: compressible_navier_stokes_explicit.h:146
Element::Pointer Create(IndexType NewId, GeometryType::Pointer pGeom, PropertiesType::Pointer pProperties) const override
It creates a new element pointer.
Definition: compressible_navier_stokes_explicit.h:156
constexpr static unsigned int Dim
Compile-time known quantities.
Definition: compressible_navier_stokes_explicit.h:77
void CalculateLocalSystem(MatrixType &rLeftHandSideMatrix, VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:176
std::string Info() const override
Turn back information as a string.
Definition: compressible_navier_stokes_explicit.h:293
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: compressible_navier_stokes_explicit.h:299
constexpr static unsigned int NumNodes
Definition: compressible_navier_stokes_explicit.h:78
void FillElementData(ElementDataStruct &rData, const ProcessInfo &rCurrentProcessInfo)
Fill element data Auxiliary function to fill the element data structure.
Definition: compressible_navier_stokes_explicit.h:740
void CalculateMomentumProjection(const ProcessInfo &rCurrentProcessInfo)
Calculate the momentum projection Auxiliary method to calculate the momentum projections for the OSS....
void AddExplicitContribution(const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:982
void Calculate(const Variable< double > &rVariable, double &Output, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:556
KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(CompressibleNavierStokesExplicit)
Counted pointer of.
CompressibleNavierStokesExplicit(IndexType NewId, GeometryType::Pointer pGeometry)
Default constructor.
Definition: compressible_navier_stokes_explicit.h:121
void CalculateRightHandSide(VectorType &rRightHandSideVector, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:197
virtual void CalculateLumpedMassVector(VectorType &rLumpedMassVector, const ProcessInfo &rCurrentProcessInfo) const override
Calculate the lumped mass vector This is called during the assembling process in order to calculate t...
Definition: compressible_navier_stokes_explicit.h:965
const Parameters GetSpecifications() const override
This method provides the specifications/requirements of the element.
Definition: compressible_navier_stokes_explicit.h:1010
CompressibleNavierStokesExplicit(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties)
Definition: compressible_navier_stokes_explicit.h:127
void CalculateOnIntegrationPoints(const Variable< double > &rVariable, std::vector< double > &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Definition: compressible_navier_stokes_explicit.h:609
~CompressibleNavierStokesExplicit() override=default
Destructor.
int Check(const ProcessInfo &rCurrentProcessInfo) const override
Implementation of template-parameter independent methods.
Definition: compressible_navier_stokes_explicit.h:523
constexpr static unsigned int BlockSize
Definition: compressible_navier_stokes_explicit.h:79
Base class for all Elements.
Definition: element.h:60
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
static double GradientsElementSize(const BoundedMatrix< double, 3, 2 > &rDN_DX)
Element size based on the shape functions gradients. Triangle element version.
Definition: element_size_calculator.cpp:1456
static double AverageElementSize(const Geometry< Node > &rGeometry)
Average element size based on the geometry.
std::size_t IndexType
Definition: flags.h:74
GeometryType::Pointer pGetGeometry()
Returns the pointer to the geometry.
Definition: geometrical_object.h:140
GeometryType & GetGeometry()
Returns the reference of the geometry.
Definition: geometrical_object.h:158
IntegrationMethod
Definition: geometry_data.h:76
Geometry base class.
Definition: geometry.h:71
GeometryData::ShapeFunctionsGradientsType ShapeFunctionsGradientsType
Definition: geometry.h:189
virtual Pointer Create(PointsArrayType const &rThisPoints) const
Creates a new geometry pointer.
Definition: geometry.h:813
virtual double DomainSize() const
This method calculate and return length, area or volume of this geometry depending to it's dimension.
Definition: geometry.h:1371
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
IndexType Id() const
Definition: indexed_object.h:107
Definition: amatrix_interface.h:41
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
iterator end()
Definition: amatrix_interface.h:243
iterator begin()
Definition: amatrix_interface.h:241
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
void SetStringArray(const std::vector< std::string > &rValue)
This method sets the string array contained in the current Parameter.
Definition: kratos_parameters.cpp:819
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.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
TVariableType::Type & GetValue(const TVariableType &rVariable)
Definition: properties.h:228
The serialization consists in storing the state of an object into a storage format like data file or ...
Definition: serializer.h:123
#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
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
constexpr bool IsSimplex(const unsigned int dimensions, const unsigned int nnodes)
Definition: compressible_navier_stokes_explicit.h:708
static std::enable_if< IsSimplex(TDim, TNumNodes), void >::type ComputeGeometryData(const Geometry< Node > &rGeometry, ElementDataStruct< TDim, TNumNodes > &rData)
Definition: compressible_navier_stokes_explicit.h:715
typename CompressibleNavierStokesExplicit< TDim, TNumNodes >::ElementDataStruct ElementDataStruct
Definition: compressible_navier_stokes_explicit.h:705
Parameters GetValue(Parameters &rParameters, const std::string &rEntry)
Definition: add_kratos_parameters_to_python.cpp:53
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
void AtomicAdd(TDataType &target, const TDataType &value)
Definition: atomic_utilities.h:55
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
div_v
Definition: generate_convection_diffusion_explicit_element.py:150
rhs
Definition: generate_frictional_mortar_condition.py:297
type
Definition: generate_gid_list_file.py:35
float gamma
Definition: generate_two_fluid_navier_stokes.py:131
def load(f)
Definition: ode_solve.py:307
int d
Definition: ode_solve.py:397
vel
Definition: pure_conduction.py:76
int k
Definition: quadrature.py:595
float temp
Definition: rotating_cone.py:85
int nnodes
Definition: sensitivityMatrix.py:24
integer i
Definition: TensorModule.f:17
subroutine d1(DSTRAN, D, dtime, NDI, NSHR, NTENS)
Definition: TensorModule.f:594
Definition: compressible_navier_stokes_explicit.h:86
double mu
Definition: compressible_navier_stokes_explicit.h:104
BoundedMatrix< double, TNumNodes, BlockSize > dUdt
Definition: compressible_navier_stokes_explicit.h:88
BoundedMatrix< double, TNumNodes, BlockSize > U
Definition: compressible_navier_stokes_explicit.h:87
array_1d< double, TNumNodes > beta_sc_nodes
Definition: compressible_navier_stokes_explicit.h:96
array_1d< double, TNumNodes > N
Definition: compressible_navier_stokes_explicit.h:99
double lambda_sc
Definition: compressible_navier_stokes_explicit.h:108
bool UseOSS
Definition: compressible_navier_stokes_explicit.h:112
BoundedMatrix< double, TNumNodes, BlockSize > ResProj
Definition: compressible_navier_stokes_explicit.h:89
double nu_sc
Definition: compressible_navier_stokes_explicit.h:106
double volume
Definition: compressible_navier_stokes_explicit.h:103
array_1d< double, TNumNodes > lamb_sc_nodes
Definition: compressible_navier_stokes_explicit.h:97
double nu
Definition: compressible_navier_stokes_explicit.h:105
array_1d< double, TNumNodes > mu_sc_nodes
Definition: compressible_navier_stokes_explicit.h:95
array_1d< double, TNumNodes > nu_sc_node
Definition: compressible_navier_stokes_explicit.h:93
BoundedMatrix< double, TNumNodes, TDim > DN_DX
Definition: compressible_navier_stokes_explicit.h:100
bool ShockCapturing
Definition: compressible_navier_stokes_explicit.h:113
double lambda
Definition: compressible_navier_stokes_explicit.h:107
double c_v
Definition: compressible_navier_stokes_explicit.h:109
double gamma
Definition: compressible_navier_stokes_explicit.h:110
array_1d< double, TNumNodes > r_ext
Definition: compressible_navier_stokes_explicit.h:92
array_1d< double, TNumNodes > alpha_sc_nodes
Definition: compressible_navier_stokes_explicit.h:94
double h
Definition: compressible_navier_stokes_explicit.h:102
BoundedMatrix< double, TNumNodes, TDim > f_ext
Definition: compressible_navier_stokes_explicit.h:90
array_1d< double, TNumNodes > m_ext
Definition: compressible_navier_stokes_explicit.h:91