diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp
index 0971745c9c89..927d1231ff93 100644
--- a/Common/include/CConfig.hpp
+++ b/Common/include/CConfig.hpp
@@ -475,15 +475,11 @@ class CConfig {
Kind_Deform_Linear_Solver, /*!< Numerical method to deform the grid */
Kind_Deform_Linear_Solver_Prec, /*!< \brief Preconditioner of the linear solver. */
Kind_Linear_Solver, /*!< \brief Numerical solver for the implicit scheme. */
- Kind_Linear_Solver_FSI_Struc, /*!< \brief Numerical solver for the structural part in FSI problems. */
Kind_Linear_Solver_Prec, /*!< \brief Preconditioner of the linear solver. */
- Kind_Linear_Solver_Prec_FSI_Struc, /*!< \brief Preconditioner of the linear solver for the structural part in FSI problems. */
Kind_AdjTurb_Linear_Solver, /*!< \brief Numerical solver for the turbulent adjoint implicit scheme. */
Kind_AdjTurb_Linear_Prec, /*!< \brief Preconditioner of the turbulent adjoint linear solver. */
Kind_DiscAdj_Linear_Solver, /*!< \brief Linear solver for the discrete adjoint system. */
Kind_DiscAdj_Linear_Prec, /*!< \brief Preconditioner of the discrete adjoint linear solver. */
- Kind_DiscAdj_Linear_Solver_FSI_Struc, /*!< \brief Linear solver for the discrete adjoint system in the structural side of FSI problems. */
- Kind_DiscAdj_Linear_Prec_FSI_Struc, /*!< \brief Preconditioner of the discrete adjoint linear solver in the structural side of FSI problems. */
Kind_SlopeLimit, /*!< \brief Global slope limiter. */
Kind_SlopeLimit_Flow, /*!< \brief Slope limiter for flow equations.*/
Kind_SlopeLimit_Turb, /*!< \brief Slope limiter for the turbulence equation.*/
@@ -525,8 +521,6 @@ class CConfig {
Kind_FEM_Flow, /*!< \brief Finite element scheme for the flow equations. */
Kind_FEM_DG_Shock, /*!< \brief Shock capturing method for the FEM DG solver. */
Kind_Matrix_Coloring, /*!< \brief Type of matrix coloring for sparse Jacobian computation. */
- Kind_Solver_Fluid_FSI, /*!< \brief Kind of solver for the fluid in FSI applications. */
- Kind_Solver_Struc_FSI, /*!< \brief Kind of solver for the structure in FSI applications. */
Kind_BGS_RelaxMethod, /*!< \brief Kind of relaxation method for Block Gauss Seidel method in FSI problems. */
Kind_CHT_Coupling; /*!< \brief Kind of coupling method used at CHT interfaces. */
bool ReconstructionGradientRequired; /*!< \brief Enable or disable a second gradient calculation for upwind reconstruction only. */
@@ -541,7 +535,7 @@ class CConfig {
MUSCL_AdjTurb, /*!< \brief MUSCL scheme for the adj turbulence equations.*/
Use_Accurate_Jacobians; /*!< \brief Use numerically computed Jacobians for AUSM+up(2) and SLAU(2). */
bool EulerPersson; /*!< \brief Boolean to determine whether this is an Euler simulation with Persson shock capturing. */
- bool FSI_Problem, /*!< \brief Boolean to determine whether the simulation is FSI or not. */
+ bool FSI_Problem = false,/*!< \brief Boolean to determine whether the simulation is FSI or not. */
Multizone_Problem; /*!< \brief Boolean to determine whether we are solving a multizone problem. */
unsigned short nID_DV; /*!< \brief ID for the region of FEM when computed using direct differentiation. */
@@ -568,11 +562,9 @@ class CConfig {
bool Inc_Inlet_UseNormal; /*!< \brief Flag for whether to use the local normal as the flow direction for an incompressible pressure inlet. */
su2double Linear_Solver_Error; /*!< \brief Min error of the linear solver for the implicit formulation. */
su2double Deform_Linear_Solver_Error; /*!< \brief Min error of the linear solver for the implicit formulation. */
- su2double Linear_Solver_Error_FSI_Struc; /*!< \brief Min error of the linear solver for the implicit formulation in the structural side for FSI problems . */
su2double Linear_Solver_Smoother_Relaxation; /*!< \brief Relaxation factor for iterative linear smoothers. */
unsigned long Linear_Solver_Iter; /*!< \brief Max iterations of the linear solver for the implicit formulation. */
unsigned long Deform_Linear_Solver_Iter; /*!< \brief Max iterations of the linear solver for the implicit formulation. */
- unsigned long Linear_Solver_Iter_FSI_Struc; /*!< \brief Max iterations of the linear solver for FSI applications and structural solver. */
unsigned long Linear_Solver_Restart_Frequency; /*!< \brief Restart frequency of the linear solver for the implicit formulation. */
unsigned long Linear_Solver_Prec_Threads; /*!< \brief Number of threads per rank for ILU and LU_SGS preconditioners. */
unsigned short Linear_Solver_ILU_n; /*!< \brief ILU fill=in level. */
@@ -605,7 +597,7 @@ class CConfig {
su2double Min_Beta_RoeTurkel, /*!< \brief Minimum value of Beta for the Roe-Turkel low Mach preconditioner. */
Max_Beta_RoeTurkel; /*!< \brief Maximum value of Beta for the Roe-Turkel low Mach preconditioner. */
unsigned long GridDef_Nonlinear_Iter; /*!< \brief Number of nonlinear increments for grid deformation. */
- unsigned short Deform_Stiffness_Type; /*!< \brief Type of element stiffness imposed for FEA mesh deformation. */
+ unsigned short Deform_StiffnessType; /*!< \brief Type of element stiffness imposed for FEA mesh deformation. */
bool Deform_Mesh; /*!< \brief Determines whether the mesh will be deformed. */
bool Deform_Output; /*!< \brief Print the residuals during mesh deformation to the console. */
su2double Deform_Tol_Factor; /*!< \brief Factor to multiply smallest volume for deform tolerance (0.001 default) */
@@ -613,8 +605,9 @@ class CConfig {
su2double Deform_Limit; /*!< \brief Deform limit */
unsigned short FFD_Continuity; /*!< \brief Surface continuity at the intersection with the FFD */
unsigned short FFD_CoordSystem; /*!< \brief Define the coordinates system */
- su2double Deform_ElasticityMod,
- Deform_PoissonRatio; /*!< \brief Young's Modulus and poisson ratio for volume deformation stiffness model */
+ su2double Deform_ElasticityMod, /*!< \brief Young's modulus for volume deformation stiffness model */
+ Deform_PoissonRatio, /*!< \brief Poisson's ratio for volume deformation stiffness model */
+ Deform_StiffLayerSize; /*!< \brief Size of the layer of highest stiffness for wall distance-based mesh stiffness */
bool Visualize_Surface_Def; /*!< \brief Flag to visualize the surface deformacion in SU2_DEF. */
bool Visualize_Volume_Def; /*!< \brief Flag to visualize the volume deformation in SU2_DEF. */
bool FFD_Symmetry_Plane; /*!< \brief FFD symmetry plane. */
@@ -890,7 +883,6 @@ class CConfig {
string RefGeom_FEMFileName; /*!< \brief File name for reference geometry. */
unsigned short RefGeom_FileFormat; /*!< \brief Mesh input format. */
unsigned short Kind_2DElasForm; /*!< \brief Kind of bidimensional elasticity solver. */
- unsigned short nIterFSI; /*!< \brief Number of maximum number of subiterations in a FSI problem. */
unsigned short nIterFSI_Ramp; /*!< \brief Number of FSI subiterations during which a ramp is applied. */
unsigned short iInst; /*!< \brief Current instance value */
su2double AitkenStatRelax; /*!< \brief Aitken's relaxation factor (if set as static) */
@@ -988,9 +980,11 @@ class CConfig {
unsigned short Pred_Order; /*!< \brief Order of the predictor for FSI applications. */
unsigned short Kind_Interpolation; /*!< \brief type of interpolation to use for FSI applications. */
bool ConservativeInterpolation; /*!< \brief Conservative approach for non matching mesh interpolation. */
+ unsigned short NumNearestNeighbors; /*!< \brief Number of neighbors used for Nearest Neighbor interpolation. */
unsigned short Kind_RadialBasisFunction; /*!< \brief type of radial basis function to use for radial basis FSI. */
bool RadialBasisFunction_PolynomialOption; /*!< \brief Option of whether to include polynomial terms in Radial Basis Function Interpolation or not. */
- su2double RadialBasisFunction_Parameter; /*!< \brief Radial basis function parameter. */
+ su2double RadialBasisFunction_Parameter; /*!< \brief Radial basis function parameter (radius). */
+ su2double RadialBasisFunction_PruneTol; /*!< \brief Tolerance to prune the RBF interpolation matrix. */
bool Prestretch; /*!< \brief Read a reference geometry for optimization purposes. */
string Prestretch_FEMFileName; /*!< \brief File name for reference geometry. */
string FEA_FileName; /*!< \brief File name for element-based properties. */
@@ -3460,27 +3454,27 @@ class CConfig {
unsigned short GetMarker_All_ZoneInterface(unsigned short val_marker) const { return Marker_All_ZoneInterface[val_marker]; }
/*!
- * \brief Get the MixingPlane interface information for a marker val_marker.
- * \param[in] val_marker value of the marker on the grid.
- * \return 0 if is not part of the MixingPlane Interface and greater than 1 if it is part.
- */
+ * \brief Get the MixingPlane interface information for a marker val_marker.
+ * \param[in] val_marker value of the marker on the grid.
+ * \return 0 if is not part of the MixingPlane Interface and greater than 1 if it is part.
+ */
unsigned short GetMarker_All_MixingPlaneInterface(unsigned short val_marker) const { return Marker_All_MixingPlaneInterface[val_marker]; }
- /*!
- * \brief Get the Turbomachinery information for a marker val_marker.
- * \param[in] val_marker value of the marker on the grid.
- * \return 0 if is not part of the Turbomachinery and greater than 1 if it is part.
- */
+ /*!
+ * \brief Get the Turbomachinery information for a marker val_marker.
+ * \param[in] val_marker value of the marker on the grid.
+ * \return 0 if is not part of the Turbomachinery and greater than 1 if it is part.
+ */
unsigned short GetMarker_All_Turbomachinery(unsigned short val_marker) const { return Marker_All_Turbomachinery[val_marker]; }
- /*!
- * \brief Get the Turbomachinery flag information for a marker val_marker.
- * \param[in] val_marker value of the marker on the grid.
- * \return 0 if is not part of the Turbomachinery, flag INFLOW or OUTFLOW if it is part.
- */
+ /*!
+ * \brief Get the Turbomachinery flag information for a marker val_marker.
+ * \param[in] val_marker value of the marker on the grid.
+ * \return 0 if is not part of the Turbomachinery, flag INFLOW or OUTFLOW if it is part.
+ */
unsigned short GetMarker_All_TurbomachineryFlag(unsigned short val_marker) const { return Marker_All_TurbomachineryFlag[val_marker]; }
- /*!
+ /*!
* \brief Get the number of FSI interface markers val_marker.
* \param[in] void.
* \return Number of markers belonging to the FSI interface.
@@ -3619,13 +3613,41 @@ class CConfig {
*/
void SetKind_Solver(unsigned short val_solver) { Kind_Solver = val_solver; }
+ /*!
+ * \brief Return true if a fluid solver is in use.
+ */
+ bool GetFluidProblem(void) const {
+ switch (Kind_Solver) {
+ case EULER : case NAVIER_STOKES: case RANS:
+ case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS:
+ case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS:
+ case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /*!
+ * \brief Return true if a structural solver is in use.
+ */
+ bool GetStructuralProblem(void) const {
+ return (Kind_Solver == FEM_ELASTICITY) || (Kind_Solver == DISC_ADJ_FEM);
+ }
+
+ /*!
+ * \brief Return true if a heat solver is in use.
+ */
+ bool GetHeatProblem(void) const {
+ return (Kind_Solver == HEAT_EQUATION) || (Kind_Solver == DISC_ADJ_HEAT);
+ }
+
/*!
* \brief Kind of Multizone Solver.
* \return Governing equation that we are solving.
*/
unsigned short GetKind_MZSolver(void) const { return Kind_MZSolver; }
-
/*!
* \brief Governing equations of the flow (it can be different from the run time equation).
* \param[in] val_zone - Zone where the soler is applied.
@@ -4103,7 +4125,12 @@ class CConfig {
* \brief Get the type of stiffness to impose for FEA mesh deformation.
* \return type of stiffness to impose for FEA mesh deformation.
*/
- unsigned short GetDeform_Stiffness_Type(void) const { return Deform_Stiffness_Type; }
+ unsigned short GetDeform_Stiffness_Type(void) const { return Deform_StiffnessType; }
+
+ /*!
+ * \brief Get the size of the layer of highest stiffness for wall distance-based mesh stiffness.
+ */
+ su2double GetDeform_StiffLayerSize(void) const { return Deform_StiffLayerSize; }
/*!
* \brief Creates a tecplot file to visualize the volume deformation deformation made by the DEF software.
@@ -4674,7 +4701,7 @@ class CConfig {
* \brief Get the type of incompressible inlet from the list.
* \return Kind of the incompressible inlet.
*/
- unsigned short GetKind_Inc_Inlet(string val_marker);
+ unsigned short GetKind_Inc_Inlet(string val_marker) const;
/*!
* \brief Get the total number of types in Kind_Inc_Inlet list
@@ -4692,7 +4719,7 @@ class CConfig {
* \brief Get the type of incompressible outlet from the list.
* \return Kind of the incompressible outlet.
*/
- unsigned short GetKind_Inc_Outlet(string val_marker);
+ unsigned short GetKind_Inc_Outlet(string val_marker) const;
/*!
* \brief Get the damping factor applied to velocity updates at incompressible pressure inlets.
@@ -5572,7 +5599,7 @@ class CConfig {
* \return TRUE if there is a grid movement; otherwise FALSE.
*/
bool GetGrid_Movement(void) const {
- return (Kind_GridMovement != NO_MOVEMENT) || ((nKind_SurfaceMovement > 0) && !GetSurface_Movement(FLUID_STRUCTURE_STATIC));
+ return (Kind_GridMovement != NO_MOVEMENT) || (nKind_SurfaceMovement > 0);
}
/*!
@@ -5585,7 +5612,7 @@ class CConfig {
* \brief Get information about the volumetric movement.
* \return TRUE if there is a volumetric movement is required; otherwise FALSE.
*/
- bool GetVolumetric_Movement(void);
+ bool GetVolumetric_Movement(void) const;
/*!
* \brief Get information about deforming markers.
@@ -6309,102 +6336,104 @@ class CConfig {
* \brief Get the rotationally periodic donor marker for boundary val_marker.
* \return Periodic donor marker from the config information for the marker val_marker.
*/
- unsigned short GetMarker_Periodic_Donor(string val_marker);
+ unsigned short GetMarker_Periodic_Donor(string val_marker) const;
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_NetThrust(string val_marker);
+ su2double GetActDisk_NetThrust(string val_marker) const;
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_Power(string val_marker);
+ su2double GetActDisk_Power(string val_marker) const;
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_MassFlow(string val_marker);
+ su2double GetActDisk_MassFlow(string val_marker) const;
+
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_Mach(string val_marker);
+ su2double GetActDisk_Mach(string val_marker) const;
+
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_Force(string val_marker);
+ su2double GetActDisk_Force(string val_marker) const;
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_BCThrust(string val_marker);
+ su2double GetActDisk_BCThrust(string val_marker) const;
/*!
* \brief Get the origin of the actuator disk.
*/
- su2double GetActDisk_BCThrust_Old(string val_marker);
+ su2double GetActDisk_BCThrust_Old(string val_marker) const;
/*!
* \brief Get the tip radius of th actuator disk.
*/
- su2double GetActDisk_Area(string val_marker);
+ su2double GetActDisk_Area(string val_marker) const;
/*!
* \brief Get the tip radius of th actuator disk.
*/
- su2double GetActDisk_ReverseMassFlow(string val_marker);
+ su2double GetActDisk_ReverseMassFlow(string val_marker) const;
/*!
* \brief Get the thrust corffient of the actuator disk.
*/
- su2double GetActDisk_PressJump(string val_marker, unsigned short val_index);
+ su2double GetActDisk_PressJump(string val_marker, unsigned short val_index) const;
/*!
* \brief Get the thrust corffient of the actuator disk.
*/
- su2double GetActDisk_TempJump(string val_marker, unsigned short val_index);
+ su2double GetActDisk_TempJump(string val_marker, unsigned short val_index) const;
/*!
* \brief Get the rev / min of the actuator disk.
*/
- su2double GetActDisk_Omega(string val_marker, unsigned short val_index);
+ su2double GetActDisk_Omega(string val_marker, unsigned short val_index) const;
/*!
* \brief Get Actuator Disk Outlet for boundary val_marker (actuator disk inlet).
* \return Actuator Disk Outlet from the config information for the marker val_marker.
*/
- unsigned short GetMarker_CfgFile_ActDiskOutlet(string val_marker);
+ unsigned short GetMarker_CfgFile_ActDiskOutlet(string val_marker) const;
/*!
* \brief Get Actuator Disk Outlet for boundary val_marker (actuator disk inlet).
* \return Actuator Disk Outlet from the config information for the marker val_marker.
*/
- unsigned short GetMarker_CfgFile_EngineExhaust(string val_marker);
+ unsigned short GetMarker_CfgFile_EngineExhaust(string val_marker) const;
/*!
* \brief Get the internal index for a moving boundary val_marker.
* \return Internal index for a moving boundary val_marker.
*/
- unsigned short GetMarker_Moving(string val_marker);
+ unsigned short GetMarker_Moving(string val_marker) const;
/*!
* \brief Get bool if marker is moving. val_marker.
* \param[in] val_marker - String of the marker to test.
* \return Bool if the marker is a moving boundary val_marker.
*/
- bool GetMarker_Moving_Bool(string val_marker);
+ bool GetMarker_Moving_Bool(string val_marker) const;
/*!
* \brief Get the internal index for a DEFORM_MESH boundary val_marker.
* \return Internal index for a DEFORM_MESH boundary val_marker.
*/
- unsigned short GetMarker_Deform_Mesh(string val_marker);
+ unsigned short GetMarker_Deform_Mesh(string val_marker) const;
/*!
* \brief Get the internal index for a Fluid_Load boundary val_marker.
* \return Internal index for a Fluid_Load boundary val_marker.
*/
- unsigned short GetMarker_Fluid_Load(string val_marker);
+ unsigned short GetMarker_Fluid_Load(string val_marker) const;
/*!
* \brief Get the name of the surface defined in the geometry file.
@@ -6451,28 +6480,28 @@ class CConfig {
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The total temperature.
*/
- su2double GetExhaust_Temperature_Target(string val_index);
+ su2double GetExhaust_Temperature_Target(string val_index) const;
/*!
* \brief Get the total temperature at an inlet boundary.
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The total temperature.
*/
- su2double GetInlet_Ttotal(string val_index);
+ su2double GetInlet_Ttotal(string val_index) const;
/*!
* \brief Get the temperature at a supersonic inlet boundary.
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The inlet density.
*/
- su2double GetInlet_Temperature(string val_index);
+ su2double GetInlet_Temperature(string val_index) const;
/*!
* \brief Get the pressure at a supersonic inlet boundary.
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The inlet pressure.
*/
- su2double GetInlet_Pressure(string val_index);
+ su2double GetInlet_Pressure(string val_index) const;
/*!
* \brief Get the velocity vector at a supersonic inlet boundary.
@@ -6486,7 +6515,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The total pressure.
*/
- su2double GetInlet_Ptotal(string val_index);
+ su2double GetInlet_Ptotal(string val_index) const;
/*!
* \brief Set the total pressure at an inlet boundary.
@@ -6500,7 +6529,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the inlet boundary.
* \return The total pressure.
*/
- su2double GetExhaust_Pressure_Target(string val_index);
+ su2double GetExhaust_Pressure_Target(string val_index) const;
/*!
* \brief Value of the CFL reduction in LevelSet problems.
@@ -6520,7 +6549,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetOutlet_Pressure(string val_index);
+ su2double GetOutlet_Pressure(string val_index) const;
/*!
* \brief Set the back pressure (static) at an outlet boundary.
@@ -6534,14 +6563,14 @@ class CConfig {
* \param[in] val_marker - Index corresponding to the Riemann boundary.
* \return The var1
*/
- su2double GetRiemann_Var1(string val_marker);
+ su2double GetRiemann_Var1(string val_marker) const;
/*!
* \brief Get the var 2 at Riemann boundary.
* \param[in] val_marker - Index corresponding to the Riemann boundary.
* \return The var2
*/
- su2double GetRiemann_Var2(string val_marker);
+ su2double GetRiemann_Var2(string val_marker) const;
/*!
* \brief Get the Flowdir at Riemann boundary.
@@ -6555,21 +6584,21 @@ class CConfig {
* \param[in] val_marker - Index corresponding to the Riemann boundary.
* \return Kind data
*/
- unsigned short GetKind_Data_Riemann(string val_marker);
+ unsigned short GetKind_Data_Riemann(string val_marker) const;
/*!
* \brief Get the var 1 for the Giels BC.
* \param[in] val_marker - Index corresponding to the Giles BC.
* \return The var1
*/
- su2double GetGiles_Var1(string val_marker);
+ su2double GetGiles_Var1(string val_marker) const;
/*!
* \brief Get the var 2 for the Giles boundary.
* \param[in] val_marker - Index corresponding to the Giles BC.
* \return The var2
*/
- su2double GetGiles_Var2(string val_marker);
+ su2double GetGiles_Var2(string val_marker) const;
/*!
* \brief Get the Flowdir for the Giles BC.
@@ -6583,7 +6612,7 @@ class CConfig {
* \param[in] val_marker - Index corresponding to the Giles BC.
* \return Kind data
*/
- unsigned short GetKind_Data_Giles(string val_marker);
+ unsigned short GetKind_Data_Giles(string val_marker) const;
/*!
* \brief Set the var 1 for Giles BC.
@@ -6596,20 +6625,20 @@ class CConfig {
* \param[in] val_marker - Index corresponding to the Giles BC.
* \return The relax factor for the average component
*/
- su2double GetGiles_RelaxFactorAverage(string val_marker);
+ su2double GetGiles_RelaxFactorAverage(string val_marker) const;
/*!
* \brief Get the relax factor for the fourier component for the Giles BC.
* \param[in] val_marker - Index corresponding to the Giles BC.
* \return The relax factor for the fourier component
*/
- su2double GetGiles_RelaxFactorFourier(string val_marker);
+ su2double GetGiles_RelaxFactorFourier(string val_marker) const;
/*!
* \brief Get the outlet pressure imposed as BC for internal flow.
* \return outlet pressure
*/
- su2double GetPressureOut_BC();
+ su2double GetPressureOut_BC() const;
/*!
* \brief Set the outlet pressure imposed as BC for internal flow.
@@ -6621,7 +6650,7 @@ class CConfig {
* \brief Get the inlet velocity or pressure imposed for incompressible flow.
* \return inlet velocity or pressure
*/
- su2double GetIncInlet_BC();
+ su2double GetIncInlet_BC() const;
/*!
* \brief Set the inlet velocity or pressure imposed as BC for incompressible flow.
@@ -6633,7 +6662,7 @@ class CConfig {
* \brief Get the inlet temperature imposed as BC for incompressible flow.
* \return inlet temperature
*/
- su2double GetIncTemperature_BC();
+ su2double GetIncTemperature_BC() const;
/*!
* \brief Set the inlet temperature imposed as BC for incompressible flow.
@@ -6645,7 +6674,7 @@ class CConfig {
* \brief Get the outlet pressure imposed as BC for incompressible flow.
* \return outlet pressure
*/
- su2double GetIncPressureOut_BC();
+ su2double GetIncPressureOut_BC() const;
/*!
* \brief Set the outlet pressure imposed as BC for incompressible flow.
@@ -6657,13 +6686,13 @@ class CConfig {
* \brief Get the inlet total pressure imposed as BC for internal flow.
* \return inlet total pressure
*/
- su2double GetTotalPressureIn_BC();
+ su2double GetTotalPressureIn_BC() const;
/*!
* \brief Get the inlet total temperature imposed as BC for internal flow.
* \return inlet total temperature
*/
- su2double GetTotalTemperatureIn_BC();
+ su2double GetTotalTemperatureIn_BC() const;
/*!
* \brief Set the inlet total temperature imposed as BC for internal flow.
@@ -6675,28 +6704,28 @@ class CConfig {
* \brief Get the inlet flow angle imposed as BC for internal flow.
* \return inlet flow angle
*/
- su2double GetFlowAngleIn_BC();
+ su2double GetFlowAngleIn_BC() const;
/*!
* \brief Get the wall temperature (static) at an isothermal boundary.
* \param[in] val_index - Index corresponding to the isothermal boundary.
* \return The wall temperature.
*/
- su2double GetIsothermal_Temperature(string val_index);
+ su2double GetIsothermal_Temperature(string val_index) const;
/*!
* \brief Get the wall heat flux on a constant heat flux boundary.
* \param[in] val_index - Index corresponding to the constant heat flux boundary.
* \return The heat flux.
*/
- su2double GetWall_HeatFlux(string val_index);
+ su2double GetWall_HeatFlux(string val_index) const;
/*!
* \brief Get the wall function treatment for the given boundary marker.
* \param[in] val_marker - String of the viscous wall marker.
* \return The type of wall function treatment.
*/
- unsigned short GetWallFunction_Treatment(string val_marker);
+ unsigned short GetWallFunction_Treatment(string val_marker) const;
/*!
* \brief Get the additional integer info for the wall function treatment
@@ -6719,35 +6748,35 @@ class CConfig {
* \param[in] val_index - Index corresponding to the engine inflow boundary.
* \return Target (pressure, massflow, etc) .
*/
- su2double GetEngineInflow_Target(string val_marker);
+ su2double GetEngineInflow_Target(string val_marker) const;
/*!
* \brief Get the fan face Mach number at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The fan face Mach number.
*/
- su2double GetInflow_Mach(string val_marker);
+ su2double GetInflow_Mach(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow pressure.
*/
- su2double GetInflow_Pressure(string val_marker);
+ su2double GetInflow_Pressure(string val_marker) const;
/*!
* \brief Get the mass flow rate at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine mass flow rate.
*/
- su2double GetInflow_MassFlow(string val_marker);
+ su2double GetInflow_MassFlow(string val_marker) const;
/*!
* \brief Get the percentage of reverse flow at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The percentage of reverse flow.
*/
- su2double GetInflow_ReverseMassFlow(string val_marker);
+ su2double GetInflow_ReverseMassFlow(string val_marker) const;
/*!
* \brief Get the percentage of reverse flow at an engine inflow boundary.
@@ -6761,98 +6790,98 @@ class CConfig {
* \param[in] val_marker - Name of the boundary.
* \return The total pressure.
*/
- su2double GetInflow_TotalPressure(string val_marker);
+ su2double GetInflow_TotalPressure(string val_marker) const;
/*!
* \brief Get the temperature (static) at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow temperature.
*/
- su2double GetInflow_Temperature(string val_marker);
+ su2double GetInflow_Temperature(string val_marker) const;
/*!
* \brief Get the total temperature at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow total temperature.
*/
- su2double GetInflow_TotalTemperature(string val_marker);
+ su2double GetInflow_TotalTemperature(string val_marker) const;
/*!
* \brief Get the ram drag at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow ram drag.
*/
- su2double GetInflow_RamDrag(string val_marker);
+ su2double GetInflow_RamDrag(string val_marker) const;
/*!
* \brief Get the force balance at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow force balance.
*/
- su2double GetInflow_Force(string val_marker);
+ su2double GetInflow_Force(string val_marker) const;
/*!
* \brief Get the power at an engine inflow boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine inflow power.
*/
- su2double GetInflow_Power(string val_marker);
+ su2double GetInflow_Power(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine exhaust pressure.
*/
- su2double GetExhaust_Pressure(string val_marker);
+ su2double GetExhaust_Pressure(string val_marker) const;
/*!
* \brief Get the temperature (static) at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine exhaust temperature.
*/
- su2double GetExhaust_Temperature(string val_marker);
+ su2double GetExhaust_Temperature(string val_marker) const;
/*!
* \brief Get the massflow at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine exhaust massflow.
*/
- su2double GetExhaust_MassFlow(string val_marker);
+ su2double GetExhaust_MassFlow(string val_marker) const;
/*!
* \brief Get the total pressure at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return The engine exhaust total pressure.
*/
- su2double GetExhaust_TotalPressure(string val_marker);
+ su2double GetExhaust_TotalPressure(string val_marker) const;
/*!
* \brief Get the total temperature at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return The total temperature.
*/
- su2double GetExhaust_TotalTemperature(string val_marker);
+ su2double GetExhaust_TotalTemperature(string val_marker) const;
/*!
* \brief Get the gross thrust at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return Gross thrust.
*/
- su2double GetExhaust_GrossThrust(string val_marker);
+ su2double GetExhaust_GrossThrust(string val_marker) const;
/*!
* \brief Get the force balance at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return Force balance.
*/
- su2double GetExhaust_Force(string val_marker);
+ su2double GetExhaust_Force(string val_marker) const;
/*!
* \brief Get the power at an engine exhaust boundary.
* \param[in] val_marker - Name of the boundary.
* \return Power.
*/
- su2double GetExhaust_Power(string val_marker);
+ su2double GetExhaust_Power(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7084,14 +7113,14 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_Temperature(string val_marker);
+ su2double GetActDiskInlet_Temperature(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_TotalTemperature(string val_marker);
+ su2double GetActDiskInlet_TotalTemperature(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7112,21 +7141,21 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_Temperature(string val_marker);
+ su2double GetActDiskOutlet_Temperature(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_TotalTemperature(string val_marker);
+ su2double GetActDiskOutlet_TotalTemperature(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_MassFlow(string val_marker);
+ su2double GetActDiskInlet_MassFlow(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7140,7 +7169,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_MassFlow(string val_marker);
+ su2double GetActDiskOutlet_MassFlow(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7154,14 +7183,14 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_Pressure(string val_marker);
+ su2double GetActDiskInlet_Pressure(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_TotalPressure(string val_marker);
+ su2double GetActDiskInlet_TotalPressure(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7252,21 +7281,21 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_RamDrag(string val_marker);
+ su2double GetActDiskInlet_RamDrag(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_Force(string val_marker);
+ su2double GetActDiskInlet_Force(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskInlet_Power(string val_marker);
+ su2double GetActDiskInlet_Power(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7322,7 +7351,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetOutlet_MassFlow(string val_marker);
+ su2double GetOutlet_MassFlow(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7336,7 +7365,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetOutlet_Density(string val_marker);
+ su2double GetOutlet_Density(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7350,7 +7379,7 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetOutlet_Area(string val_marker);
+ su2double GetOutlet_Area(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7756,35 +7785,35 @@ class CConfig {
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_Pressure(string val_marker);
+ su2double GetActDiskOutlet_Pressure(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_TotalPressure(string val_marker);
+ su2double GetActDiskOutlet_TotalPressure(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_GrossThrust(string val_marker);
+ su2double GetActDiskOutlet_GrossThrust(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_Force(string val_marker);
+ su2double GetActDiskOutlet_Force(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
* \param[in] val_index - Index corresponding to the outlet boundary.
* \return The outlet pressure.
*/
- su2double GetActDiskOutlet_Power(string val_marker);
+ su2double GetActDiskOutlet_Power(string val_marker) const;
/*!
* \brief Get the back pressure (static) at an outlet boundary.
@@ -7826,91 +7855,91 @@ class CConfig {
* \param[in] val_index - Index corresponding to the displacement boundary.
* \return The displacement value.
*/
- su2double GetDispl_Value(string val_index);
+ su2double GetDispl_Value(string val_index) const;
/*!
* \brief Get the force value at an load boundary.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load value.
*/
- su2double GetLoad_Value(string val_index);
+ su2double GetLoad_Value(string val_index) const;
/*!
* \brief Get the constant value at a damper boundary.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The damper constant.
*/
- su2double GetDamper_Constant(string val_index);
+ su2double GetDamper_Constant(string val_index) const;
/*!
* \brief Get the force value at a load boundary defined in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load value.
*/
- su2double GetLoad_Dir_Value(string val_index);
+ su2double GetLoad_Dir_Value(string val_index) const;
/*!
* \brief Get the force multiplier at a load boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load multiplier.
*/
- su2double GetLoad_Dir_Multiplier(string val_index);
+ su2double GetLoad_Dir_Multiplier(string val_index) const;
/*!
* \brief Get the force value at a load boundary defined in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load value.
*/
- su2double GetDisp_Dir_Value(string val_index);
+ su2double GetDisp_Dir_Value(string val_index) const;
/*!
* \brief Get the force multiplier at a load boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load multiplier.
*/
- su2double GetDisp_Dir_Multiplier(string val_index);
+ su2double GetDisp_Dir_Multiplier(string val_index) const;
/*!
* \brief Get the force direction at a loaded boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load direction.
*/
- su2double* GetLoad_Dir(string val_index);
+ const su2double* GetLoad_Dir(string val_index) const;
/*!
* \brief Get the force direction at a loaded boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load direction.
*/
- su2double* GetDisp_Dir(string val_index);
+ const su2double* GetDisp_Dir(string val_index) const;
/*!
* \brief Get the amplitude of the sine-wave at a load boundary defined in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load value.
*/
- su2double GetLoad_Sine_Amplitude(string val_index);
+ su2double GetLoad_Sine_Amplitude(string val_index) const;
/*!
* \brief Get the frequency of the sine-wave at a load boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load frequency.
*/
- su2double GetLoad_Sine_Frequency(string val_index);
+ su2double GetLoad_Sine_Frequency(string val_index) const;
/*!
* \brief Get the force direction at a sine-wave loaded boundary in cartesian coordinates.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load direction.
*/
- su2double* GetLoad_Sine_Dir(string val_index);
+ const su2double* GetLoad_Sine_Dir(string val_index) const;
/*!
* \brief Get the force value at an load boundary.
* \param[in] val_index - Index corresponding to the load boundary.
* \return The load value.
*/
- su2double GetFlowLoad_Value(string val_index);
+ su2double GetFlowLoad_Value(string val_index) const;
/*!
* \brief Cyclic pitch amplitude for rotor blades.
@@ -8392,18 +8421,6 @@ class CConfig {
*/
bool GetFull_Tape(void) const { return FullTape; }
- /*!
- * \brief Get the indicator whether we want to benchmark the MPI performance of FSI problems
- * \return The value for checking
- */
- bool CheckFSI_MPI(void);
-
- /*!
- * \brief Get the number of fluid subiterations roblems.
- * \return Number of FSI subiters.
- */
- unsigned short GetnIterFSI(void) const { return nIterFSI; }
-
/*!
* \brief Get the number of subiterations while a ramp is applied.
* \return Number of FSI subiters.
@@ -8655,12 +8672,6 @@ class CConfig {
*/
bool GetFSI_Simulation(void) const { return FSI_Problem || (nMarker_Fluid_Load > 0); }
- /*!
- * \brief Set that the simulation we are running is a FSI simulation
- * \param[in] FSI_sim - boolean that determines is FSI_Problem is true/false.
- */
- void SetFSI_Simulation(bool FSI_sim) { FSI_Problem = FSI_sim; }
-
/*!
* \brief Set that the simulation we are running is a multizone simulation
* \param[in] MZ_problem - boolean that determines is Multizone_Problem is true/false.
@@ -8673,10 +8684,10 @@ class CConfig {
*/
bool GetMultizone_Problem(void) const { return Multizone_Problem; }
- /*!
- * \brief Get the ID for the FEA region that we want to compute the gradient for using direct differentiation
- * \return ID
- */
+ /*!
+ * \brief Get the ID for the FEA region that we want to compute the gradient for using direct differentiation
+ * \return ID
+ */
unsigned short GetnID_DV(void) const { return nID_DV; }
/*!
@@ -8730,7 +8741,7 @@ class CConfig {
/*!
* \brief Function to make available the multiplication factor theta of the
- symmetrizing terms in the DG discretization of the viscous terms.
+ * symmetrizing terms in the DG discretization of the viscous terms.
* \return The specified factor for the DG discretization.
*/
su2double GetTheta_Interior_Penalty_DGFEM(void) const { return Theta_Interior_Penalty_DGFEM; }
@@ -8757,7 +8768,7 @@ class CConfig {
/*!
* \brief Function to make available whether or not only the exact Jacobian
- of the spatial discretization must be computed.
+ * of the spatial discretization must be computed.
* \return The boolean whether or not the Jacobian must be computed.
*/
bool GetJacobian_Spatial_Discretization_Only(void) const { return Jacobian_Spatial_Discretization_Only; }
@@ -8770,7 +8781,7 @@ class CConfig {
/*!
* \brief Get option of whether to use conservative interpolation between zones.
*/
- bool GetConservativeInterpolation(void) const { return ConservativeInterpolation; }
+ bool GetConservativeInterpolation(void) const { return ConservativeInterpolation && GetStructuralProblem(); }
/*!
* \brief Get the basis function to use for radial basis function interpolation for FSI.
@@ -8787,20 +8798,30 @@ class CConfig {
*/
su2double GetRadialBasisFunctionParameter(void) const { return RadialBasisFunction_Parameter; }
+ /*!
+ * \brief Get the tolerance used to prune the interpolation matrix (making it sparser).
+ */
+ su2double GetRadialBasisFunctionPruneTol(void) const { return RadialBasisFunction_PruneTol; }
+
+ /*!
+ * \brief Get the number of donor points to use in Nearest Neighbor interpolation.
+ */
+ unsigned short GetNumNearestNeighbors(void) const { return NumNearestNeighbors; }
+
/*!
* \brief Get the kind of inlet face interpolation function to use.
*/
- inline unsigned short GetKindInletInterpolationFunction(void) const {return Kind_InletInterpolationFunction;}
+ inline unsigned short GetKindInletInterpolationFunction(void) const { return Kind_InletInterpolationFunction; }
/*!
* \brief Get the kind of inlet face interpolation data type.
*/
- inline unsigned short GetKindInletInterpolationType (void) const {return Kind_Inlet_InterpolationType;}
+ inline unsigned short GetKindInletInterpolationType (void) const { return Kind_Inlet_InterpolationType; }
/*!
* \brief Get whether to print inlet interpolated data or not.
*/
- bool GetPrintInlet_InterpolatedData(void) const { return PrintInlet_InterpolatedData;}
+ bool GetPrintInlet_InterpolatedData(void) const { return PrintInlet_InterpolatedData; }
/*!
* \brief Get information about using UQ methodology
diff --git a/Common/include/geometry/dual_grid/CVertex.hpp b/Common/include/geometry/dual_grid/CVertex.hpp
index 858a04b9cca4..a63f5a51be52 100644
--- a/Common/include/geometry/dual_grid/CVertex.hpp
+++ b/Common/include/geometry/dual_grid/CVertex.hpp
@@ -37,26 +37,23 @@
*/
class CVertex : public CDualGrid {
protected:
- unsigned long *Nodes; /*!< \brief Vector to store the global nodes of an element. */
- su2double *Normal; /*!< \brief Normal coordinates of the element and its center of gravity. */
- su2double Aux_Var; /*!< \brief Auxiliar variable defined only on the surface. */
- su2double CartCoord[3]; /*!< \brief Vertex cartesians coordinates. */
- su2double VarCoord[3]; /*!< \brief Used for storing the coordinate variation due to a surface modification. */
- su2double *VarRot; /*!< \brief Used for storing the rotation variation due to a surface modification. */
- long PeriodicPoint[5]; /*!< \brief Store the periodic point of a boundary (iProcessor, iPoint) */
- bool ActDisk_Perimeter; /*!< \brief Identify nodes at the perimeter of the actuator disk */
- short Rotation_Type; /*!< \brief Type of rotation associated with the vertex (MPI and periodic) */
+ unsigned long Nodes[1]; /*!< \brief Vector to store the global nodes of an element. */
+ su2double Normal[3]; /*!< \brief Normal coordinates of the element and its center of gravity. */
+ su2double Aux_Var; /*!< \brief Auxiliar variable defined only on the surface. */
+ su2double CartCoord[3]; /*!< \brief Vertex cartesians coordinates. */
+ su2double VarCoord[3]; /*!< \brief Used for storing the coordinate variation due to a surface modification. */
+ su2double *VarRot; /*!< \brief Used for storing the rotation variation due to a surface modification. */
+ long PeriodicPoint[5]; /*!< \brief Store the periodic point of a boundary (iProcessor, iPoint) */
+ bool ActDisk_Perimeter; /*!< \brief Identify nodes at the perimeter of the actuator disk */
+ short Rotation_Type; /*!< \brief Type of rotation associated with the vertex (MPI and periodic) */
unsigned long Normal_Neighbor; /*!< \brief Index of the closest neighbor. */
- unsigned long *Donor_Points; /*!< \brief indices of donor points for interpolation across zones */
- unsigned long *Donor_Proc; /*!< \brief indices of donor processor for interpolation across zones in parallel */
- unsigned long Donor_Elem; /*!< \brief Store the donor element for interpolation across zones/ */
- unsigned short Donor_Face; /*!<\brief Store the donor face (w/in donor element) for interpolation across zones */
- su2double Basis_Function[3]; /*!< \brief Basis function values for interpolation across zones. */
- su2double *Donor_Coeff; /*!\brief Store a list of coefficients corresponding to the donor points. */
- unsigned short nDonor_Points; /*!\brief Number of points in Donor_Points; at least there will be one donor point (if the mesh is matching)*/
+ unsigned long *Donor_Points; /*!< \brief indices of donor points for interpolation across zones */
+ unsigned long *Donor_Proc; /*!< \brief indices of donor processor for interpolation across zones in parallel */
+ su2double Basis_Function[3]; /*!< \brief Basis function values for interpolation across zones. */
+ su2double *Donor_Coeff; /*!< \brief Store a list of coefficients corresponding to the donor points. */
+ unsigned short nDonor_Points; /*!< \brief Number of points in Donor_Coeff. */
public:
-
/*!
* \brief Constructor of the class.
* \param[in] val_point - Node of the vertex.
@@ -113,6 +110,11 @@ class CVertex : public CDualGrid {
*/
inline su2double *GetNormal(void) override { return Normal; }
+ /*!
+ * \brief Get the ith component of the normal.
+ */
+ inline su2double GetNormal(unsigned short iDim) const { return Normal[iDim]; }
+
/*!
* \brief Initialize normal vector.
*/
@@ -308,30 +310,6 @@ class CVertex : public CDualGrid {
*/
inline bool GetActDisk_Perimeter(void) const { return ActDisk_Perimeter; }
- /*!
- * \brief Set the donor element of a vertex for interpolation across zones.
- * \param[in] val_donorelem - donor element index.
- */
- inline void SetDonorElem(long val_donorelem) { Donor_Elem = val_donorelem; }
-
- /*!
- * \brief Get the donor element of a vertex for interpolation across zones.
- * \return Value of the donor element of a vertex.
- */
- inline long GetDonorElem(void) const { return Donor_Elem; }
-
- /*!
- * \brief Set the donor face of a vertex for interpolation across zones.
- * \param[in] val_donorface- donor face index (w/in donor elem).
- */
- inline void SetDonorFace(unsigned short val_donorface) { Donor_Face = val_donorface; }
-
- /*!
- * \brief Get the donor face of a vertex for interpolation across zones.
- * \return Value of the donor face index (w/in donor elem).
- */
- inline unsigned short GetDonorFace(void) const { return Donor_Face; }
-
/*!
* \brief Set the finite element basis functions needed for interpolation.
* \param[in] val_node - a node index of the owner element.
@@ -358,17 +336,6 @@ class CVertex : public CDualGrid {
*/
inline unsigned long GetNormal_Neighbor(void) const { return Normal_Neighbor; }
- /*!
- * \brief Increment the number of donor points by 1.
- */
- inline void IncrementnDonor(void) {nDonor_Points++;}
-
- /*!
- * \brief Set the value of nDonor_Points
- * \param[in] nDonor - the number of donor points
- */
- inline void SetnDonorPoints(unsigned short nDonor) {nDonor_Points = nDonor;}
-
/*!
* \brief Return the value of nDonor_Points
* \return nDonor - the number of donor points
@@ -419,9 +386,9 @@ class CVertex : public CDualGrid {
/*!
* \brief Allocate memory based on how many donor points need to be stored.
- * Uses nDonor_Points
+ * \param[in] nDonor - the number of donor points
*/
- void Allocate_DonorInfo(void);
+ void Allocate_DonorInfo(unsigned short nDonor);
/*!
* \brief Get the rotation variation
diff --git a/Common/include/geometry/elements/CElement.hpp b/Common/include/geometry/elements/CElement.hpp
index 20975dd2b9fc..c3aae53ef255 100644
--- a/Common/include/geometry/elements/CElement.hpp
+++ b/Common/include/geometry/elements/CElement.hpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -627,6 +627,26 @@ class CQUAD4 final : public CElementWithKnownSizes<4,4,2> {
*/
CQUAD4();
+ /*!
+ * \brief Shape functions (Ni) evaluated at point Xi,Eta.
+ */
+ inline static void ShapeFunctions(su2double Xi, su2double Eta, su2double* Ni) {
+ Ni[0] = 0.25*(1.0-Xi)*(1.0-Eta);
+ Ni[1] = 0.25*(1.0+Xi)*(1.0-Eta);
+ Ni[2] = 0.25*(1.0+Xi)*(1.0+Eta);
+ Ni[3] = 0.25*(1.0-Xi)*(1.0+Eta);
+ }
+
+ /*!
+ * \brief Shape function Jacobian (dNi) evaluated at point Xi,Eta.
+ */
+ inline static void ShapeFunctionJacobian(su2double Xi, su2double Eta, su2double dNi[][2]) {
+ dNi[0][0] = -0.25*(1.0-Eta); dNi[0][1] = -0.25*(1.0-Xi);
+ dNi[1][0] = 0.25*(1.0-Eta); dNi[1][1] = -0.25*(1.0+Xi);
+ dNi[2][0] = 0.25*(1.0+Eta); dNi[2][1] = 0.25*(1.0+Xi);
+ dNi[3][0] = -0.25*(1.0+Eta); dNi[3][1] = 0.25*(1.0-Xi);
+ }
+
/*!
* \brief Compute the value of the area of the element.
* \param[in] mode - Type of coordinates to consider in the computation.
diff --git a/Common/include/grid_movement_structure.hpp b/Common/include/grid_movement_structure.hpp
index d8dc1e19a241..29574e9068ce 100644
--- a/Common/include/grid_movement_structure.hpp
+++ b/Common/include/grid_movement_structure.hpp
@@ -1290,183 +1290,6 @@ class CVolumetricMovement : public CGridMovement {
virtual void Boundary_Dependencies(CGeometry **geometry, CConfig *config);
};
-/*!
- * \class CElasticityMovement
- * \brief Class for moving the volumetric numerical grid using the new linear elasticity solver.
- * \author R.Sanchez, based on CVolumetricMovement developments of F. Palacios, A. Bueno, T. Economon, S. Padron
- * \version 7.0.3 "Blackbird"
- */
-class CElasticityMovement : public CVolumetricMovement {
-protected:
-
- unsigned short nDim; /*!< \brief Number of dimensions. */
- unsigned short nVar; /*!< \brief Number of variables. */
-
- unsigned long nPoint; /*!< \brief Number of points. */
- unsigned long nPointDomain; /*!< \brief Number of points in the domain. */
-
- unsigned long nIterMesh; /*!< \brief Number of iterations in the mesh update. +*/
- su2double valResidual;
-
- su2double *Residual, /*!< \brief Auxiliary nDim vector. */
- *Solution; /*!< \brief Auxiliary nDim vector. */
-
- su2double **matrixZeros; /*!< \brief Submatrix to make zeros and impose boundary conditions. */
- su2double **matrixId; /*!< \brief Diagonal submatrix to impose boundary conditions. */
-
- su2double MinVolume;
- su2double MaxVolume;
-
-#ifndef CODI_FORWARD_TYPE
- CSysSolve System;
- CSysMatrix StiffMatrix; /*!< \brief Matrix to store the point-to-point stiffness. */
-#else
- CSysSolve System;
- CSysMatrix StiffMatrix;
-#endif
- CSysVector LinSysSol;
- CSysVector LinSysRes;
-
- su2double E; /*!< \brief Young's modulus of elasticity. */
- su2double Nu; /*!< \brief Poisson's ratio. */
-
- su2double Mu; /*!< \brief Lame's coeficient. */
- su2double Lambda; /*!< \brief Lame's coeficient. */
-
- su2double **Jacobian_ij; /*!< \brief Submatrix to store the constitutive term for node ij. */
-
- su2double **Ba_Mat, /*!< \brief Matrix B for node a - Auxiliary. */
- **Bb_Mat; /*!< \brief Matrix B for node b - Auxiliary. */
- su2double **KAux_ab; /*!< \brief Stiffness sub-term - Auxiliary. */
- su2double **D_Mat; /*!< \brief Constitutive matrix - Auxiliary. */
- su2double **GradNi_Ref_Mat; /*!< \brief Gradients of Ni - Auxiliary. */
-
-public:
-
- CElement** element_container; /*!< \brief Container which stores the element information. */
-
- /*!
- * \brief Constructor of the class.
- */
- CElasticityMovement(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CElasticityMovement(void);
-
- /*!
- * \brief Grid deformation using the linear elasticity equations.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] UpdateGeo - Update geometry.
- * \param[in] Derivative - Compute the derivative (disabled by default). Does not actually deform the grid if enabled.
- */
- void SetVolume_Deformation_Elas(CGeometry *geometry, CConfig *config, bool UpdateGeo, bool screen_output, bool Derivative = false);
-
- /*!
- * \brief Update the value of the coordinates after the grid movement.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void UpdateGridCoord(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Update the dual grid after the grid movement (edges and control volumes).
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void UpdateDualGrid(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Update the coarse multigrid levels after the grid movement.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void UpdateMultiGrid(CGeometry **geometry, CConfig *config);
-
- /*!
- * \brief Check the boundary vertex that are going to be moved.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void SetBoundaryDisplacements(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Set the boundary displacements to 0.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] val_marker -
- */
- void SetClamped_Boundary(CGeometry *geometry, CConfig *config, unsigned short val_marker);
-
- /*!
- * \brief Set the boundary displacements to the imposed external value.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void SetMoving_Boundary(CGeometry *geometry, CConfig *config, unsigned short val_marker);
-
- /*!
- * \brief Compute the min and max volume for the stiffness matrix for grid deformation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \return Value of the length of the smallest edge of the grid.
- */
- void SetMinMaxVolume(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Compute the min and max volume for the stiffness matrix for grid deformation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \return Value of the length of the smallest edge of the grid.
- */
- void SetStiffnessMatrix(CGeometry *geometry, CConfig *config);
-
- /*!
- * \brief Store the number of iterations when moving the mesh.
- * \param[in] val_nIterMesh - Number of iterations.
- */
- void Set_nIterMesh(unsigned long val_nIterMesh);
-
- /*!
- * \brief Retrieve the number of iterations when moving the mesh.
- * \param[out] Number of iterations.
- */
- unsigned long Get_nIterMesh(void);
-
- /*!
- * \brief Compute the stiffness of the element and the parameters Lambda and Mu
- */
- void Set_Element_Stiffness(su2double ElemVolume, CConfig *config);
-
- /*!
- * \brief Compute the stiffness of the element and the parameters Lambda and Mu
- */
- void Compute_Element_Contribution(CElement *element, CConfig *config);
-
- /*!
- * \brief Compute the constitutive matrix in an element for mesh deformation problems
- * \param[in] element_container - Element structure for the particular element integrated.
- */
- void Compute_Constitutive_Matrix(void);
-
- /*!
- * \brief Set the boundary displacements in the mesh side of the problem
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void Transfer_Boundary_Displacements(CGeometry *geometry, CConfig *config, unsigned short val_marker);
-
- /*!
- * \brief Set the boundary displacements in the mesh side of the problem
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void Boundary_Dependencies(CGeometry **geometry, CConfig *config);
-
-};
-
/*!
* \class CSurfaceMovement
* \brief Class for moving the surface numerical grid.
@@ -1571,46 +1394,6 @@ class CSurfaceMovement : public CGridMovement {
*/
void Moving_Walls(CGeometry *geometry, CConfig *config, unsigned short iZone, unsigned long iter);
- /*!
- * \brief Computes the displacement of a translating surface for a dynamic mesh simulation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current physical time iteration.
- * \param[in] iZone - Zone number in the mesh.
- */
- void Surface_Translating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
-
- /*!
- * \brief Computes the displacement of a plunging surface for a dynamic mesh simulation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current physical time iteration.
- * \param[in] iZone - Zone number in the mesh.
- */
- void Surface_Plunging(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
-
- /*!
- * \brief Computes the displacement of a pitching surface for a dynamic mesh simulation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current physical time iteration.
- * \param[in] iZone - Zone number in the mesh.
- */
- void Surface_Pitching(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
-
- /*!
- * \brief Computes the displacement of a rotating surface for a dynamic mesh simulation.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current physical time iteration.
- * \param[in] iZone - Zone number in the mesh.
- */
- void Surface_Rotating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
-
/*!
* \brief Computes the displacement of a rotating surface for a dynamic mesh simulation.
* \param[in] geometry - Geometrical definition of the problem.
diff --git a/Common/include/grid_movement_structure.inl b/Common/include/grid_movement_structure.inl
index 7fab42893a88..3d830bdf93df 100644
--- a/Common/include/grid_movement_structure.inl
+++ b/Common/include/grid_movement_structure.inl
@@ -216,10 +216,6 @@ inline void CVolumetricMovement::SetVolume_Deformation_Elas(CGeometry *geometry,
inline void CVolumetricMovement::Boundary_Dependencies(CGeometry **geometry, CConfig *config) { }
-inline void CElasticityMovement::Set_nIterMesh(unsigned long val_nIterMesh) { nIterMesh = val_nIterMesh; }
-
-inline unsigned long CElasticityMovement::Get_nIterMesh() { return nIterMesh; }
-
inline bool CSurfaceMovement::CheckFFDBoxDefinition(CConfig *config, unsigned short iDV) {
for (unsigned short iFFDBox = 0; iFFDBox < GetnFFDBox(); iFFDBox++) {
if (FFDBox[iFFDBox]->GetTag() == config->GetFFDTag(iDV)) { return true;}
diff --git a/Common/include/interface_interpolation/CInterpolator.hpp b/Common/include/interface_interpolation/CInterpolator.hpp
new file mode 100644
index 000000000000..32ffae355dba
--- /dev/null
+++ b/Common/include/interface_interpolation/CInterpolator.hpp
@@ -0,0 +1,190 @@
+/*!
+ * \file CInterpolator.hpp
+ * \brief Base class for multiphysics interpolation.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "../../include/datatype_structure.hpp"
+#include "../../include/toolboxes/C2DContainer.hpp"
+#include
+
+class CConfig;
+class CGeometry;
+
+using namespace std;
+
+/*!
+ * \class CInterpolator
+ * \brief Main class for defining the interpolator, it requires
+ * a child class for each particular interpolation method.
+ * \author H. Kline
+ */
+class CInterpolator {
+protected:
+ const int rank; /*!< \brief MPI Rank. */
+ const int size; /*!< \brief MPI Size. */
+ const unsigned donorZone; /*!< \brief Index of donor zone. */
+ const unsigned targetZone; /*!< \brief Index of target zone. */
+
+ unsigned long
+ MaxLocalVertex_Donor, /*!< \brief Maximum vertices per processor*/
+ nGlobalFace_Donor, /*!< \brief Number of global donor faces*/
+ nGlobalFaceNodes_Donor, /*!< \brief Number of global donor face nodes*/
+ MaxFace_Donor, /*!< \brief Maximum faces per processor*/
+ MaxFaceNodes_Donor; /*!< \brief Maximum nodes associated with faces per processor*/
+
+ unsigned long
+ *Buffer_Receive_nVertex_Donor, /*!< \brief Buffer to store the number of vertices per processor on the Donor domain */
+ *Buffer_Receive_nFace_Donor, /*!< \brief Buffer to store the number of faces per processor*/
+ *Buffer_Receive_nFaceNodes_Donor, /*!< \brief Buffer to store the number of nodes associated with faces per processor*/
+ Buffer_Send_nVertex_Donor[1], /*!< \brief Buffer to send number of vertices on the local processor*/
+ Buffer_Send_nFace_Donor[1], /*!< \brief Buffer to send number of faces on the local processor*/
+ Buffer_Send_nFaceNodes_Donor[1], /*!< \brief Buffer to send the number of nodes assocated with faces per processor*/
+ *Buffer_Send_FaceIndex, /*!< \brief Buffer to send indices pointing to the node indices that define the faces*/
+ *Buffer_Receive_FaceIndex, /*!< \brief Buffer to receive indices pointing to the node indices that define the faces*/
+ *Buffer_Send_FaceNodes, /*!< \brief Buffer to send indices pointing to the location of node information in other buffers, defining faces*/
+ *Buffer_Receive_FaceNodes; /*!< \brief Buffer to receive indices pointing to the location of node information in other buffers, defining faces*/
+
+ long *Buffer_Send_GlobalPoint, /*!< \brief Buffer to send global point indices*/
+ *Buffer_Receive_GlobalPoint; /*!< \brief Buffer to receive global point indices*/
+
+ su2double *Buffer_Send_Coord, /*!< \brief Buffer to send coordinate values*/
+ *Buffer_Send_Normal, /*!< \brief Buffer to send normal vector values */
+ *Buffer_Receive_Coord, /*!< \brief Buffer to receive coordinate values*/
+ *Buffer_Receive_Normal; /*!< \brief Buffer to receive normal vector values*/
+
+ unsigned long
+ *Receive_GlobalPoint, /*!< \brief Buffer to receive Global point indexes*/
+ *Buffer_Receive_nLinkedNodes, /*!< \brief Buffer to receive the number of edges connected to each node*/
+ *Buffer_Receive_LinkedNodes, /*!< \brief Buffer to receive the list of notes connected to the nodes through an edge*/
+ *Buffer_Receive_StartLinkedNodes, /*!< \brief Buffer to receive the index of the Receive_LinkedNodes buffer where corresponding list of linked nodes begins */
+ *Buffer_Receive_Proc; /*!< \brief Buffer to receive the thread that owns the node*/
+
+ unsigned long
+ nGlobalVertex_Target, /*!< \brief Global number of vertex of the target boundary*/
+ nLocalVertex_Target, /*!< \brief Number of vertex of the target boundary owned by the thread*/
+ nGlobalVertex_Donor, /*!< \brief Global number of vertex of the donor boundary*/
+ nLocalVertex_Donor, /*!< \brief Number of vertex of the donor boundary owned by the thread*/
+ nGlobalVertex, /*!< \brief Dummy variable to temporarily store the global number of vertex of a boundary*/
+ nLocalLinkedNodes; /*!< \brief Dummy variable to temporarily store the number of vertex of a boundary*/
+
+ CGeometry**** const Geometry; /*! \brief Vector which stores n zones of geometry. */
+ CGeometry* const donor_geometry; /*! \brief Donor geometry. */
+ CGeometry* const target_geometry; /*! \brief Target geometry. */
+
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - index of the donor zone
+ * \param[in] jZone - index of the target zone
+ */
+ CInterpolator(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief No default construction allowed to force zones and geometry to always be set.
+ */
+ CInterpolator(void) = delete;
+
+ /*!
+ * \brief Destructor of the class, nothing is deleted, derived classes need to manage the MPI buffers.
+ */
+ virtual ~CInterpolator(void) = default;
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes
+ * \note Main method that derived classes must implement.
+ * \param[in] config - Definition of the particular problem.
+ */
+ virtual void SetTransferCoeff(const CConfig* const* config) = 0;
+
+ /*!
+ * \brief Print information about the interpolation.
+ */
+ virtual void PrintStatistics(void) const { }
+
+ /*!
+ * \brief Find the index of the interface marker shared by that zone
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] val_marker_interface - Interface tag.
+ */
+ static int FindInterfaceMarker(const CConfig *config, unsigned short val_marker_interface);
+
+ /*!
+ * \brief Check whether an interface should be processed or not, i.e. if it is part of the zones.
+ * \param[in] val_markDonor - Marker tag from donor zone.
+ * \param[in] val_markTarget - Marker tag from target zone.
+ */
+ static bool CheckInterfaceBoundary(int val_markDonor, int val_markTarget);
+
+ /*!
+ * \brief Check whether two zones have a common interface.
+ * \param[in] donor - Configuration of the donor zone.
+ * \param[in] target - Configuration of the target zone.
+ */
+ static bool CheckZonesInterface(const CConfig* donor, const CConfig* target);
+
+protected:
+ /*!
+ * \brief Recontstruct the boundary connectivity from parallel partitioning and broadcasts it to all threads
+ * \param[in] val_zone - index of the zone
+ * \param[in] val_marker - index of the marker
+ */
+ void ReconstructBoundary(unsigned long val_zone, int val_marker);
+
+ /*!
+ * \brief Determine array sizes used to collect and send coordinate and global point information.
+ * \param[in] markDonor - Index of the boundary on the donor domain.
+ * \param[in] markTarget - Index of the boundary on the target domain.
+ * \param[in] nVertexDonor - Number of vertices on the donor boundary.
+ * \param[in] nDim - number of physical dimensions.
+ */
+ void Determine_ArraySize(int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim);
+
+ /*!
+ * \brief Collect and communicate vertex info: coord, global point.
+ * \param[in] markDonor - Index of the boundary on the donor domain.
+ * \param[in] markTarget - Index of the boundary on the target domain.
+ * \param[in] nVertexDonor - Number of vertices on the donor boundary.
+ * \param[in] nDim - number of physical dimensions.
+ */
+ void Collect_VertexInfo(int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim);
+
+ /*!
+ * \brief Collect all donor elements in an interface pair.
+ * \param[in] markDonor - Index of the boundary on the donor domain.
+ * \param[in] nDim - number of physical dimensions.
+ * \param[in] compress - Squeeze the information (Allgatherv instead of Allgather).
+ * \param[out] allNumElem - Number of donor element per rank.
+ * \param[out] numNodes - Number of nodes for each element.
+ * \param[out] idxNodes - Index (global) of those nodes.
+ * \return Number of collected donor elements.
+ * \note The last two outputs are always sized for Allgather.
+ */
+ unsigned long Collect_ElementInfo(int markDonor, unsigned short nDim, bool compress,
+ vector& allNumElem, vector& numNodes,
+ su2matrix& idxNodes) const;
+};
diff --git a/Common/include/interface_interpolation/CInterpolatorFactory.hpp b/Common/include/interface_interpolation/CInterpolatorFactory.hpp
new file mode 100644
index 000000000000..72189e6e7a07
--- /dev/null
+++ b/Common/include/interface_interpolation/CInterpolatorFactory.hpp
@@ -0,0 +1,52 @@
+/*!
+ * \file CInterpolatorFactory.hpp
+ * \brief Factory to generate interpolator objects.
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+class CConfig;
+class CGeometry;
+class CInterpolator;
+
+/*!
+ * \namespace CInterpolatorFactory
+ * \brief Factory methods for CInterpolator objects.
+ */
+namespace CInterpolatorFactory {
+
+/*!
+ * \brief The factory method.
+ * \param[in] geometry_container - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - Index of the donor zone.
+ * \param[in] jZone - Index of the target zone.
+ * \param[in] verbose - If true, print information to screen.
+ * \return Pointer to interpolator on the heap, caller is responsible for deletion.
+ */
+CInterpolator* createInterpolator(CGeometry ****geometry_container,
+ const CConfig* const* config,
+ unsigned iZone, unsigned jZone,
+ bool verbose = true);
+
+}
diff --git a/Common/include/interface_interpolation/CIsoparametric.hpp b/Common/include/interface_interpolation/CIsoparametric.hpp
new file mode 100644
index 000000000000..e4c27c6bb9c8
--- /dev/null
+++ b/Common/include/interface_interpolation/CIsoparametric.hpp
@@ -0,0 +1,91 @@
+/*!
+ * \file CIsoparametric.hpp
+ * \brief Isoparametric interpolation using FE shape functions.
+ * \author P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "CInterpolator.hpp"
+
+/*!
+ * \brief Isoparametric interpolation.
+ */
+class CIsoparametric final : public CInterpolator {
+private:
+ enum: unsigned long { NUM_CANDIDATE_DONORS = 8 }; /*!< \brief Test this many nearby donor elements for "best fit". */
+ /*--- Statistics. ---*/
+ su2double MaxDistance = 0.0, ErrorRate = 0.0;
+ unsigned long ErrorCounter = 0;
+
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - index of the donor zone
+ * \param[in] jZone - index of the target zone
+ */
+ CIsoparametric(CGeometry ****geometry_container, const CConfig* const* config,
+ unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes
+ * \param[in] config - Definition of the particular problem.
+ */
+ void SetTransferCoeff(const CConfig* const* config) override;
+
+ /*!
+ * \brief Print information about the interpolation.
+ */
+ void PrintStatistics(void) const override;
+
+private:
+ /*!
+ * \brief Compute the isoparametric interpolation coefficients for a 2D line element.
+ * \param[in] X - Coordinate matrix defining the line.
+ * \param[in] xj - Coordinates of the target point.
+ * \param[out] isoparams - Isoparametric coefficients.
+ * \return 0 on success, 1 if xj is too far outside element bounds.
+ */
+ static int LineIsoparameters(const su2double X[][3], const su2double *xj, su2double* isoparams);
+
+ /*!
+ * \brief Compute the isoparametric interpolation coefficients for a 3D triangle element.
+ * \param[in] X - Coordinate matrix defining the triangle.
+ * \param[in] xj - Coordinates of the target point.
+ * \param[out] isoparams - Isoparametric coefficients.
+ * \return 0 on success, 1 if xj is too far outside element bounds.
+ */
+ static int TriangleIsoparameters(const su2double X[][3], const su2double *xj, su2double* isoparams);
+
+ /*!
+ * \brief Compute the isoparametric interpolation coefficients for a 3D quadrilateral element.
+ * \param[in] X - Coordinate matrix defining the quadrilateral.
+ * \param[in] xj - Coordinates of the target point.
+ * \param[out] isoparams - Isoparametric coefficients.
+ * \return 0 on success, 1 if xj is too far outside element bounds.
+ */
+ static int QuadrilateralIsoparameters(const su2double X[][3], const su2double *xj, su2double* isoparams);
+
+};
diff --git a/Common/include/interface_interpolation/CMirror.hpp b/Common/include/interface_interpolation/CMirror.hpp
new file mode 100644
index 000000000000..e884b70b40e0
--- /dev/null
+++ b/Common/include/interface_interpolation/CMirror.hpp
@@ -0,0 +1,53 @@
+/*!
+ * \file CMirror.hpp
+ * \brief Mirror interpolation for the conservative (work-wise) approach in FSI problems.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "CInterpolator.hpp"
+
+/*!
+ * \brief Mirror interpolation: copy point linking and coefficient values from the opposing mesh.
+ * \note Assumes that the oppoosing mesh has already run interpolation, otherwise will result in empty/trivial interpolation.
+ */
+class CMirror final : public CInterpolator {
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \note Data is set in geometry[targetZone].
+ * \param[in] geometry_container
+ * \param[in] config - config container
+ * \param[in] iZone - First zone
+ * \param[in] jZone - Second zone
+ */
+ CMirror(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes
+ * \param[in] config - Definition of the particular problem.
+ */
+ void SetTransferCoeff(const CConfig* const* config) override;
+
+};
diff --git a/Common/include/interface_interpolation/CNearestNeighbor.hpp b/Common/include/interface_interpolation/CNearestNeighbor.hpp
new file mode 100644
index 000000000000..53a2f92478ed
--- /dev/null
+++ b/Common/include/interface_interpolation/CNearestNeighbor.hpp
@@ -0,0 +1,62 @@
+/*!
+ * \file CNearestNeighbor.hpp
+ * \brief Nearest Neighbor interpolation class.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "CInterpolator.hpp"
+
+/*!
+ * \brief Nearest Neighbor(s) interpolation.
+ * \note The closest k neighbors are used for IDW interpolation, the computational
+ * cost of setting up the interpolation is O(N^2 log(k)), this can be improved
+ * by using a kd-tree.
+ */
+class CNearestNeighbor final : public CInterpolator {
+private:
+ su2double AvgDistance = 0.0, MaxDistance = 0.0;
+
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - index of the donor zone
+ * \param[in] jZone - index of the target zone
+ */
+ CNearestNeighbor(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void SetTransferCoeff(const CConfig* const* config) override;
+
+ /*!
+ * \brief Print interpolation statistics.
+ */
+ void PrintStatistics(void) const override;
+
+};
diff --git a/Common/include/interface_interpolation/CRadialBasisFunction.hpp b/Common/include/interface_interpolation/CRadialBasisFunction.hpp
new file mode 100644
index 000000000000..61e154b0afcb
--- /dev/null
+++ b/Common/include/interface_interpolation/CRadialBasisFunction.hpp
@@ -0,0 +1,139 @@
+/*!
+ * \file CRadialBasisFunction.hpp
+ * \brief Radial basis function interpolation.
+ * \author Joel Ho, P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "CInterpolator.hpp"
+#include "../option_structure.hpp"
+#include "../toolboxes/C2DContainer.hpp"
+
+/*!
+ * \brief Radial basis function interpolation.
+ */
+class CRadialBasisFunction final : public CInterpolator {
+ static_assert(su2passivematrix::Storage == StorageType::RowMajor,
+ "This class relies on row major storage throughout.");
+private:
+ unsigned long MinDonors = 0, AvgDonors = 0, MaxDonors = 0;
+ passivedouble Density = 0.0, AvgCorrection = 0.0, MaxCorrection = 0.0;
+
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - index of the donor zone
+ * \param[in] jZone - index of the target zone
+ */
+ CRadialBasisFunction(CGeometry ****geometry_container, const CConfig* const* config,
+ unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes
+ * \param[in] config - Definition of the particular problem.
+ */
+ void SetTransferCoeff(const CConfig* const* config) override;
+
+ /*!
+ * \brief Print information about the interpolation.
+ */
+ void PrintStatistics(void) const override;
+
+ /*!
+ * \brief Compute the value of a radial basis function, this is static so it can be re-used.
+ * \param[in] type - of radial basis function
+ * \param[in] radius - the characteristic dimension
+ * \param[in] dist - distance
+ * \return value of the RBF.
+ */
+ static su2double Get_RadialBasisValue(ENUM_RADIALBASIS type, const su2double radius, const su2double dist);
+
+ /*!
+ * \brief Compute the RBF "generator" matrix with or without polynomial terms.
+ * \note Multiplying C_inv_trunc by a column vector gives specific coefficients for given "known values",
+ * conversely, multiplying (on the left) by a row vector of polynomial and RBF values gives generic
+ * interpolation coefficients for a given target evaluation point.
+ * \param[in] type - Type of radial basis function.
+ * \param[in] usePolynomial - Whether to use polynomial terms.
+ * \param[in] radius - Normalizes point-to-point distance when computing RBF values.
+ * \param[in] coords - Coordinates of the donor points.
+ * \param[out] nPolynomial - Num of poly terms, -1 if !usePolynomial, nDim-1 if coords lie on plane, else nDim.
+ * \param[out] keepPolynomialRow - Size nDim, signals which (if any) iDim was removed from polynomial term.
+ * \param[out] C_inv_trunc - The generator matrix as described above.
+ */
+ static void ComputeGeneratorMatrix(ENUM_RADIALBASIS type, bool usePolynomial, su2double radius,
+ const su2activematrix& coords, int& nPolynomial,
+ vector& keepPolynomialRow, su2passivematrix& C_inv_trunc);
+
+ /*!
+ * \brief If the polynomial term is included in the interpolation, and the points lie on a plane, the matrix
+ * becomes rank deficient and cannot be inverted. This method detects that condition and corrects it by
+ * removing a row from P (the polynomial part of the interpolation matrix).
+ * \param[in] max_diff_tol - Tolerance to detect whether points are on a plane.
+ * \param[out] keep_row - Marks the dimensions of P kept.
+ * \param[in,out] P - Polynomial part of the interpolation matrix, one row may be eliminated.
+ * \return n_polynomial - Size of the polynomial part on exit (in practice nDim or nDim-1).
+ */
+ static int CheckPolynomialTerms(su2double max_diff_tol, vector& keep_row, su2passivematrix &P);
+
+private:
+ /*!
+ * \brief Helper function, prunes (by setting to zero) small interpolation coefficients,
+ * i.e. <= tolerance*max(abs(coeffs)). The vector is re-scaled such that sum(coeffs)==1.
+ * \param[in] tolerance - Relative pruning tolerance.
+ * \param[in] size - Size of the coefficient vector.
+ * \param[in,out] coeffs - Iterator to start of vector of interpolation coefficients.
+ * \return Number of non-zero coefficients after pruning and correction factor.
+ */
+ template
+ static pair PruneSmallCoefficients(Float tolerance, Int size, ForwardIt coeffs) {
+
+ /*--- Determine the pruning threshold. ---*/
+ Float thresh = 0.0;
+ auto end = coeffs;
+ for (Int i = 0; i < size; ++i)
+ thresh = max(thresh, fabs(*(end++)));
+ thresh *= tolerance;
+
+ /*--- Prune and count non-zeros. ---*/
+ Int numNonZeros = 0;
+ Float coeffSum = 0.0;
+ for (auto it = coeffs; it != end; ++it) {
+ if (fabs(*it) > thresh) { // keep
+ coeffSum += *it;
+ ++numNonZeros;
+ }
+ else { *it = 0.0; } // prune
+ }
+
+ /*--- Correct remaining coefficients, sum must be 1 for conservation. ---*/
+ Float correction = 1.0 / coeffSum;
+ while (coeffs != end) *(coeffs++) *= correction;
+
+ return make_pair(numNonZeros, correction);
+ }
+
+};
diff --git a/Common/include/interface_interpolation/CSlidingMesh.hpp b/Common/include/interface_interpolation/CSlidingMesh.hpp
new file mode 100644
index 000000000000..25f77886b8a5
--- /dev/null
+++ b/Common/include/interface_interpolation/CSlidingMesh.hpp
@@ -0,0 +1,129 @@
+/*!
+ * \file CSlidingMesh.hpp
+ * \brief Sliding mesh interpolation.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include "CInterpolator.hpp"
+
+/*!
+ * \brief Sliding mesh approach.
+ * \note The algorithm is based on Rinaldi et al. "Flux-conserving treatment of non-conformal interfaces
+ * for finite-volume discritization of conservation laws" 2015, Comp. Fluids, 120, pp 126-139
+ */
+class CSlidingMesh final : public CInterpolator {
+public:
+ /*!
+ * \brief Constructor of the class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] iZone - index of the donor zone
+ * \param[in] jZone - index of the target zone
+ */
+ CSlidingMesh(CGeometry ****geometry_container, const CConfig* const* config,
+ unsigned int iZone, unsigned int jZone);
+
+ /*!
+ * \brief Set up transfer matrix defining relation between two meshes
+ * \param[in] config - Definition of the particular problem.
+ */
+ void SetTransferCoeff(const CConfig* const* config) override;
+
+private:
+ /*!
+ * \brief For 3-Dimensional grids, build the dual surface element
+ * \param[in] map - array containing the index of the boundary points connected to the node
+ * \param[in] startIndex - for each vertex specifies the corresponding index in the global
+ * array containing the indexes of all its neighbouring vertexes
+ * \param[in] nNeighbour - for each vertex specifies the number of its neighbouring vertexes (on the boundary)
+ * \param[in] coord - array containing the coordinates of all the boundary vertexes
+ * \param[in] centralNode - label of the vertex around which the dual surface element is built
+ * \param[out] element - double array where element node coordinates will be stored
+ * \return Number of points included in the element.
+ */
+ static int Build_3D_surface_element(const unsigned long *map, const unsigned long *startIndex,
+ const unsigned long* nNeighbor, const su2double *coord,
+ unsigned long centralNode, su2double** element);
+
+ /*!
+ * \brief For 2-Dimensional grids, compute intersection length of two segments projected along a given direction
+ * \param[in] nDim - Number of dimensions
+ * \param[in] A1 - first point of segment A
+ * \param[in] A2 - second point of segment A
+ * \param[in] B1 - first point of segment B
+ * \param[in] B2 - second point of segment B
+ * \param[in] Direction - along which segments are projected
+ */
+ static su2double ComputeLineIntersectionLength(unsigned short nDim, const su2double* A1, const su2double* A2,
+ const su2double* B1, const su2double* B2, const su2double* Direction);
+
+ /*!
+ * \brief For 3-Dimensional grids, compute intersection area between two triangle projected on a given plane
+ * \param[in] A1 - first point of triangle A
+ * \param[in] A2 - second point of triangle A
+ * \param[in] A3 - third point of triangle A
+ * \param[in] B1 - first point of triangle B
+ * \param[in] B2 - second point of triangle B
+ * \param[in] B3 - third point of triangle B
+ * \param[in] Direction - vector normal to projection plane
+ */
+ static su2double Compute_Triangle_Intersection(const su2double* A1, const su2double* A2, const su2double* A3,
+ const su2double* B1, const su2double* B2, const su2double* B3,
+ const su2double* Direction);
+
+ /*!
+ * \brief For 3-Dimensional grids, compute intersection area between two triangle projected on a given plane
+ * P1 from triangle P MUST be inside triangle Q, points order doesn't matter
+ * \param[in] P1 - first point of triangle A
+ * \param[in] P2 - second point of triangle A
+ * \param[in] P3 - third point of triangle A
+ * \param[in] Q1 - first point of triangle B
+ * \param[in] Q2 - second point of triangle B
+ * \param[in] Q3 - third point of triangle B
+ */
+ static su2double ComputeIntersectionArea(const su2double* P1, const su2double* P2, const su2double* P3,
+ const su2double* Q1, const su2double* Q2, const su2double* Q3);
+
+ /*!
+ * \brief For 2-Dimensional grids, check whether, and compute, two lines are intersecting
+ * \param[in] A1 - first defining first line
+ * \param[in] A2 - second defining first line
+ * \param[in] B1 - first defining second line
+ * \param[in] B2 - second defining second line
+ * \param[out] IntersectionPoint - Container for intersection coordinates
+ */
+ static void ComputeLineIntersectionPoint(const su2double* A1, const su2double* A2, const su2double* B1,
+ const su2double* B2, su2double* IntersectionPoint);
+
+ /*!
+ * \brief For N-Dimensional grids, check whether a point is inside a triangle specified by 3 T points
+ * \param[in] Point - query point
+ * \param[in] T1 - first point of triangle T
+ * \param[in] T2 - second point of triangle T
+ * \param[in] T3 - third point of triangle T
+ */
+ static bool CheckPointInsideTriangle(const su2double* Point, const su2double* T1,
+ const su2double* T2, const su2double* T3);
+};
diff --git a/Common/include/interpolation_structure.hpp b/Common/include/interpolation_structure.hpp
deleted file mode 100644
index 3ea27b746b9d..000000000000
--- a/Common/include/interpolation_structure.hpp
+++ /dev/null
@@ -1,491 +0,0 @@
-/*!
- * \file interpolation_structure.hpp
- * \brief Headers of classes used for multiphysics interpolation.
- * The implementation is in the interpolation_structure.cpp file.
- * \author H. Kline
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-
-#pragma once
-
-#include "../../Common/include/mpi_structure.hpp"
-
-#include
-#include
-#include
-#include
-#include
-
-#include "CConfig.hpp"
-#include "geometry/CGeometry.hpp"
-
-using namespace std;
-
-
-/*!
- * \class CInterpolator
- * \brief Main class for defining the interpolator, it requires
- * a child class for each particular interpolation method
- * \author H. Kline
- */
-class CInterpolator {
-protected:
- int rank, /*!< \brief MPI Rank. */
- size; /*!< \brief MPI Size. */
- unsigned int nZone; /*!< \brief Number of zones*/
- unsigned int donorZone,
- targetZone; /*!< \brief Type of MPI zone */
-
- unsigned long
- MaxLocalVertex_Donor, /*!< \brief Maximum vertices per processor*/
- nGlobalFace_Donor, /*!< \brief Number of global donor faces*/
- nGlobalFaceNodes_Donor, /*!< \brief Number of global donor face nodes*/
- MaxFace_Donor, /*!< \brief Maximum faces per processor*/
- MaxFaceNodes_Donor; /*!< \brief Maximum nodes associated with faces per processor*/
-
- unsigned long
- *Buffer_Receive_nVertex_Donor, /*!< \brief Buffer to store the number of vertices per processor on the Donor domain */
- *Buffer_Receive_nFace_Donor, /*!< \brief Buffer to store the number of faces per processor*/
- *Buffer_Receive_nFaceNodes_Donor, /*!< \brief Buffer to store the number of nodes associated with faces per processor*/
- *Buffer_Send_nVertex_Donor, /*!< \brief Buffer to send number of vertices on the local processor*/
- *Buffer_Send_nFace_Donor, /*!< \brief Buffer to send number of faces on the local processor*/
- *Buffer_Send_nFaceNodes_Donor, /*!< \brief Buffer to send the number of nodes assocated with faces per processor*/
- *Buffer_Send_FaceIndex, /*!< \brief Buffer to send indices pointing to the node indices that define the faces*/
- *Buffer_Receive_FaceIndex, /*!< \brief Buffer to receive indices pointing to the node indices that define the faces*/
- *Buffer_Send_FaceNodes, /*!< \brief Buffer to send indices pointing to the location of node information in other buffers, defining faces*/
- *Buffer_Receive_FaceNodes, /*!< \brief Buffer to receive indices pointing to the location of node information in other buffers, defining faces*/
- *Buffer_Send_FaceProc, /*!< \brief Buffer to send processor which stores the node indicated in Buffer_Receive_FaceNodes*/
- *Buffer_Receive_FaceProc; /*!< \brief Buffer to receive processor which stores the node indicated in Buffer_Receive_FaceNodes*/
-
- long *Buffer_Send_GlobalPoint, /*!< \brief Buffer to send global point indices*/
- *Buffer_Receive_GlobalPoint; /*!< \brief Buffer to receive global point indices*/
-
- su2double *Buffer_Send_Coord, /*!< \brief Buffer to send coordinate values*/
- *Buffer_Send_Normal, /*!< \brief Buffer to send normal vector values */
- *Buffer_Receive_Coord, /*!< \brief Buffer to receive coordinate values*/
- *Buffer_Receive_Normal; /*!< \brief Buffer to receive normal vector values*/
-
- unsigned long *Receive_GlobalPoint, /*!< \brief Buffer to receive Global point indexes*/
- *Buffer_Receive_nLinkedNodes, /*!< \brief Buffer to receive the number of edges connected to each node*/
- *Buffer_Receive_LinkedNodes, /*!< \brief Buffer to receive the list of notes connected to the nodes through an edge*/
- *Buffer_Receive_StartLinkedNodes, /*!< \brief Buffer to receive the index of the Receive_LinkedNodes buffer where corresponding list of linked nodes begins */
- *Buffer_Receive_Proc; /*!< \brief Buffer to receive the thread that owns the node*/
-
- unsigned long nGlobalVertex_Target, /*!< \brief Global number of vertex of the target boundary*/
- nLocalVertex_Target, /*!< \brief Number of vertex of the target boundary owned by the thread*/
- nGlobalVertex_Donor, /*!< \brief Global number of vertex of the donor boundary*/
- nLocalVertex_Donor, /*!< \brief Number of vertex of the donor boundary owned by the thread*/
- nGlobalVertex, /*!< \brief Dummy variable to temporarily store the global number of vertex of a boundary*/
- nLocalLinkedNodes; /*!< \brief Dummy variable to temporarily store the number of vertex of a boundary*/
-
-public:
- CGeometry**** Geometry; /*! \brief Vector which stores n zones of geometry. */
- CGeometry* donor_geometry; /*! \brief Vector which stores the donor geometry. */
- CGeometry* target_geometry; /*! \brief Vector which stores the target geometry. */
-
- /*!
- * \brief Constructor of the class.
- */
- CInterpolator(void);
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iZone - index of the donor zone
- * \param[in] jZone - index of the target zone
- */
- CInterpolator(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- virtual ~CInterpolator(void);
-
- /*!
- * \brief Find the index of the interface marker shared by that zone
- * \param[in] config - Definition of the particular problem.
- * \param[in] val_marker_interface - Interface tag.
- */
- int Find_InterfaceMarker(CConfig *config, unsigned short val_marker_interface);
-
- /*!
- * \brief Check whether the interface should be processed or not
- * \param[in] val_markDonor - Marker tag from donor zone.
- * \param[in] val_markTarget - Marker tag from target zone.
- */
- bool CheckInterfaceBoundary(int val_markDonor, int val_markTarget);
-
- /*!
- * \brief Recontstruct the boundary connectivity from parallel partitioning and broadcasts it to all threads
- * \param[in] val_zone - index of the zone
- * \param[in] val_marker - index of the marker
- */
- void ReconstructBoundary(unsigned long val_zone, int val_marker);
-
- /*!
- * \brief compute distance between 2 points
- * \param[in] point_i
- * \param[in] point_i
- */
- su2double PointsDistance(su2double *point_i, su2double *point_j);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- virtual void Set_TransferCoeff(CConfig **config);
-
- /*!
- * \brief Determine array sizes used to collect and send coordinate and global point
- * information.
- * \param[in] faces - boolean that determines whether or not to set face information as well
- * \param[in] markDonor - Index of the boundary on the donor domain.
- * \param[in] markTarget - Index of the boundary on the target domain.
- * \param[in] nVertexDonor - Number of vertices on the donor boundary.
- * \param[in] nDim - number of physical dimensions.
- */
- void Determine_ArraySize(bool faces, int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim);
-
- /*!
- * \brief Collect and communicate vertex info: coord, global point, and if faces=true the normal vector
- * \param[in] faces - boolean that determines whether or not to set face information as well
- * \param[in] markDonor - Index of the boundary on the donor domain.
- * \param[in] markTarget - Index of the boundary on the target domain.
- * \param[in] nVertexDonor - Number of vertices on the donor boundary.
- * \param[in] nDim - number of physical dimensions.
- */
- void Collect_VertexInfo(bool faces, int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim);
-
-};
-
-/*!
- * \brief Nearest Neighbor interpolation
- */
-class CNearestNeighbor : public CInterpolator {
-public:
-
- /*!
- * \brief Constructor of the class.
- */
- CNearestNeighbor(void);
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iZone - index of the donor zone
- * \param[in] jZone - index of the target zone
- */
- CNearestNeighbor(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CNearestNeighbor(void);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- void Set_TransferCoeff(CConfig **config);
-
-};
-
-/*!
- * \brief Isoparametric interpolation
- */
-class CIsoparametric : public CInterpolator {
-public:
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iZone - index of the donor zone
- * \param[in] jZone - index of the target zone
- */
- CIsoparametric(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CIsoparametric(void);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- void Set_TransferCoeff(CConfig **config);
-
- /*!
- * \brief Calculate the isoparametric representation of point iVertex in marker iZone_0 by nodes of element donor_elem in marker jMarker of zone iZone_1.
- * \param[in] iVertex - vertex index of the point being interpolated.
- * \param[in] nDim - the dimension of the coordinates.
- * \param[in] iZone_1 - zone index of the element to use for interpolation (the DONOR zone)
- * \param[in] donor_elem - element index of the element to use for interpolation (or global index of a point in 2D)
- * \param[in] nDonorPoints - number of donor points in the element.
- * \param[in] xj - point projected onto the plane of the donor element.
- * \param[out] isoparams - isoparametric coefficients. Must be allocated to size nNodes ahead of time. (size> nDonors)
- *
- * If the problem is 2D, the 'face' projected onto is actually an edge; the local index
- * of the edge is then stored in iFace, and the global index of the node (from which the edge
- * is referenced)
- */
- void Isoparameters(unsigned short nDim, unsigned short nDonor, su2double *X, su2double *xj,su2double* isoparams);
-
-};
-
-/*!
- * \brief Mirror interpolation: copy point linking and coefficient values from the opposing mesh
- * Assumes that the oppoosing mesh has already run interpolation. (otherwise this will result in empty/trivial interpolation)
- */
-class CMirror : public CInterpolator {
-public:
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry_container
- * \param[in] config - config container
- * \param[in] iZone - First zone
- * \param[in] jZone - Second zone
- *
- * Data is set in geometry[targetZone]
- *
- */
- CMirror(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CMirror(void);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- void Set_TransferCoeff(CConfig **config);
-
-};
-
-/*!
- * \brief Sliding mesh approach
- */
-class CSlidingMesh : public CInterpolator {
-public:
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iZone - index of the donor zone
- * \param[in] jZone - index of the target zone
- */
- CSlidingMesh(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CSlidingMesh(void);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- void Set_TransferCoeff(CConfig **config);
-
- /*!
- * \brief For 3-Dimensional grids, build the dual surface element
- * \param[in] map - array containing the index of the boundary points connected to the node
- * \param[in] startIndex - for each vertex specifies the corresponding index in the global array containing the indexes of all its neighbouring vertexes
- * \param[in] nNeighbour - for each vertex specifies the number of its neighbouring vertexes (on the boundary)
- * \param[in] coord - array containing the coordinates of all the boundary vertexes
- * \param[in] centralNode - label of the vertex around which the dual surface element is built
- * \param[in] element - double array where element node coordinates will be stored
- */
- int Build_3D_surface_element(unsigned long *map, unsigned long *startIndex, unsigned long* nNeighbor, su2double *coord, unsigned long centralNode, su2double** element);
-
- /*!
- * \brief For 2-Dimensional grids, compute intersection length of two segments projected along a given direction
- * \param[in] A1 - first point of segment A
- * \param[in] A2 - second point of segment A
- * \param[in] B1 - first point of segment B
- * \param[in] B2 - second point of segment B
- * \param[in] Direction - along which segments are projected
- */
- su2double ComputeLineIntersectionLength(su2double* A1, su2double* A2, su2double* B1, su2double* B2, su2double* Direction);
-
- /*!
- * \brief For 3-Dimensional grids, compute intersection area between two triangle projected on a given plane
- * \param[in] A1 - first point of triangle A
- * \param[in] A2 - second point of triangle A
- * \param[in] A3 - third point of triangle A
- * \param[in] B1 - first point of triangle B
- * \param[in] B2 - second point of triangle B
- * \param[in] B3 - third point of triangle B
- * \param[in] Direction - vector normal to projection plane
- */
- su2double Compute_Triangle_Intersection(su2double* A1, su2double* A2, su2double* A3, su2double* B1, su2double* B2, su2double* B3, su2double* Direction);
-
- /*!
- * \brief For 3-Dimensional grids, compute intersection area between two triangle projected on a given plane
- * P1 from triangle P MUST be inside triangle Q, points order doesn't matter
- * \param[in] P1 - first point of triangle A
- * \param[in] P2 - second point of triangle A
- * \param[in] P3 - third point of triangle A
- * \param[in] Q1 - first point of triangle B
- * \param[in] Q2 - second point of triangle B
- * \param[in] Q3 - third point of triangle B
- */
- su2double ComputeIntersectionArea( su2double* P1, su2double* P2, su2double* P3, su2double* Q1, su2double* Q2, su2double* Q3 );
-
- /*!
- * \brief For 2-Dimensional grids, check whether, and compute, two lines are intersecting
- * \param[in] A1 - first defining first line
- * \param[in] A2 - second defining first line
- * \param[in] B1 - first defining second line
- * \param[in] B2 - second defining second line
- * \param[in] IntersectionPoint - Container for intersection coordinates
- */
- void ComputeLineIntersectionPoint( su2double* A1, su2double* A2, su2double* B1, su2double* B2, su2double* IntersectionPoint );
-
- /*!
- * \brief For N-Dimensional grids, check whether a point is inside a triangle specified by 3 T points
- * \param[in] Point - query point
- * \param[in] T1 - first point of triangle T
- * \param[in] T2 - second point of triangle T
- * \param[in] T3 - third point of triangle T
- */
- bool CheckPointInsideTriangle(su2double* Point, su2double* T1, su2double* T2, su2double* T3);
-};
-
-/*!
- * \brief Radial basis function interpolation
- */
-class CRadialBasisFunction : public CInterpolator {
-public:
-
- /*!
- * \brief Constructor of the class.
- */
- CRadialBasisFunction(void);
-
- /*!
- * \brief Constructor of the class.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iZone - index of the donor zone
- * \param[in] jZone - index of the target zone
- */
- CRadialBasisFunction(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CRadialBasisFunction(void);
-
- /*!
- * \brief Set up transfer matrix defining relation between two meshes
- * \param[in] config - Definition of the particular problem.
- */
- void Set_TransferCoeff(CConfig **config);
-
- /*!
- * \brief Compute the value of a radial basis function, this is static so it can be re-used.
- * \param[in] type - of radial basis function
- * \param[in] radius - the characteristic dimension
- * \param[in] dist - distance
- */
- static su2double Get_RadialBasisValue(const short unsigned int type, const su2double &radius, const su2double &dist);
-
-private:
- /*!
- * \brief If the polynomial term is included in the interpolation, and the points lie on a plane, the matrix becomes rank deficient
- * and cannot be inverted. This method detects that condition and corrects it by removing a row from P (the polynomial part of the matrix).
- * \param[in] m - number of rows of P
- * \param[in] n - number of columns of P
- * \param[in] skip_row - marks the row of P which is all ones (by construction)
- * \param[in] max_diff_tol_in - tolerance to detect points are on a plane
- * \param[out] keep_row - marks the rows of P kept
- * \param[out] n_polynomial - size of the polynomial part on exit (i.e. new number of rows)
- * \param[in,out] P - polynomial part of the matrix, may be changed or not!
- */
- void Check_PolynomialTerms(int m, unsigned long n, const int *skip_row, su2double max_diff_tol_in, int *keep_row, int &n_polynomial, su2double *P);
-
-};
-
-/*!
- * \brief Helper class used by CRadialBasisFunction to calculate the interpolation weights.
- * This does not inherit from CSysMatrix because: it is a dense format rather than block sparse;
- * as the interpolation is done on a single core there are no methods for communication.
- * The code can be compiled with LAPACK to use optimized matrix inversion and multiplication routines.
- * CPPFLAGS="-DHAVE_LAPACK" LDFLAGS=-L/path/to/lapack_lib LIBS="-llapack -lrefblas -lgfortran"
- */
-class CSymmetricMatrix{
-
- private:
-
- bool initialized, inversed;
- int sz, num_val;
- int *perm_vec;
- passivedouble *val_vec, *decompose_vec, *inv_val_vec;
-
- enum DecompositionType { none, cholesky, lu };
-
- DecompositionType decomposed;
-
- inline int CalcIdx(int i, int j);
- inline int CalcIdxFull(int i, int j);
- inline void CheckBounds(int i, int j);
-
- passivedouble ReadL(int i, int j);
- passivedouble ReadU(int i, int j);
- passivedouble ReadInv(int i,int j);
-
- // not optimized dense matrix factorization and inversion for portability
- void CholeskyDecompose(bool overwrite);
- void LUDecompose();
- void CalcInv(bool overwrite);
- // matrix inversion using LAPACK routines (LDLT factorization)
- void CalcInv_sptri();
- void CalcInv_potri() {}; // LLT not implemented yet
-
- public:
-
- /*--- Methods ---*/
- CSymmetricMatrix();
- ~CSymmetricMatrix();
-
- void Initialize(int N);
- void Initialize(int N, su2double *formed_val_vec);
-
- inline int GetSize();
-
- void Write(int i, int j, const su2double& val);
- passivedouble Read(int i, int j);
-
- void MatVecMult(passivedouble *v);
- void MatMatMult(bool left_mult, su2double *mat_vec, int N);
- void Invert(const bool is_spd);
-
-};
diff --git a/Common/include/linear_algebra/CSysSolve.hpp b/Common/include/linear_algebra/CSysSolve.hpp
index df2848de37da..8f514a1c5bc3 100644
--- a/Common/include/linear_algebra/CSysSolve.hpp
+++ b/Common/include/linear_algebra/CSysSolve.hpp
@@ -48,6 +48,10 @@ template class CPreconditioner;
using namespace std;
+/*--- Relative tolerance, target residual is tol*||b-Ax||,
+ * Absolute tolerance, target residual is tol*||b||. ---*/
+enum class LinearToleranceType {RELATIVE, ABSOLUTE};
+
/*!
* \class CSysSolve
* \brief Class for solving linear systems using classical and Krylov-subspace iterative methods
@@ -98,6 +102,8 @@ class CSysSolve {
VectorType* LinSysSol_ptr; /*!< \brief Pointer to appropriate LinSysSol (set to original or temporary in call to Solve). */
const VectorType* LinSysRes_ptr; /*!< \brief Pointer to appropriate LinSysRes (set to original or temporary in call to Solve). */
+ LinearToleranceType tol_type = LinearToleranceType::RELATIVE; /*!< \brief How the linear solvers interpret the tolerance. */
+
/*!
* \brief sign transfer function
* \param[in] x - value having sign prescribed
@@ -313,4 +319,9 @@ class CSysSolve {
*/
inline ScalarType GetResidual(void) const { return Residual; }
+ /*!
+ * \brief Set the type of the tolerance for stoping the linear solvers (RELATIVE or ABSOLUTE).
+ */
+ inline void SetToleranceType(LinearToleranceType type) {tol_type = type;}
+
};
diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp
index 99a4326edc8f..4f53145cb13a 100644
--- a/Common/include/option_structure.hpp
+++ b/Common/include/option_structure.hpp
@@ -372,9 +372,7 @@ enum ENUM_TRANSFER {
NO_COMMON_INTERFACE = 1, /*!< \brief No common interface between the zones (geometrical). */
NO_TRANSFER = 2, /*!< \brief Zones may share a boundary, but still no coupling desired. */
FLOW_TRACTION = 10, /*!< \brief Flow traction coupling (between fluids and solids). */
- STRUCTURAL_DISPLACEMENTS_LEGACY = 11, /*!< \brief Structural displacements (between fluids and solids) - legacy version (to be removed). */
BOUNDARY_DISPLACEMENTS = 21, /*!< \brief Boundary displacements (between fluids and solids) */
- STRUCTURAL_DISPLACEMENTS_DISC_ADJ = 12, /*!< \brief Adjoints of structural displacements (between fluids and solids). */
SLIDING_INTERFACE = 13, /*!< \brief Sliding interface (between fluids). */
CONSERVATIVE_VARIABLES = 14, /*!< \brief General coupling that simply transfers the conservative variables (between same solvers). */
MIXING_PLANE = 15, /*!< \brief Mixing plane between fluids. */
@@ -650,14 +648,12 @@ enum ENUM_SURFACEMOVEMENT {
FLUID_STRUCTURE = 5, /*!< \brief Fluid structure deformation. */
EXTERNAL = 6, /*!< \brief Simulation with external motion. */
EXTERNAL_ROTATION = 7, /*!< \brief Simulation with external rotation motion. */
- FLUID_STRUCTURE_STATIC = 8 /*!< \brief Fluid structure deformation with no grid velocity. */
};
static const MapType SurfaceMovement_Map = {
MakePair("DEFORMING", DEFORMING)
MakePair("MOVING_WALL", MOVING_WALL)
MakePair("AEROELASTIC_RIGID_MOTION", AEROELASTIC_RIGID_MOTION)
MakePair("AEROELASTIC", AEROELASTIC)
- MakePair("FLUID_STRUCTURE_STATIC", FLUID_STRUCTURE_STATIC)
MakePair("FLUID_STRUCTURE", FLUID_STRUCTURE)
MakePair("EXTERNAL", EXTERNAL)
MakePair("EXTERNAL_ROTATION", EXTERNAL_ROTATION)
diff --git a/Common/include/toolboxes/C2DContainer.hpp b/Common/include/toolboxes/C2DContainer.hpp
index c495e76de0cf..507e1d5703e9 100644
--- a/Common/include/toolboxes/C2DContainer.hpp
+++ b/Common/include/toolboxes/C2DContainer.hpp
@@ -113,15 +113,14 @@ class AccessorImpl
\
AccessorImpl& operator= (AccessorImpl&& other) noexcept \
{ \
- if(m_data!=nullptr) free(m_data); \
+ MemoryAllocation::aligned_free(m_data); \
MOVE; m_data=other.m_data; other.m_data=nullptr; \
return *this; \
} \
\
~AccessorImpl() \
{ \
- if(m_data!=nullptr) \
- MemoryAllocation::aligned_free(m_data); \
+ MemoryAllocation::aligned_free(m_data); \
}
/*!
* Shorthand for when specialization has only one more member than m_data.
@@ -371,6 +370,7 @@ class C2DContainer :
using Base::size;
using Index = Index_t;
using Scalar = Scalar_t;
+ static constexpr StorageType Storage = Store;
private:
/*!
@@ -380,7 +380,7 @@ class C2DContainer :
{
/*--- fully static, no allocation needed ---*/
if(StaticRows!=DynamicSize && StaticCols!=DynamicSize)
- return StaticRows*StaticCols;
+ return StaticRows*StaticCols;
/*--- dynamic row vector, swap size specification ---*/
if(StaticRows==1 && StaticCols==DynamicSize) {cols = rows; rows = 1;}
@@ -399,12 +399,10 @@ class C2DContainer :
/*--- compare with current dimensions to determine if deallocation
is needed, also makes the container safe against self assignment
no need to check for 0 size as the allocators handle that ---*/
- if(m_data!=nullptr)
- {
- if(rows==this->rows() && cols==this->cols())
- return reqSize;
- free(m_data);
- }
+ if(rows==this->rows() && cols==this->cols())
+ return reqSize;
+
+ MemoryAllocation::aligned_free(m_data);
/*--- request actual allocation to base class as it needs specialization ---*/
size_t bytes = reqSize*sizeof(Scalar_t);
diff --git a/Common/include/toolboxes/CSymmetricMatrix.hpp b/Common/include/toolboxes/CSymmetricMatrix.hpp
new file mode 100644
index 000000000000..05ec1d871605
--- /dev/null
+++ b/Common/include/toolboxes/CSymmetricMatrix.hpp
@@ -0,0 +1,87 @@
+/*!
+ * \file CSymmetricMatrix.hpp
+ * \brief Dense symmetric matrix, used for example in RBF interpolation.
+ * \author Joel Ho, P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+#pragma once
+
+#include
+#include "C2DContainer.hpp"
+
+using namespace std;
+
+/*!
+ * \brief The matrix is symmetric but full storage is used as that gives much better
+ * performance for some BLAS libraries (notably OpenBLAS). The code should be compiled
+ * with LAPACK to use optimized matrix inversion and multiplication routines.
+ */
+class CSymmetricMatrix {
+ static_assert(su2passivematrix::Storage == StorageType::RowMajor,
+ "Row major storage is assumed for LAPACK.");
+private:
+ su2passivematrix mat;
+
+ // Not optimized dense matrix factorization and inversion for portability.
+ void CalcInv(bool is_spd);
+ void CholeskyDecompose();
+ void LUDecompose(su2passivematrix& decomp, vector& perm) const;
+ // Matrix inversion using LAPACK routines (LDLT and LLT factorization).
+ void CalcInv_sytri();
+ void CalcInv_potri();
+
+public:
+ CSymmetricMatrix() = default;
+ CSymmetricMatrix(int N) {Initialize(N);}
+
+ void Initialize(int N);
+
+ inline int Size() const { return mat.rows(); }
+
+ inline passivedouble Get(int i, int j) const { return mat(min(i,j),max(i,j)); }
+
+ inline void Set(int i, int j, passivedouble val) { mat(min(i,j),max(i,j)) = val; }
+
+ inline passivedouble& operator() (int i, int j) { return mat(min(i,j),max(i,j)); }
+
+ inline const passivedouble& operator() (int i, int j) const { return mat(min(i,j),max(i,j)); }
+
+ template
+ void MatVecMult(ForwardIt vec_in, ForwardIt vec_out) const
+ {
+ for (int i = 0; i < Size(); ++i) {
+ *vec_out = 0.0;
+ auto vec = vec_in;
+ for (int k = 0; k < Size(); ++k)
+ *vec_out += *(vec++) * Get(i,k);
+ ++vec_out;
+ }
+ }
+
+ void MatMatMult(const char side, const su2passivematrix& mat_in, su2passivematrix& mat_out) const;
+
+ void Invert(bool is_spd = false);
+
+ su2passivematrix StealData();
+
+};
diff --git a/Common/include/toolboxes/geometry_toolbox.hpp b/Common/include/toolboxes/geometry_toolbox.hpp
new file mode 100644
index 000000000000..4fcb616a5f7f
--- /dev/null
+++ b/Common/include/toolboxes/geometry_toolbox.hpp
@@ -0,0 +1,186 @@
+/*!
+ * \file geometry_toolbox.hpp
+ * \brief Collection of common lightweight geometry-oriented methods.
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#pragma once
+
+namespace GeometryToolbox {
+
+/*! \return ||a-b||^2 */
+template
+inline T SquaredDistance(Int nDim, const T* a, const T* b) {
+ T d(0);
+ for(Int i = 0; i < nDim; i++) d += pow(a[i]-b[i], 2);
+ return d;
+}
+
+/*! \return ||a-b|| */
+template
+inline T Distance(Int nDim, const T* a, const T* b) {
+ return sqrt(SquaredDistance(nDim, a, b));
+}
+
+/*! \brief d = a-b */
+template
+inline void Distance(Int nDim, const T* a, const T* b, T* d) {
+ for(Int i = 0; i < nDim; i++) d[i] = a[i] - b[i];
+}
+
+/*! \return a.b */
+template
+inline T DotProduct(Int nDim, const T* a, const T* b) {
+ T d(0);
+ for (Int i = 0; i < nDim; ++i) d += a[i]*b[i];
+ return d;
+}
+
+/*! \return ||a||^2 */
+template
+inline T SquaredNorm(Int nDim, const T* a) {
+ return DotProduct(nDim, a, a);
+}
+
+/*! \return ||a|| */
+template
+inline T Norm(Int nDim, const T* a) {
+ return sqrt(SquaredNorm(nDim, a));
+}
+
+/*! \brief c = a x b */
+template
+inline void CrossProduct(const T* a, const T* b, T* c) {
+ c[0] = a[1]*b[2] - a[2]*b[1];
+ c[1] = a[2]*b[0] - a[0]*b[2];
+ c[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+/*!
+ * \brief Compute the coordinate (c) where the line defined by coordinate l0 and
+ * direction d intersects the plane defined by point p0 and normal n.
+ * \return The intersection distance.
+ */
+template
+inline T LinePlaneIntersection(const T* l0, const T* d, const T* p0, const T* n, T* c) {
+ T dist[nDim] = {0.0};
+ Distance(nDim, p0, l0, dist);
+ T alpha = DotProduct(nDim, dist, n) / DotProduct(nDim, d, n);
+ for (int iDim = 0; iDim < nDim; ++iDim)
+ c[iDim] = l0[iDim] + alpha * d[iDim];
+ return fabs(alpha) * Norm(nDim,d);
+}
+
+/*!
+ * \brief Compute the coordinate (c) where point p1 intersects the plane defined
+ * by point p0 and normal n if projected perpendicular to it.
+ * \return The normal distance.
+ */
+template
+inline T PointPlaneProjection(const T* p1, const T* p0, const T* n, T* c) {
+ return LinePlaneIntersection(p1, n, p0, n, c);
+}
+
+/*! \brief Set U as the normal to a 2D line defined by coords[iPoint][iDim]. */
+template
+inline void LineNormal(const T& coords, U* normal) {
+ normal[0] = coords[0][1] - coords[1][1];
+ normal[1] = coords[1][0] - coords[0][0];
+}
+
+/*! \brief Normal vector of a triangle, cross product of two sides. */
+template
+inline void TriangleNormal(const T& coords, U* normal) {
+
+ U a[3], b[3];
+
+ for (int iDim = 0; iDim < 3; iDim++) {
+ a[iDim] = coords[1][iDim] - coords[0][iDim];
+ b[iDim] = coords[2][iDim] - coords[0][iDim];
+ }
+
+ CrossProduct(a, b, normal);
+ normal[0] *= 0.5; normal[1] *= 0.5; normal[2] *= 0.5;
+}
+
+/*! \brief Normal vector of a quadrilateral, cross product of the two diagonals. */
+template
+inline void QuadrilateralNormal(const T& coords, U* normal) {
+
+ U a[3], b[3];
+
+ for (int iDim = 0; iDim < 3; iDim++) {
+ a[iDim] = coords[2][iDim] - coords[0][iDim];
+ b[iDim] = coords[3][iDim] - coords[1][iDim];
+ }
+
+ CrossProduct(a, b, normal);
+ normal[0] *= 0.5; normal[1] *= 0.5; normal[2] *= 0.5;
+}
+
+/*!
+ * \brief Compute a 3D rotation matrix.
+ * \note The implicit ordering is rotation about the x, y, and then z axis.
+ */
+template
+inline void RotationMatrix(Scalar theta, Scalar phi, Scalar psi, Matrix& mat) {
+
+ Scalar cosTheta = cos(theta); Scalar cosPhi = cos(phi); Scalar cosPsi = cos(psi);
+ Scalar sinTheta = sin(theta); Scalar sinPhi = sin(phi); Scalar sinPsi = sin(psi);
+
+ mat[0][0] = cosPhi*cosPsi;
+ mat[1][0] = cosPhi*sinPsi;
+ mat[2][0] = -sinPhi;
+
+ mat[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
+ mat[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
+ mat[2][1] = sinTheta*cosPhi;
+
+ mat[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
+ mat[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
+ mat[2][2] = cosTheta*cosPhi;
+}
+
+/*! \brief Compute a 2D rotation matrix. */
+template
+inline void RotationMatrix(Scalar psi, Matrix& mat) {
+
+ Scalar cosPsi = cos(psi);
+ Scalar sinPsi = sin(psi);
+
+ mat[0][0] = cosPsi; mat[0][1] =-sinPsi;
+ mat[1][0] = sinPsi; mat[1][1] = cosPsi;
+}
+
+/*! \brief Apply a rotation matrix (R) about origin (O) to a point at
+ * distance (d) from it to obtain new coordinate (c). */
+template
+inline void Rotate(const Scalar R[][nDim], const Scalar* O, const Scalar* d, Scalar* c) {
+
+ for (int iDim = 0; iDim < nDim; ++iDim) {
+ c[iDim] = O[iDim];
+ for (int k = 0; k < nDim; ++k) c[iDim] += R[iDim][k] * d[k];
+ }
+}
+
+}
diff --git a/Common/lib/Makefile.am b/Common/lib/Makefile.am
index 3c0348826315..59f08d78e097 100644
--- a/Common/lib/Makefile.am
+++ b/Common/lib/Makefile.am
@@ -93,12 +93,19 @@ lib_sources = \
../src/geometry/primal_grid/CTetrahedron.cpp \
../src/geometry/primal_grid/CQuadrilateral.cpp \
../src/geometry/primal_grid/CVertexMPI.cpp \
- ../src/interpolation_structure.cpp \
+ ../src/interface_interpolation/CInterpolatorFactory.cpp \
+ ../src/interface_interpolation/CInterpolator.cpp \
+ ../src/interface_interpolation/CMirror.cpp \
+ ../src/interface_interpolation/CSlidingMesh.cpp \
+ ../src/interface_interpolation/CIsoparametric.cpp \
+ ../src/interface_interpolation/CNearestNeighbor.cpp \
+ ../src/interface_interpolation/CRadialBasisFunction.cpp \
../src/adt_structure.cpp \
../src/wall_model.cpp \
../src/toolboxes/printing_toolbox.cpp \
../src/toolboxes/CLinearPartitioner.cpp \
../src/toolboxes/C1DInterpolation.cpp \
+ ../src/toolboxes/CSymmetricMatrix.cpp \
../src/toolboxes/MMS/CVerificationSolution.cpp \
../src/toolboxes/MMS/CIncTGVSolution.cpp \
../src/toolboxes/MMS/CInviscidVortexSolution.cpp \
diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp
index 634a64e02f79..2f0e07136ffc 100644
--- a/Common/src/CConfig.cpp
+++ b/Common/src/CConfig.cpp
@@ -935,7 +935,7 @@ void CConfig::SetPointersNull(void) {
Kind_SurfaceMovement = NULL;
LocationStations = NULL;
Motion_Origin = NULL;
- Translation_Rate = NULL;
+ Translation_Rate = NULL;
Rotation_Rate = NULL;
Pitching_Omega = NULL;
Pitching_Ampl = NULL;
@@ -943,7 +943,7 @@ void CConfig::SetPointersNull(void) {
Plunging_Omega = NULL;
Plunging_Ampl = NULL;
MarkerMotion_Origin = NULL;
- MarkerTranslation_Rate = NULL;
+ MarkerTranslation_Rate = NULL;
MarkerRotation_Rate = NULL;
MarkerPitching_Omega = NULL;
MarkerPitching_Ampl = NULL;
@@ -1118,8 +1118,6 @@ void CConfig::SetConfig_Options() {
/*!\brief WEAKLY_COUPLED_HEAT_EQUATION \n DESCRIPTION: Enable heat equation for incompressible flows. \ingroup Config*/
addBoolOption("WEAKLY_COUPLED_HEAT_EQUATION", Weakly_Coupled_Heat, NO);
- addBoolOption("ADJ_FSI", FSI_Problem, NO);
-
/*\brief AXISYMMETRIC \n DESCRIPTION: Axisymmetric simulation \n DEFAULT: false \ingroup Config */
addBoolOption("AXISYMMETRIC", Axisymmetric, false);
/* DESCRIPTION: Add the gravity force */
@@ -1701,9 +1699,6 @@ void CConfig::SetConfig_Options() {
/* DESCRIPTION: Preconditioner for the discrete adjoint Krylov linear solvers */
addEnumOption("DISCADJ_LIN_PREC", Kind_DiscAdj_Linear_Prec, Linear_Solver_Prec_Map, ILU);
/* DESCRIPTION: Linear solver for the discete adjoint systems */
- addEnumOption("FSI_DISCADJ_LIN_SOLVER_STRUC", Kind_DiscAdj_Linear_Solver_FSI_Struc, Linear_Solver_Map, CONJUGATE_GRADIENT);
- /* DESCRIPTION: Preconditioner for the discrete adjoint Krylov linear solvers */
- addEnumOption("FSI_DISCADJ_LIN_PREC_STRUC", Kind_DiscAdj_Linear_Prec_FSI_Struc, Linear_Solver_Prec_Map, JACOBI);
/*!\par CONFIG_CATEGORY: Convergence\ingroup Config*/
/*--- Options related to convergence ---*/
@@ -2221,11 +2216,13 @@ void CConfig::SetConfig_Options() {
/* DESCRIPTION: Deform limit in m or inches */
addDoubleOption("DEFORM_LIMIT", Deform_Limit, 1E6);
/* DESCRIPTION: Type of element stiffness imposed for FEA mesh deformation (INVERSE_VOLUME, WALL_DISTANCE, CONSTANT_STIFFNESS) */
- addEnumOption("DEFORM_STIFFNESS_TYPE", Deform_Stiffness_Type, Deform_Stiffness_Map, SOLID_WALL_DISTANCE);
- /* DESCRIPTION: Poisson's ratio for constant stiffness FEA method of grid deformation*/
+ addEnumOption("DEFORM_STIFFNESS_TYPE", Deform_StiffnessType, Deform_Stiffness_Map, SOLID_WALL_DISTANCE);
+ /* DESCRIPTION: Poisson's ratio for constant stiffness FEA method of grid deformation */
addDoubleOption("DEFORM_ELASTICITY_MODULUS", Deform_ElasticityMod, 2E11);
- /* DESCRIPTION: Young's modulus and Poisson's ratio for constant stiffness FEA method of grid deformation*/
+ /* DESCRIPTION: Young's modulus and Poisson's ratio for constant stiffness FEA method of grid deformation */
addDoubleOption("DEFORM_POISSONS_RATIO", Deform_PoissonRatio, 0.3);
+ /* DESCRIPTION: Size of the layer of highest stiffness for wall distance-based mesh stiffness */
+ addDoubleOption("DEFORM_STIFF_LAYER_SIZE", Deform_StiffLayerSize, 0.0);
/* DESCRIPTION: Linear solver for the mesh deformation\n OPTIONS: see \link Linear_Solver_Map \endlink \n DEFAULT: FGMRES \ingroup Config*/
addEnumOption("DEFORM_LINEAR_SOLVER", Kind_Deform_Linear_Solver, Linear_Solver_Map, FGMRES);
/* \n DESCRIPTION: Preconditioner for the Krylov linear solvers \n OPTIONS: see \link Linear_Solver_Prec_Map \endlink \n DEFAULT: LU_SGS \ingroup Config*/
@@ -2394,27 +2391,6 @@ void CConfig::SetConfig_Options() {
/* CONFIG_CATEGORY: FSI solver */
/*--- Options related to the FSI solver ---*/
- /*!\brief PHYSICAL_PROBLEM_FLUID_FSI
- * DESCRIPTION: Physical governing equations \n
- * Options: NONE (default),EULER, NAVIER_STOKES, RANS,
- * \ingroup Config*/
- addEnumOption("FSI_FLUID_PROBLEM", Kind_Solver_Fluid_FSI, FSI_Fluid_Solver_Map, NO_SOLVER_FFSI);
-
- /*!\brief PHYSICAL_PROBLEM_STRUCTURAL_FSI
- * DESCRIPTION: Physical governing equations \n
- * Options: NONE (default), FEM_ELASTICITY
- * \ingroup Config*/
- addEnumOption("FSI_STRUCTURAL_PROBLEM", Kind_Solver_Struc_FSI, FSI_Struc_Solver_Map, NO_SOLVER_SFSI);
-
- /* DESCRIPTION: Linear solver for the structural side on FSI problems */
- addEnumOption("FSI_LINEAR_SOLVER_STRUC", Kind_Linear_Solver_FSI_Struc, Linear_Solver_Map, FGMRES);
- /* DESCRIPTION: Preconditioner for the Krylov linear solvers */
- addEnumOption("FSI_LINEAR_SOLVER_PREC_STRUC", Kind_Linear_Solver_Prec_FSI_Struc, Linear_Solver_Prec_Map, ILU);
- /* DESCRIPTION: Maximum number of iterations of the linear solver for the implicit formulation */
- addUnsignedLongOption("FSI_LINEAR_SOLVER_ITER_STRUC", Linear_Solver_Iter_FSI_Struc, 500);
- /* DESCRIPTION: Minimum error threshold for the linear solver for the implicit formulation */
- addDoubleOption("FSI_LINEAR_SOLVER_ERROR_STRUC", Linear_Solver_Error_FSI_Struc, 1E-6);
-
/* DESCRIPTION: ID of the region we want to compute the sensitivities using direct differentiation */
addUnsignedShortOption("FEA_ID_DIRECTDIFF", nID_DV, 0);
@@ -2457,17 +2433,17 @@ void CConfig::SetConfig_Options() {
addBoolOption("WRT_FORCES_BREAKDOWN", Wrt_ForcesBreakdown, false);
-
- /* DESCRIPTION: Use conservative approach for interpolating between meshes.
- * Options: NO, YES \ingroup Config */
- addBoolOption("CONSERVATIVE_INTERPOLATION", ConservativeInterpolation, true);
-
/*!\par KIND_INTERPOLATION \n
* DESCRIPTION: Type of interpolation to use for multi-zone problems. \n OPTIONS: see \link Interpolator_Map \endlink
* Sets Kind_Interpolation \ingroup Config
*/
addEnumOption("KIND_INTERPOLATION", Kind_Interpolation, Interpolator_Map, NEAREST_NEIGHBOR);
+ /* DESCRIPTION: Use conservative approach for interpolating between meshes. */
+ addBoolOption("CONSERVATIVE_INTERPOLATION", ConservativeInterpolation, true);
+
+ addUnsignedShortOption("NUM_NEAREST_NEIGHBORS", NumNearestNeighbors, 1);
+
/*!\par KIND_INTERPOLATION \n
* DESCRIPTION: Type of radial basis function to use for radial basis function interpolation. \n OPTIONS: see \link RadialBasis_Map \endlink
* Sets Kind_RadialBasis \ingroup Config
@@ -2478,8 +2454,11 @@ void CConfig::SetConfig_Options() {
* Options: NO, YES \ingroup Config */
addBoolOption("RADIAL_BASIS_FUNCTION_POLYNOMIAL_TERM", RadialBasisFunction_PolynomialOption, true);
- /* DESCRIPTION: Radius for radial basis function */
- addDoubleOption("RADIAL_BASIS_FUNCTION_PARAMETER", RadialBasisFunction_Parameter, 1);
+ /* DESCRIPTION: Radius for radial basis function. */
+ addDoubleOption("RADIAL_BASIS_FUNCTION_PARAMETER", RadialBasisFunction_Parameter, 1.0);
+
+ /* DESCRIPTION: Tolerance to prune small coefficients from the RBF interpolation matrix. */
+ addDoubleOption("RADIAL_BASIS_FUNCTION_PRUNE_TOLERANCE", RadialBasisFunction_PruneTol, 1e-6);
/*!\par INLETINTERPOLATION \n
* DESCRIPTION: Type of spanwise interpolation to use for the inlet face. \n OPTIONS: see \link Inlet_SpanwiseInterpolation_Map \endlink
@@ -2495,8 +2474,6 @@ void CConfig::SetConfig_Options() {
addBoolOption("PRINT_INLET_INTERPOLATED_DATA", PrintInlet_InterpolatedData, false);
- /* DESCRIPTION: Maximum number of FSI iterations */
- addUnsignedShortOption("FSI_ITER", nIterFSI, 1);
/* DESCRIPTION: Number of FSI iterations during which a ramp is applied */
addUnsignedShortOption("RAMP_FSI_ITER", nIterFSI_Ramp, 2);
/* DESCRIPTION: Aitken's static relaxation factor */
@@ -3569,11 +3546,11 @@ void CConfig::SetPostprocessing(unsigned short val_software, unsigned short val_
}
}
- if (nKind_SurfaceMovement > 1 && (GetSurface_Movement(FLUID_STRUCTURE) || GetSurface_Movement(FLUID_STRUCTURE_STATIC))){
+ if ((nKind_SurfaceMovement > 1) && GetSurface_Movement(FLUID_STRUCTURE)) {
SU2_MPI::Error("FSI in combination with moving surfaces is currently not supported.", CURRENT_FUNCTION);
}
- if (nKind_SurfaceMovement != nMarker_Moving && !(GetSurface_Movement(FLUID_STRUCTURE) || GetSurface_Movement(FLUID_STRUCTURE_STATIC))){
+ if ((nKind_SurfaceMovement != nMarker_Moving) && !GetSurface_Movement(FLUID_STRUCTURE)) {
SU2_MPI::Error("Number of KIND_SURFACE_MOVEMENT must match number of MARKER_MOVING", CURRENT_FUNCTION);
}
@@ -3824,11 +3801,10 @@ void CConfig::SetPostprocessing(unsigned short val_software, unsigned short val_
/*--- Set number of TurboPerformance markers ---*/
if(GetGrid_Movement() && RampRotatingFrame && !DiscreteAdjoint){
- FinalRotation_Rate_Z = Rotation_Rate[2];
- if(abs(FinalRotation_Rate_Z) > 0.0){
- Rotation_Rate[2] = RampRotatingFrame_Coeff[0];
- }
-
+ FinalRotation_Rate_Z = Rotation_Rate[2];
+ if(abs(FinalRotation_Rate_Z) > 0.0){
+ Rotation_Rate[2] = RampRotatingFrame_Coeff[0];
+ }
}
if(RampOutletPressure && !DiscreteAdjoint){
@@ -4923,6 +4899,9 @@ void CConfig::SetPostprocessing(unsigned short val_software, unsigned short val_
/*--- 0 in the config file means "disable" which can be done using a very large group. ---*/
if (edgeColorGroupSize==0) edgeColorGroupSize = 1<<30;
+ /*--- Specifying a deforming surface requires a mesh deformation solver. ---*/
+ if (GetSurface_Movement(DEFORMING)) Deform_Mesh = true;
+
}
void CConfig::SetMarkers(unsigned short val_software) {
@@ -4970,126 +4949,72 @@ void CConfig::SetMarkers(unsigned short val_software) {
/*--- Allocate the memory (markers in each domain) ---*/
Marker_All_TagBound = new string[nMarker_All]; // Store the tag that correspond with each marker.
- Marker_All_SendRecv = new short[nMarker_All]; // +#domain (send), -#domain (receive).
- Marker_All_KindBC = new unsigned short[nMarker_All]; // Store the kind of boundary condition.
- Marker_All_Monitoring = new unsigned short[nMarker_All]; // Store whether the boundary should be monitored.
- Marker_All_Designing = new unsigned short[nMarker_All]; // Store whether the boundary should be designed.
- Marker_All_Plotting = new unsigned short[nMarker_All]; // Store whether the boundary should be plotted.
- Marker_All_Analyze = new unsigned short[nMarker_All]; // Store whether the boundary should be plotted.
- Marker_All_ZoneInterface = new unsigned short[nMarker_All]; // Store whether the boundary is in the FSI interface.
- Marker_All_GeoEval = new unsigned short[nMarker_All]; // Store whether the boundary should be geometry evaluation.
- Marker_All_DV = new unsigned short[nMarker_All]; // Store whether the boundary should be affected by design variables.
- Marker_All_Moving = new unsigned short[nMarker_All]; // Store whether the boundary should be in motion.
- Marker_All_Deform_Mesh = new unsigned short[nMarker_All]; // Store whether the boundary is deformable.
- Marker_All_Fluid_Load = new unsigned short[nMarker_All]; // Store whether the boundary computes/applies fluid loads.
- Marker_All_PyCustom = new unsigned short[nMarker_All]; // Store whether the boundary is Python customizable.
- Marker_All_PerBound = new short[nMarker_All]; // Store whether the boundary belongs to a periodic boundary.
- Marker_All_Turbomachinery = new unsigned short[nMarker_All]; // Store whether the boundary is in needed for Turbomachinery computations.
- Marker_All_TurbomachineryFlag = new unsigned short[nMarker_All]; // Store whether the boundary has a flag for Turbomachinery computations.
- Marker_All_MixingPlaneInterface = new unsigned short[nMarker_All]; // Store whether the boundary has a in the MixingPlane interface.
-
+ Marker_All_SendRecv = new short[nMarker_All] (); // +#domain (send), -#domain (receive).
+ Marker_All_KindBC = new unsigned short[nMarker_All] (); // Store the kind of boundary condition.
+ Marker_All_Monitoring = new unsigned short[nMarker_All] (); // Store whether the boundary should be monitored.
+ Marker_All_Designing = new unsigned short[nMarker_All] (); // Store whether the boundary should be designed.
+ Marker_All_Plotting = new unsigned short[nMarker_All] (); // Store whether the boundary should be plotted.
+ Marker_All_Analyze = new unsigned short[nMarker_All] (); // Store whether the boundary should be plotted.
+ Marker_All_ZoneInterface = new unsigned short[nMarker_All] (); // Store whether the boundary is in the FSI interface.
+ Marker_All_GeoEval = new unsigned short[nMarker_All] (); // Store whether the boundary should be geometry evaluation.
+ Marker_All_DV = new unsigned short[nMarker_All] (); // Store whether the boundary should be affected by design variables.
+ Marker_All_Moving = new unsigned short[nMarker_All] (); // Store whether the boundary should be in motion.
+ Marker_All_Deform_Mesh = new unsigned short[nMarker_All] (); // Store whether the boundary is deformable.
+ Marker_All_Fluid_Load = new unsigned short[nMarker_All] (); // Store whether the boundary computes/applies fluid loads.
+ Marker_All_PyCustom = new unsigned short[nMarker_All] (); // Store whether the boundary is Python customizable.
+ Marker_All_PerBound = new short[nMarker_All] (); // Store whether the boundary belongs to a periodic boundary.
+ Marker_All_Turbomachinery = new unsigned short[nMarker_All] (); // Store whether the boundary is in needed for Turbomachinery computations.
+ Marker_All_TurbomachineryFlag = new unsigned short[nMarker_All] (); // Store whether the boundary has a flag for Turbomachinery computations.
+ Marker_All_MixingPlaneInterface = new unsigned short[nMarker_All] (); // Store whether the boundary has a in the MixingPlane interface.
for (iMarker_All = 0; iMarker_All < nMarker_All; iMarker_All++) {
- Marker_All_TagBound[iMarker_All] = "SEND_RECEIVE";
- Marker_All_SendRecv[iMarker_All] = 0;
- Marker_All_KindBC[iMarker_All] = 0;
- Marker_All_Monitoring[iMarker_All] = 0;
- Marker_All_GeoEval[iMarker_All] = 0;
- Marker_All_Designing[iMarker_All] = 0;
- Marker_All_Plotting[iMarker_All] = 0;
- Marker_All_Analyze[iMarker_All] = 0;
- Marker_All_ZoneInterface[iMarker_All] = 0;
- Marker_All_DV[iMarker_All] = 0;
- Marker_All_Moving[iMarker_All] = 0;
- Marker_All_Deform_Mesh[iMarker_All] = 0;
- Marker_All_Fluid_Load[iMarker_All] = 0;
- Marker_All_PerBound[iMarker_All] = 0;
- Marker_All_Turbomachinery[iMarker_All] = 0;
- Marker_All_TurbomachineryFlag[iMarker_All] = 0;
- Marker_All_MixingPlaneInterface[iMarker_All] = 0;
- Marker_All_PyCustom[iMarker_All] = 0;
+ Marker_All_TagBound[iMarker_All] = "SEND_RECEIVE";
}
/*--- Allocate the memory (markers in the config file) ---*/
Marker_CfgFile_TagBound = new string[nMarker_CfgFile];
- Marker_CfgFile_KindBC = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Monitoring = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Designing = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Plotting = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Analyze = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_GeoEval = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_ZoneInterface = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_DV = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Moving = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Deform_Mesh = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Fluid_Load = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_PerBound = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_Turbomachinery = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_TurbomachineryFlag = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_MixingPlaneInterface = new unsigned short[nMarker_CfgFile];
- Marker_CfgFile_PyCustom = new unsigned short[nMarker_CfgFile];
+ Marker_CfgFile_KindBC = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Monitoring = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Designing = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Plotting = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Analyze = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_GeoEval = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_ZoneInterface = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_DV = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Moving = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Deform_Mesh = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Fluid_Load = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_PerBound = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_Turbomachinery = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_TurbomachineryFlag = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_MixingPlaneInterface = new unsigned short[nMarker_CfgFile] ();
+ Marker_CfgFile_PyCustom = new unsigned short[nMarker_CfgFile] ();
for (iMarker_CfgFile = 0; iMarker_CfgFile < nMarker_CfgFile; iMarker_CfgFile++) {
- Marker_CfgFile_TagBound[iMarker_CfgFile] = "SEND_RECEIVE";
- Marker_CfgFile_KindBC[iMarker_CfgFile] = 0;
- Marker_CfgFile_Monitoring[iMarker_CfgFile] = 0;
- Marker_CfgFile_GeoEval[iMarker_CfgFile] = 0;
- Marker_CfgFile_Designing[iMarker_CfgFile] = 0;
- Marker_CfgFile_Plotting[iMarker_CfgFile] = 0;
- Marker_CfgFile_Analyze[iMarker_CfgFile] = 0;
- Marker_CfgFile_ZoneInterface[iMarker_CfgFile] = 0;
- Marker_CfgFile_DV[iMarker_CfgFile] = 0;
- Marker_CfgFile_Moving[iMarker_CfgFile] = 0;
- Marker_CfgFile_Deform_Mesh[iMarker_CfgFile] = 0;
- Marker_CfgFile_Fluid_Load[iMarker_CfgFile] = 0;
- Marker_CfgFile_PerBound[iMarker_CfgFile] = 0;
- Marker_CfgFile_Turbomachinery[iMarker_CfgFile] = 0;
- Marker_CfgFile_TurbomachineryFlag[iMarker_CfgFile] = 0;
- Marker_CfgFile_MixingPlaneInterface[iMarker_CfgFile] = 0;
- Marker_CfgFile_PyCustom[iMarker_CfgFile] = 0;
+ Marker_CfgFile_TagBound[iMarker_CfgFile] = "SEND_RECEIVE";
}
/*--- Allocate memory to store surface information (Analyze BC) ---*/
- Surface_MassFlow = new su2double[nMarker_Analyze];
- Surface_Mach = new su2double[nMarker_Analyze];
- Surface_Temperature = new su2double[nMarker_Analyze];
- Surface_Pressure = new su2double[nMarker_Analyze];
- Surface_Density = new su2double[nMarker_Analyze];
- Surface_Enthalpy = new su2double[nMarker_Analyze];
- Surface_NormalVelocity = new su2double[nMarker_Analyze];
- Surface_Uniformity = new su2double[nMarker_Analyze];
- Surface_SecondaryStrength = new su2double[nMarker_Analyze];
- Surface_SecondOverUniform = new su2double[nMarker_Analyze];
- Surface_MomentumDistortion = new su2double[nMarker_Analyze];
- Surface_TotalTemperature = new su2double[nMarker_Analyze];
- Surface_TotalPressure = new su2double[nMarker_Analyze];
- Surface_PressureDrop = new su2double[nMarker_Analyze];
- Surface_DC60 = new su2double[nMarker_Analyze];
- Surface_IDC = new su2double[nMarker_Analyze];
- Surface_IDC_Mach = new su2double[nMarker_Analyze];
- Surface_IDR = new su2double[nMarker_Analyze];
- for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
- Surface_MassFlow[iMarker_Analyze] = 0.0;
- Surface_Mach[iMarker_Analyze] = 0.0;
- Surface_Temperature[iMarker_Analyze] = 0.0;
- Surface_Pressure[iMarker_Analyze] = 0.0;
- Surface_Density[iMarker_Analyze] = 0.0;
- Surface_Enthalpy[iMarker_Analyze] = 0.0;
- Surface_NormalVelocity[iMarker_Analyze] = 0.0;
- Surface_Uniformity[iMarker_Analyze] = 0.0;
- Surface_SecondaryStrength[iMarker_Analyze] = 0.0;
- Surface_SecondOverUniform[iMarker_Analyze] = 0.0;
- Surface_MomentumDistortion[iMarker_Analyze] = 0.0;
- Surface_TotalTemperature[iMarker_Analyze] = 0.0;
- Surface_TotalPressure[iMarker_Analyze] = 0.0;
- Surface_PressureDrop[iMarker_Analyze] = 0.0;
- Surface_DC60[iMarker_Analyze] = 0.0;
- Surface_IDC[iMarker_Analyze] = 0.0;
- Surface_IDC_Mach[iMarker_Analyze] = 0.0;
- Surface_IDR[iMarker_Analyze] = 0.0;
- }
+ Surface_MassFlow = new su2double[nMarker_Analyze] ();
+ Surface_Mach = new su2double[nMarker_Analyze] ();
+ Surface_Temperature = new su2double[nMarker_Analyze] ();
+ Surface_Pressure = new su2double[nMarker_Analyze] ();
+ Surface_Density = new su2double[nMarker_Analyze] ();
+ Surface_Enthalpy = new su2double[nMarker_Analyze] ();
+ Surface_NormalVelocity = new su2double[nMarker_Analyze] ();
+ Surface_Uniformity = new su2double[nMarker_Analyze] ();
+ Surface_SecondaryStrength = new su2double[nMarker_Analyze] ();
+ Surface_SecondOverUniform = new su2double[nMarker_Analyze] ();
+ Surface_MomentumDistortion = new su2double[nMarker_Analyze] ();
+ Surface_TotalTemperature = new su2double[nMarker_Analyze] ();
+ Surface_TotalPressure = new su2double[nMarker_Analyze] ();
+ Surface_PressureDrop = new su2double[nMarker_Analyze] ();
+ Surface_DC60 = new su2double[nMarker_Analyze] ();
+ Surface_IDC = new su2double[nMarker_Analyze] ();
+ Surface_IDC_Mach = new su2double[nMarker_Analyze] ();
+ Surface_IDR = new su2double[nMarker_Analyze] ();
/*--- Populate the marker information in the config file (all domains) ---*/
@@ -5119,97 +5044,56 @@ void CConfig::SetMarkers(unsigned short val_software) {
iMarker_CfgFile++;
}
- ActDisk_DeltaPress = new su2double[nMarker_ActDiskInlet];
- ActDisk_DeltaTemp = new su2double[nMarker_ActDiskInlet];
- ActDisk_TotalPressRatio = new su2double[nMarker_ActDiskInlet];
- ActDisk_TotalTempRatio = new su2double[nMarker_ActDiskInlet];
- ActDisk_StaticPressRatio = new su2double[nMarker_ActDiskInlet];
- ActDisk_StaticTempRatio = new su2double[nMarker_ActDiskInlet];
- ActDisk_Power = new su2double[nMarker_ActDiskInlet];
- ActDisk_MassFlow = new su2double[nMarker_ActDiskInlet];
- ActDisk_Mach = new su2double[nMarker_ActDiskInlet];
- ActDisk_Force = new su2double[nMarker_ActDiskInlet];
- ActDisk_NetThrust = new su2double[nMarker_ActDiskInlet];
- ActDisk_BCThrust = new su2double[nMarker_ActDiskInlet];
- ActDisk_BCThrust_Old = new su2double[nMarker_ActDiskInlet];
- ActDisk_GrossThrust = new su2double[nMarker_ActDiskInlet];
- ActDisk_Area = new su2double[nMarker_ActDiskInlet];
- ActDisk_ReverseMassFlow = new su2double[nMarker_ActDiskInlet];
-
- for (iMarker_ActDiskInlet = 0; iMarker_ActDiskInlet < nMarker_ActDiskInlet; iMarker_ActDiskInlet++) {
- ActDisk_DeltaPress[iMarker_ActDiskInlet] = 0.0;
- ActDisk_DeltaTemp[iMarker_ActDiskInlet] = 0.0;
- ActDisk_TotalPressRatio[iMarker_ActDiskInlet] = 0.0;
- ActDisk_TotalTempRatio[iMarker_ActDiskInlet] = 0.0;
- ActDisk_StaticPressRatio[iMarker_ActDiskInlet] = 0.0;
- ActDisk_StaticTempRatio[iMarker_ActDiskInlet] = 0.0;
- ActDisk_Power[iMarker_ActDiskInlet] = 0.0;
- ActDisk_MassFlow[iMarker_ActDiskInlet] = 0.0;
- ActDisk_Mach[iMarker_ActDiskInlet] = 0.0;
- ActDisk_Force[iMarker_ActDiskInlet] = 0.0;
- ActDisk_NetThrust[iMarker_ActDiskInlet] = 0.0;
- ActDisk_BCThrust[iMarker_ActDiskInlet] = 0.0;
- ActDisk_BCThrust_Old[iMarker_ActDiskInlet] = 0.0;
- ActDisk_GrossThrust[iMarker_ActDiskInlet] = 0.0;
- ActDisk_Area[iMarker_ActDiskInlet] = 0.0;
- ActDisk_ReverseMassFlow[iMarker_ActDiskInlet] = 0.0;
- }
-
-
- ActDiskInlet_MassFlow = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_Temperature = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_TotalTemperature = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_Pressure = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_TotalPressure = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_RamDrag = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_Force = new su2double[nMarker_ActDiskInlet];
- ActDiskInlet_Power = new su2double[nMarker_ActDiskInlet];
+ ActDisk_DeltaPress = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_DeltaTemp = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_TotalPressRatio = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_TotalTempRatio = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_StaticPressRatio = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_StaticTempRatio = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_Power = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_MassFlow = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_Mach = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_Force = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_NetThrust = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_BCThrust = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_BCThrust_Old = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_GrossThrust = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_Area = new su2double[nMarker_ActDiskInlet] ();
+ ActDisk_ReverseMassFlow = new su2double[nMarker_ActDiskInlet] ();
+
+ ActDiskInlet_MassFlow = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_Temperature = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_TotalTemperature = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_Pressure = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_TotalPressure = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_RamDrag = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_Force = new su2double[nMarker_ActDiskInlet] ();
+ ActDiskInlet_Power = new su2double[nMarker_ActDiskInlet] ();
for (iMarker_ActDiskInlet = 0; iMarker_ActDiskInlet < nMarker_ActDiskInlet; iMarker_ActDiskInlet++) {
Marker_CfgFile_TagBound[iMarker_CfgFile] = Marker_ActDiskInlet[iMarker_ActDiskInlet];
Marker_CfgFile_KindBC[iMarker_CfgFile] = ACTDISK_INLET;
- ActDiskInlet_MassFlow[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_Temperature[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_TotalTemperature[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_Pressure[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_TotalPressure[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_RamDrag[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_Force[iMarker_ActDiskInlet] = 0.0;
- ActDiskInlet_Power[iMarker_ActDiskInlet] = 0.0;
iMarker_CfgFile++;
}
- ActDiskOutlet_MassFlow = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_Temperature = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_TotalTemperature = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_Pressure = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_TotalPressure = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_GrossThrust = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_Force = new su2double[nMarker_ActDiskOutlet];
- ActDiskOutlet_Power = new su2double[nMarker_ActDiskOutlet];
+ ActDiskOutlet_MassFlow = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_Temperature = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_TotalTemperature = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_Pressure = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_TotalPressure = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_GrossThrust = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_Force = new su2double[nMarker_ActDiskOutlet] ();
+ ActDiskOutlet_Power = new su2double[nMarker_ActDiskOutlet] ();
for (iMarker_ActDiskOutlet = 0; iMarker_ActDiskOutlet < nMarker_ActDiskOutlet; iMarker_ActDiskOutlet++) {
Marker_CfgFile_TagBound[iMarker_CfgFile] = Marker_ActDiskOutlet[iMarker_ActDiskOutlet];
Marker_CfgFile_KindBC[iMarker_CfgFile] = ACTDISK_OUTLET;
- ActDiskOutlet_MassFlow[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_Temperature[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_TotalTemperature[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_Pressure[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_TotalPressure[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_GrossThrust[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_Force[iMarker_ActDiskOutlet] = 0.0;
- ActDiskOutlet_Power[iMarker_ActDiskOutlet] = 0.0;
iMarker_CfgFile++;
}
- Outlet_MassFlow = new su2double[nMarker_Outlet];
- Outlet_Density = new su2double[nMarker_Outlet];
- Outlet_Area = new su2double[nMarker_Outlet];
- for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++) {
- Outlet_MassFlow[iMarker_Outlet] = 0.0;
- Outlet_Density[iMarker_Outlet] = 0.0;
- Outlet_Area[iMarker_Outlet] = 0.0;
- }
+ Outlet_MassFlow = new su2double[nMarker_Outlet] ();
+ Outlet_Density = new su2double[nMarker_Outlet] ();
+ Outlet_Area = new su2double[nMarker_Outlet] ();
for (iMarker_NearFieldBound = 0; iMarker_NearFieldBound < nMarker_NearFieldBound; iMarker_NearFieldBound++) {
Marker_CfgFile_TagBound[iMarker_CfgFile] = Marker_NearFieldBound[iMarker_NearFieldBound];
@@ -5247,69 +5131,42 @@ void CConfig::SetMarkers(unsigned short val_software) {
iMarker_CfgFile++;
}
- Engine_Power = new su2double[nMarker_EngineInflow];
- Engine_Mach = new su2double[nMarker_EngineInflow];
- Engine_Force = new su2double[nMarker_EngineInflow];
- Engine_NetThrust = new su2double[nMarker_EngineInflow];
- Engine_GrossThrust = new su2double[nMarker_EngineInflow];
- Engine_Area = new su2double[nMarker_EngineInflow];
-
- for (iMarker_EngineInflow = 0; iMarker_EngineInflow < nMarker_EngineInflow; iMarker_EngineInflow++) {
- Engine_Power[iMarker_EngineInflow] = 0.0;
- Engine_Mach[iMarker_EngineInflow] = 0.0;
- Engine_Force[iMarker_EngineInflow] = 0.0;
- Engine_NetThrust[iMarker_EngineInflow] = 0.0;
- Engine_GrossThrust[iMarker_EngineInflow] = 0.0;
- Engine_Area[iMarker_EngineInflow] = 0.0;
- }
-
- Inflow_Mach = new su2double[nMarker_EngineInflow];
- Inflow_Pressure = new su2double[nMarker_EngineInflow];
- Inflow_MassFlow = new su2double[nMarker_EngineInflow];
- Inflow_ReverseMassFlow = new su2double[nMarker_EngineInflow];
- Inflow_TotalPressure = new su2double[nMarker_EngineInflow];
- Inflow_Temperature = new su2double[nMarker_EngineInflow];
- Inflow_TotalTemperature = new su2double[nMarker_EngineInflow];
- Inflow_RamDrag = new su2double[nMarker_EngineInflow];
- Inflow_Force = new su2double[nMarker_EngineInflow];
- Inflow_Power = new su2double[nMarker_EngineInflow];
+ Engine_Power = new su2double[nMarker_EngineInflow] ();
+ Engine_Mach = new su2double[nMarker_EngineInflow] ();
+ Engine_Force = new su2double[nMarker_EngineInflow] ();
+ Engine_NetThrust = new su2double[nMarker_EngineInflow] ();
+ Engine_GrossThrust = new su2double[nMarker_EngineInflow] ();
+ Engine_Area = new su2double[nMarker_EngineInflow] ();
+
+ Inflow_Mach = new su2double[nMarker_EngineInflow] ();
+ Inflow_Pressure = new su2double[nMarker_EngineInflow] ();
+ Inflow_MassFlow = new su2double[nMarker_EngineInflow] ();
+ Inflow_ReverseMassFlow = new su2double[nMarker_EngineInflow] ();
+ Inflow_TotalPressure = new su2double[nMarker_EngineInflow] ();
+ Inflow_Temperature = new su2double[nMarker_EngineInflow] ();
+ Inflow_TotalTemperature = new su2double[nMarker_EngineInflow] ();
+ Inflow_RamDrag = new su2double[nMarker_EngineInflow] ();
+ Inflow_Force = new su2double[nMarker_EngineInflow] ();
+ Inflow_Power = new su2double[nMarker_EngineInflow] ();
for (iMarker_EngineInflow = 0; iMarker_EngineInflow < nMarker_EngineInflow; iMarker_EngineInflow++) {
Marker_CfgFile_TagBound[iMarker_CfgFile] = Marker_EngineInflow[iMarker_EngineInflow];
Marker_CfgFile_KindBC[iMarker_CfgFile] = ENGINE_INFLOW;
- Inflow_Mach[iMarker_EngineInflow] = 0.0;
- Inflow_Pressure[iMarker_EngineInflow] = 0.0;
- Inflow_MassFlow[iMarker_EngineInflow] = 0.0;
- Inflow_ReverseMassFlow[iMarker_EngineInflow] = 0.0;
- Inflow_TotalPressure[iMarker_EngineInflow] = 0.0;
- Inflow_Temperature[iMarker_EngineInflow] = 0.0;
- Inflow_TotalTemperature[iMarker_EngineInflow] = 0.0;
- Inflow_RamDrag[iMarker_EngineInflow] = 0.0;
- Inflow_Force[iMarker_EngineInflow] = 0.0;
- Inflow_Power[iMarker_EngineInflow] = 0.0;
iMarker_CfgFile++;
}
- Exhaust_Pressure = new su2double[nMarker_EngineExhaust];
- Exhaust_Temperature = new su2double[nMarker_EngineExhaust];
- Exhaust_MassFlow = new su2double[nMarker_EngineExhaust];
- Exhaust_TotalPressure = new su2double[nMarker_EngineExhaust];
- Exhaust_TotalTemperature = new su2double[nMarker_EngineExhaust];
- Exhaust_GrossThrust = new su2double[nMarker_EngineExhaust];
- Exhaust_Force = new su2double[nMarker_EngineExhaust];
- Exhaust_Power = new su2double[nMarker_EngineExhaust];
+ Exhaust_Pressure = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_Temperature = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_MassFlow = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_TotalPressure = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_TotalTemperature = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_GrossThrust = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_Force = new su2double[nMarker_EngineExhaust] ();
+ Exhaust_Power = new su2double[nMarker_EngineExhaust] ();
for (iMarker_EngineExhaust = 0; iMarker_EngineExhaust < nMarker_EngineExhaust; iMarker_EngineExhaust++) {
Marker_CfgFile_TagBound[iMarker_CfgFile] = Marker_EngineExhaust[iMarker_EngineExhaust];
Marker_CfgFile_KindBC[iMarker_CfgFile] = ENGINE_EXHAUST;
- Exhaust_Pressure[iMarker_EngineExhaust] = 0.0;
- Exhaust_Temperature[iMarker_EngineExhaust] = 0.0;
- Exhaust_MassFlow[iMarker_EngineExhaust] = 0.0;
- Exhaust_TotalPressure[iMarker_EngineExhaust] = 0.0;
- Exhaust_TotalTemperature[iMarker_EngineExhaust] = 0.0;
- Exhaust_GrossThrust[iMarker_EngineExhaust] = 0.0;
- Exhaust_Force[iMarker_EngineExhaust] = 0.0;
- Exhaust_Power[iMarker_EngineExhaust] = 0.0;
iMarker_CfgFile++;
}
@@ -5557,14 +5414,13 @@ void CConfig::SetOutput(unsigned short val_software, unsigned short val_izone) {
cout << endl <<"----------------- Physical Case Definition ( Zone " << iZone << " ) -------------------" << endl;
if (val_software == SU2_CFD) {
- if (FSI_Problem) {
+ if (FSI_Problem)
cout << "Fluid-Structure Interaction." << endl;
- }
- if (DiscreteAdjoint) {
- cout <<"Discrete Adjoint equations using Algorithmic Differentiation " << endl;
+ if (DiscreteAdjoint) {
+ cout <<"Discrete Adjoint equations using Algorithmic Differentiation\n";
cout <<"based on the physical case: ";
- }
+ }
switch (Kind_Solver) {
case EULER: case DISC_ADJ_EULER:
case INC_EULER: case DISC_ADJ_INC_EULER:
@@ -8228,7 +8084,7 @@ su2double* CConfig::GetPeriodicTranslation(string val_marker) {
return Periodic_Translation[iMarker_PerBound];
}
-unsigned short CConfig::GetMarker_Periodic_Donor(string val_marker) {
+unsigned short CConfig::GetMarker_Periodic_Donor(string val_marker) const {
unsigned short iMarker_PerBound, jMarker_PerBound, kMarker_All;
/*--- Find the marker for this periodic boundary. ---*/
@@ -8246,7 +8102,7 @@ unsigned short CConfig::GetMarker_Periodic_Donor(string val_marker) {
return kMarker_All;
}
-su2double CConfig::GetActDisk_NetThrust(string val_marker) {
+su2double CConfig::GetActDisk_NetThrust(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8254,7 +8110,7 @@ su2double CConfig::GetActDisk_NetThrust(string val_marker) {
return ActDisk_NetThrust[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_Power(string val_marker) {
+su2double CConfig::GetActDisk_Power(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8262,7 +8118,7 @@ su2double CConfig::GetActDisk_Power(string val_marker) {
return ActDisk_Power[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_MassFlow(string val_marker) {
+su2double CConfig::GetActDisk_MassFlow(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8270,7 +8126,7 @@ su2double CConfig::GetActDisk_MassFlow(string val_marker) {
return ActDisk_MassFlow[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_Mach(string val_marker) {
+su2double CConfig::GetActDisk_Mach(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8278,7 +8134,7 @@ su2double CConfig::GetActDisk_Mach(string val_marker) {
return ActDisk_Mach[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_Force(string val_marker) {
+su2double CConfig::GetActDisk_Force(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8286,7 +8142,7 @@ su2double CConfig::GetActDisk_Force(string val_marker) {
return ActDisk_Force[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_BCThrust(string val_marker) {
+su2double CConfig::GetActDisk_BCThrust(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8294,7 +8150,7 @@ su2double CConfig::GetActDisk_BCThrust(string val_marker) {
return ActDisk_BCThrust[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_BCThrust_Old(string val_marker) {
+su2double CConfig::GetActDisk_BCThrust_Old(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8318,7 +8174,7 @@ void CConfig::SetActDisk_BCThrust_Old(string val_marker, su2double val_actdisk_b
ActDisk_BCThrust_Old[iMarker_ActDisk] = val_actdisk_bcthrust_old;
}
-su2double CConfig::GetActDisk_Area(string val_marker) {
+su2double CConfig::GetActDisk_Area(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8326,7 +8182,7 @@ su2double CConfig::GetActDisk_Area(string val_marker) {
return ActDisk_Area[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_ReverseMassFlow(string val_marker) {
+su2double CConfig::GetActDisk_ReverseMassFlow(string val_marker) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8334,7 +8190,7 @@ su2double CConfig::GetActDisk_ReverseMassFlow(string val_marker) {
return ActDisk_ReverseMassFlow[iMarker_ActDisk];
}
-su2double CConfig::GetActDisk_PressJump(string val_marker, unsigned short val_value) {
+su2double CConfig::GetActDisk_PressJump(string val_marker, unsigned short val_value) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8342,7 +8198,7 @@ su2double CConfig::GetActDisk_PressJump(string val_marker, unsigned short val_va
return ActDisk_PressJump[iMarker_ActDisk][val_value];
}
-su2double CConfig::GetActDisk_TempJump(string val_marker, unsigned short val_value) {
+su2double CConfig::GetActDisk_TempJump(string val_marker, unsigned short val_value) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8350,7 +8206,7 @@ su2double CConfig::GetActDisk_TempJump(string val_marker, unsigned short val_val
return ActDisk_TempJump[iMarker_ActDisk][val_value];;
}
-su2double CConfig::GetActDisk_Omega(string val_marker, unsigned short val_value) {
+su2double CConfig::GetActDisk_Omega(string val_marker, unsigned short val_value) const {
unsigned short iMarker_ActDisk;
for (iMarker_ActDisk = 0; iMarker_ActDisk < nMarker_ActDiskInlet; iMarker_ActDisk++)
if ((Marker_ActDiskInlet[iMarker_ActDisk] == val_marker) ||
@@ -8358,28 +8214,28 @@ su2double CConfig::GetActDisk_Omega(string val_marker, unsigned short val_value)
return ActDisk_Omega[iMarker_ActDisk][val_value];;
}
-su2double CConfig::GetOutlet_MassFlow(string val_marker) {
+su2double CConfig::GetOutlet_MassFlow(string val_marker) const {
unsigned short iMarker_Outlet;
for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++)
if ((Marker_Outlet[iMarker_Outlet] == val_marker)) break;
return Outlet_MassFlow[iMarker_Outlet];
}
-su2double CConfig::GetOutlet_Density(string val_marker) {
+su2double CConfig::GetOutlet_Density(string val_marker) const {
unsigned short iMarker_Outlet;
for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++)
if ((Marker_Outlet[iMarker_Outlet] == val_marker)) break;
return Outlet_Density[iMarker_Outlet];
}
-su2double CConfig::GetOutlet_Area(string val_marker) {
+su2double CConfig::GetOutlet_Area(string val_marker) const {
unsigned short iMarker_Outlet;
for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++)
if ((Marker_Outlet[iMarker_Outlet] == val_marker)) break;
return Outlet_Area[iMarker_Outlet];
}
-unsigned short CConfig::GetMarker_CfgFile_ActDiskOutlet(string val_marker) {
+unsigned short CConfig::GetMarker_CfgFile_ActDiskOutlet(string val_marker) const {
unsigned short iMarker_ActDisk, kMarker_All;
/*--- Find the marker for this actuator disk inlet. ---*/
@@ -8395,7 +8251,7 @@ unsigned short CConfig::GetMarker_CfgFile_ActDiskOutlet(string val_marker) {
return kMarker_All;
}
-unsigned short CConfig::GetMarker_CfgFile_EngineExhaust(string val_marker) {
+unsigned short CConfig::GetMarker_CfgFile_EngineExhaust(string val_marker) const {
unsigned short iMarker_Engine, kMarker_All;
/*--- Find the marker for this engine inflow. ---*/
@@ -8411,14 +8267,12 @@ unsigned short CConfig::GetMarker_CfgFile_EngineExhaust(string val_marker) {
return kMarker_All;
}
-bool CConfig::GetVolumetric_Movement(){
+bool CConfig::GetVolumetric_Movement() const {
bool volumetric_movement = false;
if (GetSurface_Movement(AEROELASTIC) ||
- GetSurface_Movement(DEFORMING) ||
GetSurface_Movement(AEROELASTIC_RIGID_MOTION)||
GetSurface_Movement(FLUID_STRUCTURE) ||
- GetSurface_Movement(FLUID_STRUCTURE_STATIC) ||
GetSurface_Movement(EXTERNAL) ||
GetSurface_Movement(EXTERNAL_ROTATION)){
volumetric_movement = true;
@@ -8440,7 +8294,7 @@ bool CConfig::GetSurface_Movement(unsigned short kind_movement) const {
return false;
}
-unsigned short CConfig::GetMarker_Moving(string val_marker) {
+unsigned short CConfig::GetMarker_Moving(string val_marker) const {
unsigned short iMarker_Moving;
/*--- Find the marker for this moving boundary. ---*/
@@ -8450,7 +8304,7 @@ unsigned short CConfig::GetMarker_Moving(string val_marker) {
return iMarker_Moving;
}
-bool CConfig::GetMarker_Moving_Bool(string val_marker) {
+bool CConfig::GetMarker_Moving_Bool(string val_marker) const {
unsigned short iMarker_Moving;
/*--- Find the marker for this moving boundary, if it exists. ---*/
@@ -8460,7 +8314,7 @@ bool CConfig::GetMarker_Moving_Bool(string val_marker) {
return false;
}
-unsigned short CConfig::GetMarker_Deform_Mesh(string val_marker) {
+unsigned short CConfig::GetMarker_Deform_Mesh(string val_marker) const {
unsigned short iMarker_Deform_Mesh;
/*--- Find the marker for this interface boundary. ---*/
@@ -8470,7 +8324,7 @@ unsigned short CConfig::GetMarker_Deform_Mesh(string val_marker) {
return iMarker_Deform_Mesh;
}
-unsigned short CConfig::GetMarker_Fluid_Load(string val_marker) {
+unsigned short CConfig::GetMarker_Fluid_Load(string val_marker) const {
unsigned short iMarker_Fluid_Load;
/*--- Find the marker for this interface boundary. ---*/
@@ -8480,42 +8334,42 @@ unsigned short CConfig::GetMarker_Fluid_Load(string val_marker) {
return iMarker_Fluid_Load;
}
-su2double CConfig::GetExhaust_Temperature_Target(string val_marker) {
+su2double CConfig::GetExhaust_Temperature_Target(string val_marker) const {
unsigned short iMarker_EngineExhaust;
for (iMarker_EngineExhaust = 0; iMarker_EngineExhaust < nMarker_EngineExhaust; iMarker_EngineExhaust++)
if (Marker_EngineExhaust[iMarker_EngineExhaust] == val_marker) break;
return Exhaust_Temperature_Target[iMarker_EngineExhaust];
}
-su2double CConfig::GetExhaust_Pressure_Target(string val_marker) {
+su2double CConfig::GetExhaust_Pressure_Target(string val_marker) const {
unsigned short iMarker_EngineExhaust;
for (iMarker_EngineExhaust = 0; iMarker_EngineExhaust < nMarker_EngineExhaust; iMarker_EngineExhaust++)
if (Marker_EngineExhaust[iMarker_EngineExhaust] == val_marker) break;
return Exhaust_Pressure_Target[iMarker_EngineExhaust];
}
-unsigned short CConfig::GetKind_Inc_Inlet(string val_marker) {
+unsigned short CConfig::GetKind_Inc_Inlet(string val_marker) const {
unsigned short iMarker_Inlet;
for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++)
if (Marker_Inlet[iMarker_Inlet] == val_marker) break;
return Kind_Inc_Inlet[iMarker_Inlet];
}
-unsigned short CConfig::GetKind_Inc_Outlet(string val_marker) {
+unsigned short CConfig::GetKind_Inc_Outlet(string val_marker) const {
unsigned short iMarker_Outlet;
for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++)
if (Marker_Outlet[iMarker_Outlet] == val_marker) break;
return Kind_Inc_Outlet[iMarker_Outlet];
}
-su2double CConfig::GetInlet_Ttotal(string val_marker) {
+su2double CConfig::GetInlet_Ttotal(string val_marker) const {
unsigned short iMarker_Inlet;
for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++)
if (Marker_Inlet[iMarker_Inlet] == val_marker) break;
return Inlet_Ttotal[iMarker_Inlet];
}
-su2double CConfig::GetInlet_Ptotal(string val_marker) {
+su2double CConfig::GetInlet_Ptotal(string val_marker) const {
unsigned short iMarker_Inlet;
for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++)
if (Marker_Inlet[iMarker_Inlet] == val_marker) break;
@@ -8536,14 +8390,14 @@ su2double* CConfig::GetInlet_FlowDir(string val_marker) {
return Inlet_FlowDir[iMarker_Inlet];
}
-su2double CConfig::GetInlet_Temperature(string val_marker) {
+su2double CConfig::GetInlet_Temperature(string val_marker) const {
unsigned short iMarker_Supersonic_Inlet;
for (iMarker_Supersonic_Inlet = 0; iMarker_Supersonic_Inlet < nMarker_Supersonic_Inlet; iMarker_Supersonic_Inlet++)
if (Marker_Supersonic_Inlet[iMarker_Supersonic_Inlet] == val_marker) break;
return Inlet_Temperature[iMarker_Supersonic_Inlet];
}
-su2double CConfig::GetInlet_Pressure(string val_marker) {
+su2double CConfig::GetInlet_Pressure(string val_marker) const {
unsigned short iMarker_Supersonic_Inlet;
for (iMarker_Supersonic_Inlet = 0; iMarker_Supersonic_Inlet < nMarker_Supersonic_Inlet; iMarker_Supersonic_Inlet++)
if (Marker_Supersonic_Inlet[iMarker_Supersonic_Inlet] == val_marker) break;
@@ -8557,7 +8411,7 @@ su2double* CConfig::GetInlet_Velocity(string val_marker) {
return Inlet_Velocity[iMarker_Supersonic_Inlet];
}
-su2double CConfig::GetOutlet_Pressure(string val_marker) {
+su2double CConfig::GetOutlet_Pressure(string val_marker) const {
unsigned short iMarker_Outlet;
for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++)
if (Marker_Outlet[iMarker_Outlet] == val_marker) break;
@@ -8571,14 +8425,14 @@ void CConfig::SetOutlet_Pressure(su2double val_pressure, string val_marker) {
Outlet_Pressure[iMarker_Outlet] = val_pressure;
}
-su2double CConfig::GetRiemann_Var1(string val_marker) {
+su2double CConfig::GetRiemann_Var1(string val_marker) const {
unsigned short iMarker_Riemann;
for (iMarker_Riemann = 0; iMarker_Riemann < nMarker_Riemann; iMarker_Riemann++)
if (Marker_Riemann[iMarker_Riemann] == val_marker) break;
return Riemann_Var1[iMarker_Riemann];
}
-su2double CConfig::GetRiemann_Var2(string val_marker) {
+su2double CConfig::GetRiemann_Var2(string val_marker) const {
unsigned short iMarker_Riemann;
for (iMarker_Riemann = 0; iMarker_Riemann < nMarker_Riemann; iMarker_Riemann++)
if (Marker_Riemann[iMarker_Riemann] == val_marker) break;
@@ -8592,7 +8446,7 @@ su2double* CConfig::GetRiemann_FlowDir(string val_marker) {
return Riemann_FlowDir[iMarker_Riemann];
}
-unsigned short CConfig::GetKind_Data_Riemann(string val_marker) {
+unsigned short CConfig::GetKind_Data_Riemann(string val_marker) const {
unsigned short iMarker_Riemann;
for (iMarker_Riemann = 0; iMarker_Riemann < nMarker_Riemann; iMarker_Riemann++)
if (Marker_Riemann[iMarker_Riemann] == val_marker) break;
@@ -8600,7 +8454,7 @@ unsigned short CConfig::GetKind_Data_Riemann(string val_marker) {
}
-su2double CConfig::GetGiles_Var1(string val_marker) {
+su2double CConfig::GetGiles_Var1(string val_marker) const {
unsigned short iMarker_Giles;
for (iMarker_Giles = 0; iMarker_Giles < nMarker_Giles; iMarker_Giles++)
if (Marker_Giles[iMarker_Giles] == val_marker) break;
@@ -8614,21 +8468,21 @@ void CConfig::SetGiles_Var1(su2double newVar1, string val_marker) {
Giles_Var1[iMarker_Giles] = newVar1;
}
-su2double CConfig::GetGiles_Var2(string val_marker) {
+su2double CConfig::GetGiles_Var2(string val_marker) const {
unsigned short iMarker_Giles;
for (iMarker_Giles = 0; iMarker_Giles < nMarker_Giles; iMarker_Giles++)
if (Marker_Giles[iMarker_Giles] == val_marker) break;
return Giles_Var2[iMarker_Giles];
}
-su2double CConfig::GetGiles_RelaxFactorAverage(string val_marker) {
+su2double CConfig::GetGiles_RelaxFactorAverage(string val_marker) const {
unsigned short iMarker_Giles;
for (iMarker_Giles = 0; iMarker_Giles < nMarker_Giles; iMarker_Giles++)
if (Marker_Giles[iMarker_Giles] == val_marker) break;
return RelaxFactorAverage[iMarker_Giles];
}
-su2double CConfig::GetGiles_RelaxFactorFourier(string val_marker) {
+su2double CConfig::GetGiles_RelaxFactorFourier(string val_marker) const {
unsigned short iMarker_Giles;
for (iMarker_Giles = 0; iMarker_Giles < nMarker_Giles; iMarker_Giles++)
if (Marker_Giles[iMarker_Giles] == val_marker) break;
@@ -8642,15 +8496,14 @@ su2double* CConfig::GetGiles_FlowDir(string val_marker) {
return Giles_FlowDir[iMarker_Giles];
}
-unsigned short CConfig::GetKind_Data_Giles(string val_marker) {
+unsigned short CConfig::GetKind_Data_Giles(string val_marker) const {
unsigned short iMarker_Giles;
for (iMarker_Giles = 0; iMarker_Giles < nMarker_Giles; iMarker_Giles++)
if (Marker_Giles[iMarker_Giles] == val_marker) break;
return Kind_Data_Giles[iMarker_Giles];
}
-
-su2double CConfig::GetPressureOut_BC() {
+su2double CConfig::GetPressureOut_BC() const {
unsigned short iMarker_BC;
su2double pres_out = 0.0;
for (iMarker_BC = 0; iMarker_BC < nMarker_Giles; iMarker_BC++){
@@ -8666,7 +8519,6 @@ su2double CConfig::GetPressureOut_BC() {
return pres_out/Pressure_Ref;
}
-
void CConfig::SetPressureOut_BC(su2double val_press) {
unsigned short iMarker_BC;
for (iMarker_BC = 0; iMarker_BC < nMarker_Giles; iMarker_BC++){
@@ -8681,7 +8533,7 @@ void CConfig::SetPressureOut_BC(su2double val_press) {
}
}
-su2double CConfig::GetTotalPressureIn_BC() {
+su2double CConfig::GetTotalPressureIn_BC() const {
unsigned short iMarker_BC;
su2double tot_pres_in = 0.0;
for (iMarker_BC = 0; iMarker_BC < nMarker_Giles; iMarker_BC++){
@@ -8700,7 +8552,7 @@ su2double CConfig::GetTotalPressureIn_BC() {
return tot_pres_in/Pressure_Ref;
}
-su2double CConfig::GetTotalTemperatureIn_BC() {
+su2double CConfig::GetTotalTemperatureIn_BC() const {
unsigned short iMarker_BC;
su2double tot_temp_in = 0.0;
for (iMarker_BC = 0; iMarker_BC < nMarker_Giles; iMarker_BC++){
@@ -8738,7 +8590,7 @@ void CConfig::SetTotalTemperatureIn_BC(su2double val_temp) {
}
}
-su2double CConfig::GetFlowAngleIn_BC() {
+su2double CConfig::GetFlowAngleIn_BC() const {
unsigned short iMarker_BC;
su2double alpha_in = 0.0;
for (iMarker_BC = 0; iMarker_BC < nMarker_Giles; iMarker_BC++){
@@ -8759,7 +8611,7 @@ su2double CConfig::GetFlowAngleIn_BC() {
return alpha_in;
}
-su2double CConfig::GetIncInlet_BC() {
+su2double CConfig::GetIncInlet_BC() const {
su2double val_out = 0.0;
@@ -8781,29 +8633,24 @@ void CConfig::SetIncInlet_BC(su2double val_in) {
else if (Kind_Inc_Inlet[0] == PRESSURE_INLET)
Inlet_Ptotal[0] = val_in*Pressure_Ref;
}
-
}
-su2double CConfig::GetIncTemperature_BC() {
+su2double CConfig::GetIncTemperature_BC() const {
su2double val_out = 0.0;
- if (nMarker_Inlet > 0) {
- val_out = Inlet_Ttotal[0]/Temperature_Ref;
- }
+ if (nMarker_Inlet > 0)
+ val_out = Inlet_Ttotal[0]/Temperature_Ref;
return val_out;
}
void CConfig::SetIncTemperature_BC(su2double val_temperature) {
-
- if (nMarker_Inlet > 0) {
- Inlet_Ttotal[0] = val_temperature*Temperature_Ref;
- }
-
+ if (nMarker_Inlet > 0)
+ Inlet_Ttotal[0] = val_temperature*Temperature_Ref;
}
-su2double CConfig::GetIncPressureOut_BC() {
+su2double CConfig::GetIncPressureOut_BC() const {
su2double pressure_out = 0.0;
@@ -8826,7 +8673,7 @@ void CConfig::SetIncPressureOut_BC(su2double val_pressure) {
}
-su2double CConfig::GetIsothermal_Temperature(string val_marker) {
+su2double CConfig::GetIsothermal_Temperature(string val_marker) const {
unsigned short iMarker_Isothermal = 0;
@@ -8838,7 +8685,7 @@ su2double CConfig::GetIsothermal_Temperature(string val_marker) {
return Isothermal_Temperature[iMarker_Isothermal];
}
-su2double CConfig::GetWall_HeatFlux(string val_marker) {
+su2double CConfig::GetWall_HeatFlux(string val_marker) const {
unsigned short iMarker_HeatFlux = 0;
if (nMarker_HeatFlux > 0) {
@@ -8849,7 +8696,7 @@ su2double CConfig::GetWall_HeatFlux(string val_marker) {
return Heat_Flux[iMarker_HeatFlux];
}
-unsigned short CConfig::GetWallFunction_Treatment(string val_marker) {
+unsigned short CConfig::GetWallFunction_Treatment(string val_marker) const {
unsigned short WallFunction = NO_WALL_FUNCTION;
for(unsigned short iMarker=0; iMarkerGetnMarker_TurboPerformance();
- TangGridVelIn = new su2double*[config->GetnMarker_TurboPerformance()];
- SpanAreaIn = new su2double*[config->GetnMarker_TurboPerformance()];
- TurboRadiusIn = new su2double*[config->GetnMarker_TurboPerformance()];
- TangGridVelOut = new su2double*[config->GetnMarker_TurboPerformance()];
- SpanAreaOut = new su2double*[config->GetnMarker_TurboPerformance()];
- TurboRadiusOut = new su2double*[config->GetnMarker_TurboPerformance()];
-
- for (unsigned short iMarker = 0; iMarker < config->GetnMarker_TurboPerformance(); iMarker++){
- TangGridVelIn[iMarker] = NULL;
- SpanAreaIn[iMarker] = NULL;
- TurboRadiusIn[iMarker] = NULL;
- TangGridVelOut[iMarker] = NULL;
- SpanAreaOut[iMarker] = NULL;
- TurboRadiusOut[iMarker] = NULL;
- }
+ TangGridVelIn = new su2double*[nTurboPerf] ();
+ SpanAreaIn = new su2double*[nTurboPerf] ();
+ TurboRadiusIn = new su2double*[nTurboPerf] ();
+ TangGridVelOut = new su2double*[nTurboPerf] ();
+ SpanAreaOut = new su2double*[nTurboPerf] ();
+ TurboRadiusOut = new su2double*[nTurboPerf] ();
}
diff --git a/Common/src/geometry/dual_grid/CVertex.cpp b/Common/src/geometry/dual_grid/CVertex.cpp
index 10a994a26fb5..fd252f8a1cff 100644
--- a/Common/src/geometry/dual_grid/CVertex.cpp
+++ b/Common/src/geometry/dual_grid/CVertex.cpp
@@ -40,52 +40,35 @@ CVertex::CVertex(unsigned long val_point, unsigned short val_nDim) : CDualGrid(v
ActDisk_Perimeter = false;
- /*--- Pointers initialization ---*/
-
- Nodes = NULL;
- Normal = NULL;
-
- /*--- Allocate node, and face normal ---*/
-
- Nodes = new unsigned long[1];
- Normal = new su2double [nDim];
-
/*--- Initializate the structure ---*/
Nodes[0] = val_point;
- for (iDim = 0; iDim < nDim; iDim ++)
- Normal[iDim] = 0.0;
+
+ for (iDim = 0; iDim < 3; iDim ++) Normal[iDim] = 0.0;
/*--- Set to zero the variation of the coordinates ---*/
- VarCoord[0] = 0.0;
- VarCoord[1] = 0.0;
- VarCoord[2] = 0.0;
+ for (iDim = 0; iDim < 3; iDim ++) VarCoord[iDim] = 0.0;
- /*--- Set to NULL variation of the rotation ---*/
+ /*--- Set to nullptr variation of the rotation ---*/
- VarRot = NULL;
+ VarRot = nullptr;
- /*--- Set to NULL donor arrays for interpolation ---*/
+ /*--- Set to nullptr donor arrays for interpolation ---*/
- Donor_Points = NULL;
- Donor_Proc = NULL;
- Donor_Coeff = NULL;
+ Donor_Points = nullptr;
+ Donor_Proc = nullptr;
+ Donor_Coeff = nullptr;
nDonor_Points = 1;
}
CVertex::~CVertex() {
- if (Normal != NULL) delete[] Normal;
- if (Nodes != NULL) delete[] Nodes;
-
- /*--- donor arrays for interpolation ---*/
-
- if (VarRot != NULL) delete[] VarRot;
- if (Donor_Coeff != NULL) delete[] Donor_Coeff;
- if (Donor_Proc != NULL) delete[] Donor_Proc;
- if (Donor_Points != NULL) delete[] Donor_Points;
+ delete[] VarRot;
+ delete[] Donor_Coeff;
+ delete[] Donor_Proc;
+ delete[] Donor_Points;
}
@@ -131,13 +114,16 @@ void CVertex::SetNodes_Coord(su2double *val_coord_Edge_CG, su2double *val_coord_
}
-void CVertex::Allocate_DonorInfo(void){
+void CVertex::Allocate_DonorInfo(unsigned short nDonor) {
+
+ nDonor_Points = nDonor;
+
+ delete [] Donor_Points;
+ delete [] Donor_Proc;
+ delete [] Donor_Coeff;
- if( Donor_Points != NULL ) delete [] Donor_Points;
- if( Donor_Proc != NULL ) delete [] Donor_Proc;
- if( Donor_Coeff != NULL ) delete [] Donor_Coeff;
+ Donor_Points = new unsigned long [nDonor_Points];
+ Donor_Proc = new unsigned long [nDonor_Points];
+ Donor_Coeff = new su2double [nDonor_Points];
- Donor_Points = new unsigned long[nDonor_Points];
- Donor_Proc = new unsigned long[nDonor_Points];
- Donor_Coeff = new su2double[nDonor_Points];
}
diff --git a/Common/src/geometry/elements/CQUAD4.cpp b/Common/src/geometry/elements/CQUAD4.cpp
index a47051f36e0e..7661a2da251b 100644
--- a/Common/src/geometry/elements/CQUAD4.cpp
+++ b/Common/src/geometry/elements/CQUAD4.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -41,25 +41,23 @@ CQUAD4::CQUAD4() : CElementWithKnownSizes() {
/*--- Store the values of the shape functions and their derivatives ---*/
- unsigned short iNode, iGauss;
- su2double Xi, Eta, val_Ni;
+ unsigned short iNode, iGauss, jGauss;
+ su2double Xi, Eta;
for (iGauss = 0; iGauss < NGAUSS; iGauss++) {
Xi = GaussCoord[iGauss][0];
Eta = GaussCoord[iGauss][1];
- val_Ni = 0.25*(1.0-Xi)*(1.0-Eta); GaussPoint[iGauss].SetNi(val_Ni,0);
- val_Ni = 0.25*(1.0+Xi)*(1.0-Eta); GaussPoint[iGauss].SetNi(val_Ni,1);
- val_Ni = 0.25*(1.0+Xi)*(1.0+Eta); GaussPoint[iGauss].SetNi(val_Ni,2);
- val_Ni = 0.25*(1.0-Xi)*(1.0+Eta); GaussPoint[iGauss].SetNi(val_Ni,3);
+ su2double Ni[4] = {0.0};
+ ShapeFunctions(Xi, Eta, Ni);
+
+ for (jGauss = 0; jGauss < NGAUSS; jGauss++)
+ GaussPoint[iGauss].SetNi(Ni[jGauss], jGauss);
/*--- dN/d xi, dN/d eta ---*/
- dNiXj[iGauss][0][0] = -0.25*(1.0-Eta); dNiXj[iGauss][0][1] = -0.25*(1.0-Xi);
- dNiXj[iGauss][1][0] = 0.25*(1.0-Eta); dNiXj[iGauss][1][1] = -0.25*(1.0+Xi);
- dNiXj[iGauss][2][0] = 0.25*(1.0+Eta); dNiXj[iGauss][2][1] = 0.25*(1.0+Xi);
- dNiXj[iGauss][3][0] = -0.25*(1.0+Eta); dNiXj[iGauss][3][1] = 0.25*(1.0-Xi);
+ ShapeFunctionJacobian(Xi, Eta, dNiXj[iGauss]);
}
diff --git a/Common/src/grid_movement_structure.cpp b/Common/src/grid_movement_structure.cpp
index 6c8e6ccf0cbc..8c99ae1db498 100644
--- a/Common/src/grid_movement_structure.cpp
+++ b/Common/src/grid_movement_structure.cpp
@@ -5681,902 +5681,321 @@ void CSurfaceMovement::Moving_Walls(CGeometry *geometry, CConfig *config,
}
}
-void CSurfaceMovement::Surface_Translating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+void CSurfaceMovement::AeroelasticDeform(CGeometry *geometry, CConfig *config, unsigned long TimeIter, unsigned short iMarker, unsigned short iMarker_Monitoring, vector& displacements) {
- su2double deltaT, time_new, time_old;
- su2double Center[3] = {0.0,0.0,0.0}, VarCoord[3] = {0.0,0.0,0.0};
- su2double xDot[3] = {0.0,0.0,0.0};
- unsigned short iMarker, jMarker, Moving;
- unsigned long iVertex;
- string Marker_Tag, Moving_Tag;
+ /* The sign conventions of these are those of the Typical Section Wing Model, below the signs are corrected */
+ su2double dh = -displacements[0]; // relative plunge
+ su2double dalpha = -displacements[1]; // relative pitch
+ su2double dh_x, dh_y;
+ su2double Center[2];
unsigned short iDim;
+ su2double Lref = config->GetLength_Ref();
+ su2double *Coord;
+ unsigned long iPoint, iVertex;
+ su2double x_new, y_new;
+ su2double VarCoord[3];
+ string Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring);
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
-
- /*--- Retrieve values from the config file ---*/
-
- deltaT = config->GetDelta_UnstTimeND();
-
- /*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
-
- /*--- Store displacement of each node on the translating surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to translate ---*/
-
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- for (iDim = 0; iDim < 3; iDim++){
- xDot[iDim] = config->GetMarkerTranslationRate(jMarker, iDim);
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
-
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing translating displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Translational velocity: (" << xDot[0]*config->GetVelocity_Ref() << ", " << xDot[1]*config->GetVelocity_Ref();
- cout << ", " << xDot[2]*config->GetVelocity_Ref();
- if (config->GetSystemMeasurements() == SI) cout << ") m/s." << endl;
- else cout << ") ft/s." << endl;
- }
- }
-
- /*--- Compute delta change in the position in the x, y, & z directions. ---*/
-
- VarCoord[0] = xDot[0]*(time_new-time_old);
- VarCoord[1] = xDot[1]*(time_new-time_old);
- VarCoord[2] = xDot[2]*(time_new-time_old);
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Set node displacement for volume deformation ---*/
- geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- }
- }
- }
+ /*--- Calculate the plunge displacement for the Typical Section Wing Model taking into account rotation ---*/
+ if (config->GetKind_GridMovement() == AEROELASTIC_RIGID_MOTION) {
+ su2double Omega, dt, psi;
+ dt = config->GetDelta_UnstTimeND();
+ Omega = (config->GetRotation_Rate(3)/config->GetOmega_Ref());
+ psi = Omega*(dt*TimeIter);
+
+ /*--- Correct for the airfoil starting position (This is hardcoded in here) ---*/
+ if (Monitoring_Tag == "Airfoil1") {
+ psi = psi + 0.0;
+ }
+ else if (Monitoring_Tag == "Airfoil2") {
+ psi = psi + 2.0/3.0*PI_NUMBER;
+ }
+ else if (Monitoring_Tag == "Airfoil3") {
+ psi = psi + 4.0/3.0*PI_NUMBER;
}
+ else
+ cout << "WARNING: There is a marker that we are monitoring that doesn't match the values hardcoded above!" << endl;
+
+ dh_x = -dh*sin(psi);
+ dh_y = dh*cos(psi);
+
+ } else {
+ dh_x = 0;
+ dh_y = dh;
}
- /*--- When updating the origins it is assumed that all markers have the
- same translational velocity, because we use the last VarCoord set ---*/
+ /*--- Pitching origin from config. ---*/
- /*--- Set the mesh motion center to the new location after
- incrementing the position with the translation. This new
- location will be used for subsequent mesh motion for the given marker.---*/
+ Center[0] = config->GetRefOriginMoment_X(iMarker_Monitoring);
+ Center[1] = config->GetRefOriginMoment_Y(iMarker_Monitoring);
- for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+ /*--- Coordinates of the current point ---*/
+ Coord = geometry->node[iPoint]->GetCoord();
- /*-- Check if we want to update the motion origin for the given marker ---*/
+ /*--- Calculate non-dim. position from rotation center ---*/
+ su2double r[2] = {0,0};
+ for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
+ r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
- if (config->GetMoveMotion_Origin(jMarker) == YES) {
- for (iDim = 0; iDim < 3; iDim++){
- Center[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center, jMarker);
- }
+ /*--- Compute delta of transformed point coordinates ---*/
+ // The deltas are needed for the FEA grid deformation Method.
+ // rotation contribution - previous position + plunging contribution
+ x_new = cos(dalpha)*r[0] - sin(dalpha)*r[1] -r[0] + dh_x;
+ y_new = sin(dalpha)*r[0] + cos(dalpha)*r[1] -r[1] + dh_y;
+
+ VarCoord[0] = x_new;
+ VarCoord[1] = y_new;
+ VarCoord[2] = 0.0;
+
+ /*--- Store new delta node locations for the surface ---*/
+ geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
}
+ /*--- Set the elastic axis to the new location after incrementing the position with the plunge ---*/
+ config->SetRefOriginMoment_X(iMarker_Monitoring, Center[0]+dh_x);
+ config->SetRefOriginMoment_Y(iMarker_Monitoring, Center[1]+dh_y);
+
- /*--- Set the moment computation center to the new location after
- incrementing the position with the translation. ---*/
-
- for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
- Center[0] = config->GetRefOriginMoment_X(jMarker) + VarCoord[0];
- Center[1] = config->GetRefOriginMoment_Y(jMarker) + VarCoord[1];
- Center[2] = config->GetRefOriginMoment_Z(jMarker) + VarCoord[2];
- config->SetRefOriginMoment_X(jMarker, Center[0]);
- config->SetRefOriginMoment_Y(jMarker, Center[1]);
- config->SetRefOriginMoment_Z(jMarker, Center[2]);
- }
}
-void CSurfaceMovement::Surface_Plunging(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+void CSurfaceMovement::SetBoundary_Flutter3D(CGeometry *geometry, CConfig *config,
+ CFreeFormDefBox **FFDBox, unsigned long iter, unsigned short iZone) {
- su2double deltaT, time_new, time_old, Lref;
- su2double Center[3] = {0.0, 0.0, 0.0}, VarCoord[3], Omega[3], Ampl[3];
+ su2double omega, deltaT;
+ su2double alpha, alpha_new, alpha_old;
+ su2double time_new, time_old;
+ su2double Omega[3], Ampl[3];
su2double DEG2RAD = PI_NUMBER/180.0;
- unsigned short iMarker, jMarker, Moving;
- unsigned long iVertex;
- string Marker_Tag, Moving_Tag;
- unsigned short iDim;
-
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
+ bool adjoint = (config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint());
+ unsigned short iDim = 0;
/*--- Retrieve values from the config file ---*/
deltaT = config->GetDelta_UnstTimeND();
- Lref = config->GetLength_Ref();
-
- /*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
- /*--- Store displacement of each node on the plunging surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to plunge ---*/
+ /*--- Pitching origin, frequency, and amplitude from config. ---*/
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Plunging frequency and amplitude from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Ampl[iDim] = config->GetMarkerPlunging_Ampl(jMarker, iDim)/Lref;
- Omega[iDim] = config->GetMarkerPlunging_Omega(jMarker, iDim)/config->GetOmega_Ref();
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing plunging displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Plunging frequency: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s." << endl;
- cout << " Plunging amplitude: (" << Ampl[0]/DEG2RAD;
- cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- }
- }
-
- /*--- Compute delta change in the position in the x, y, & z directions. ---*/
-
- VarCoord[0] = -Ampl[0]*(sin(Omega[0]*time_new) - sin(Omega[0]*time_old));
- VarCoord[1] = -Ampl[1]*(sin(Omega[1]*time_new) - sin(Omega[1]*time_old));
- VarCoord[2] = -Ampl[2]*(sin(Omega[2]*time_new) - sin(Omega[2]*time_old));
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Set node displacement for volume deformation ---*/
- geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- }
- }
- }
- }
+ for (iDim = 0; iDim < 3; iDim++){
+ Omega[iDim] = config->GetPitching_Omega(iDim)/config->GetOmega_Ref();
+ Ampl[iDim] = config->GetPitching_Ampl(iDim)*DEG2RAD;
}
- /*--- When updating the origins it is assumed that all markers have the
- same plunging movement, because we use the last VarCoord set ---*/
-
- /*--- Set the mesh motion center to the new location after
- incrementing the position with the translation. This new
- location will be used for subsequent mesh motion for the given marker.---*/
+ /*--- Compute delta time based on physical time step ---*/
- for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
+ if (adjoint) {
- /*-- Check if we want to update the motion origin for the given marker ---*/
+ /*--- For the unsteady adjoint, we integrate backwards through
+ physical time, so perform mesh motion in reverse. ---*/
- if (config->GetMoveMotion_Origin(jMarker) == YES) {
- for (iDim = 0; iDim < 3; iDim++){
- Center[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center, jMarker);
- }
+ unsigned long nFlowIter = config->GetnTime_Iter();
+ unsigned long directIter = nFlowIter - iter - 1;
+ time_new = static_cast(directIter)*deltaT;
+ time_old = time_new;
+ if (iter != 0) time_old = (static_cast(directIter)+1.0)*deltaT;
+ } else {
+
+ /*--- Forward time for the direct problem ---*/
+
+ time_new = static_cast(iter)*deltaT;
+ time_old = time_new;
+ if (iter != 0) time_old = (static_cast(iter)-1.0)*deltaT;
}
- /*--- Set the moment computation center to the new location after
- incrementing the position with the plunging. ---*/
+ /*--- Update the pitching angle at this time step. Flip sign for
+ nose-up positive convention. ---*/
- for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
- Center[0] = config->GetRefOriginMoment_X(jMarker) + VarCoord[0];
- Center[1] = config->GetRefOriginMoment_Y(jMarker) + VarCoord[1];
- Center[2] = config->GetRefOriginMoment_Z(jMarker) + VarCoord[2];
- config->SetRefOriginMoment_X(jMarker, Center[0]);
- config->SetRefOriginMoment_Y(jMarker, Center[1]);
- config->SetRefOriginMoment_Z(jMarker, Center[2]);
- }
-}
+ omega = Omega[2];
+ alpha_new = Ampl[2]*sin(omega*time_new);
+ alpha_old = Ampl[2]*sin(omega*time_old);
+ alpha = (1E-10 + (alpha_new - alpha_old))*(-PI_NUMBER/180.0);
+
+ if (rank == MASTER_NODE)
+ cout << "New dihedral angle (alpha): " << alpha_new/DEG2RAD << " degrees." << endl;
+
+ unsigned short iOrder, jOrder, kOrder;
+ short iFFDBox;
+ su2double movement[3] = {0.0,0.0,0.0};
+ bool *move = new bool [nFFDBox];
+ unsigned short *index = new unsigned short[3];
+
+ move[0] = true; move[1] = true; move[2] = true;
-void CSurfaceMovement::Surface_Pitching(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+ /*--- Change the value of the control point if move is true ---*/
- su2double deltaT, time_new, time_old, Lref, *Coord;
- su2double Center[3], VarCoord[3], Omega[3], Ampl[3], Phase[3];
- su2double rotCoord[3], r[3] = {0.0,0.0,0.0};
- su2double rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
- su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
- su2double cosPhi, sinPhi, cosPsi, sinPsi;
- su2double DEG2RAD = PI_NUMBER/180.0;
- unsigned short iMarker, jMarker, Moving, iDim, nDim = geometry->GetnDim();
- unsigned long iPoint, iVertex;
- string Marker_Tag, Moving_Tag;
+ for (iFFDBox = 0; iFFDBox < nFFDBox; iFFDBox++)
+ if (move[iFFDBox])
+ for (iOrder = 0; iOrder < FFDBox[iFFDBox]->GetlOrder(); iOrder++)
+ for (jOrder = 0; jOrder < FFDBox[iFFDBox]->GetmOrder(); jOrder++)
+ for (kOrder = 0; kOrder < FFDBox[iFFDBox]->GetnOrder(); kOrder++) {
+ index[0] = iOrder; index[1] = jOrder; index[2] = kOrder;
+ su2double *coord = FFDBox[iFFDBox]->GetCoordControlPoints(iOrder, jOrder, kOrder);
+ movement[0] = 0.0; movement[1] = 0.0; movement[2] = coord[1]*tan(alpha);
+ FFDBox[iFFDBox]->SetControlPoints(index, movement);
+ }
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
+ /*--- Recompute cartesian coordinates using the new control points position ---*/
- /*--- Retrieve values from the config file ---*/
+ for (iFFDBox = 0; iFFDBox < nFFDBox; iFFDBox++)
+ SetCartesianCoord(geometry, config, FFDBox[iFFDBox], iFFDBox, false);
- deltaT = config->GetDelta_UnstTimeND();
- Lref = config->GetLength_Ref();
+ delete [] index;
+ delete [] move;
- /*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
-
- /*--- Store displacement of each node on the pitching surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to pitch ---*/
-
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Pitching origin, frequency, and amplitude from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Ampl[iDim] = config->GetMarkerPitching_Ampl(jMarker, iDim)*DEG2RAD;
- Omega[iDim] = config->GetMarkerPitching_Omega(jMarker, iDim)/config->GetOmega_Ref();
- Phase[iDim] = config->GetMarkerPitching_Phase(jMarker, iDim)*DEG2RAD;
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing pitching displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Pitching frequency: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
- cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
- cout << " Pitching amplitude about origin: (" << Ampl[0]/DEG2RAD;
- cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- cout << " Pitching phase lag about origin: (" << Phase[0]/DEG2RAD;
- cout << ", " << Phase[1]/DEG2RAD <<", "<< Phase[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- }
- }
-
- /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
-
- dtheta = -Ampl[0]*(sin(Omega[0]*time_new + Phase[0])
- - sin(Omega[0]*time_old + Phase[0]));
- dphi = -Ampl[1]*(sin(Omega[1]*time_new + Phase[1])
- - sin(Omega[1]*time_old + Phase[1]));
- dpsi = -Ampl[2]*(sin(Omega[2]*time_new + Phase[2])
- - sin(Omega[2]*time_old + Phase[2]));
-
- /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
-
- cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
- sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
-
- /*--- Compute the rotation matrix. Note that the implicit
- ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
-
- rotMatrix[0][0] = cosPhi*cosPsi;
- rotMatrix[1][0] = cosPhi*sinPsi;
- rotMatrix[2][0] = -sinPhi;
-
- rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
- rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
- rotMatrix[2][1] = sinTheta*cosPhi;
-
- rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
- rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
- rotMatrix[2][2] = cosTheta*cosPhi;
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Index and coordinates of the current point ---*/
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- Coord = geometry->node[iPoint]->GetCoord();
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- /*--- Set node displacement for volume deformation ---*/
- geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- }
- }
- }
- }
- }
- /*--- For pitching we don't update the motion origin and moment reference origin. ---*/
}
-void CSurfaceMovement::Surface_Rotating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+void CSurfaceMovement::SetExternal_Deformation(CGeometry *geometry, CConfig *config, unsigned short iZone, unsigned long iter) {
- su2double deltaT, time_new, time_old, Lref, *Coord;
- su2double Center[3] = {0.0,0.0,0.0}, VarCoord[3] = {0.0,0.0,0.0}, Omega[3] = {0.0,0.0,0.0},
- rotCoord[3] = {0.0,0.0,0.0}, r[3] = {0.0,0.0,0.0}, Center_Aux[3] = {0.0,0.0,0.0};
- su2double rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
- su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
- su2double cosPhi, sinPhi, cosPsi, sinPsi;
- unsigned short iMarker, jMarker, Moving, iDim, nDim = geometry->GetnDim();
- unsigned long iPoint, iVertex;
- string Marker_Tag, Moving_Tag;
+ /*--- Local variables ---*/
+
+ unsigned short iDim, nDim;
+ unsigned long iPoint = 0, flowIter = 0;
+ unsigned long jPoint, GlobalIndex;
+ su2double VarCoord[3], *Coord_Old = NULL, *Coord_New = NULL, Center[3] = {0.0,0.0,0.0};
+ su2double Lref = config->GetLength_Ref();
+ su2double NewCoord[3] = {0.0,0.0,0.0}, rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
+ su2double r[3] = {0.0,0.0,0.0}, rotCoord[3] = {0.0,0.0,0.0};
+ unsigned long iVertex;
+ unsigned short iMarker;
+ char buffer[50];
+ string DV_Filename, UnstExt, text_line;
+ ifstream surface_positions;
+ bool unsteady = config->GetTime_Marching();
+ bool adjoint = (config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint());
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
+ /*--- Load stuff from config ---*/
- /*--- Retrieve values from the config file ---*/
+ nDim = geometry->GetnDim();
+ DV_Filename = config->GetDV_Filename();
- deltaT = config->GetDelta_UnstTimeND();
- Lref = config->GetLength_Ref();
+ /*--- Set the extension for the correct unsteady mesh motion file ---*/
- /*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
+ if (unsteady) {
+ if (adjoint) {
+ /*--- For the unsteady adjoint, we integrate backwards through
+ physical time, so perform mesh motion in reverse. ---*/
+ unsigned long nFlowIter = config->GetnTime_Iter() - 1;
+ flowIter = nFlowIter - iter;
+ unsigned short lastindex = DV_Filename.find_last_of(".");
+ DV_Filename = DV_Filename.substr(0, lastindex);
+ if ((SU2_TYPE::Int(flowIter) >= 0) && (SU2_TYPE::Int(flowIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 10) && (SU2_TYPE::Int(flowIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 100) && (SU2_TYPE::Int(flowIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 1000) && (SU2_TYPE::Int(flowIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(flowIter));
+ if (SU2_TYPE::Int(flowIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(flowIter));
+ UnstExt = string(buffer);
+ DV_Filename.append(UnstExt);
+ } else {
+ /*--- Forward time for the direct problem ---*/
+ flowIter = iter;
+ unsigned short lastindex = DV_Filename.find_last_of(".");
+ DV_Filename = DV_Filename.substr(0, lastindex);
+ if ((SU2_TYPE::Int(flowIter) >= 0) && (SU2_TYPE::Int(flowIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 10) && (SU2_TYPE::Int(flowIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 100) && (SU2_TYPE::Int(flowIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(flowIter));
+ if ((SU2_TYPE::Int(flowIter) >= 1000) && (SU2_TYPE::Int(flowIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(flowIter));
+ if (SU2_TYPE::Int(flowIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(flowIter));
+ UnstExt = string(buffer);
+ DV_Filename.append(UnstExt);
+ }
+
+ if (rank == MASTER_NODE)
+ cout << "Reading in the arbitrary mesh motion from direct iteration " << flowIter << "." << endl;
}
- /*--- Store displacement of each node on the rotating surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to rotate ---*/
+ /*--- Open the motion file ---*/
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Rotation origin and angular velocity from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Omega[iDim] = config->GetMarkerRotationRate(jMarker, iDim)/config->GetOmega_Ref();
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing rotating displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Angular velocity: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
- cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
- }
- }
-
- /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
-
- dtheta = Omega[0]*(time_new-time_old);
- dphi = Omega[1]*(time_new-time_old);
- dpsi = Omega[2]*(time_new-time_old);
-
- /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
-
- cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
- sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
-
- /*--- Compute the rotation matrix. Note that the implicit
- ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
-
- rotMatrix[0][0] = cosPhi*cosPsi;
- rotMatrix[1][0] = cosPhi*sinPsi;
- rotMatrix[2][0] = -sinPhi;
-
- rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
- rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
- rotMatrix[2][1] = sinTheta*cosPhi;
-
- rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
- rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
- rotMatrix[2][2] = cosTheta*cosPhi;
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Index and coordinates of the current point ---*/
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- Coord = geometry->node[iPoint]->GetCoord();
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- /*--- Set node displacement for volume deformation ---*/
- geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
+ surface_positions.open(DV_Filename.data(), ios::in);
+
+ /*--- Throw error if there is no file ---*/
+
+ if (surface_positions.fail()) {
+ SU2_MPI::Error(string("There is no surface positions file ") + DV_Filename, CURRENT_FUNCTION);
+ }
+
+ /*--- Read in and store the new mesh node locations ---*/
+
+ while (getline(surface_positions, text_line)) {
+ istringstream point_line(text_line);
+ if (nDim == 2) point_line >> iPoint >> NewCoord[0] >> NewCoord[1];
+ if (nDim == 3) point_line >> iPoint >> NewCoord[0] >> NewCoord[1] >> NewCoord[2];
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if ((config->GetMarker_All_DV(iMarker) == YES && config->GetKind_SU2() == SU2_DEF) ||
+ (config->GetMarker_All_Moving(iMarker) == YES && config->GetKind_SU2() == SU2_CFD)) {
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+ jPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+ GlobalIndex = geometry->node[jPoint]->GetGlobalIndex();
+ if (GlobalIndex == iPoint) {
+ geometry->vertex[iMarker][iVertex]->SetVarCoord(NewCoord);
+ break;
}
}
}
}
}
- /*--- When updating the origins it is assumed that all markers have the
- same rotation movement, because we use the last markers rotation matrix and center ---*/
+ /*--- Close the surface positions file ---*/
- /*--- Set the mesh motion center to the new location after
- incrementing the position with the rotation. This new
- location will be used for subsequent mesh motion for the given marker.---*/
+ surface_positions.close();
- for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- /*-- Check if we want to update the motion origin for the given marker ---*/
-
- if (config->GetMoveMotion_Origin(jMarker) == YES) {
-
- for (iDim = 0; iDim < 3; iDim++){
- Center_Aux[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Center_Aux[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Center_Aux[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- for (iDim = 0; iDim < 3; iDim++){
- Center_Aux[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center_Aux, jMarker);
- }
- }
-
- /*--- Set the moment computation center to the new location after
- incrementing the position with the rotation. ---*/
+ /*--- If rotating as well, prepare the rotation matrix ---*/
- for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
-
- Center_Aux[0] = config->GetRefOriginMoment_X(jMarker);
- Center_Aux[1] = config->GetRefOriginMoment_Y(jMarker);
- Center_Aux[2] = config->GetRefOriginMoment_Z(jMarker);
-
- /*--- Calculate non-dim. position from rotation center ---*/
+ if (config->GetKind_GridMovement() == EXTERNAL_ROTATION) {
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Center_Aux[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
+ /*--- Variables needed only for rotation ---*/
- /*--- Compute transformed point coordinates ---*/
+ su2double Omega[3], dt;
+ su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
+ su2double cosPhi, sinPhi, cosPsi, sinPsi;
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
+ /*--- Center of rotation & angular velocity vector from config ---*/
+ Center[0] = config->GetMotion_Origin(0);
+ Center[1] = config->GetMotion_Origin(1);
+ Center[2] = config->GetMotion_Origin(2);
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
+ /*--- Angular velocity vector from config ---*/
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
+ dt = static_cast(iter)*config->GetDelta_UnstTimeND();
+ Omega[0] = config->GetRotation_Rate(0);
+ Omega[1] = config->GetRotation_Rate(1);
+ Omega[2] = config->GetRotation_Rate(2);
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Center_Aux[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
+ /*--- For the unsteady adjoint, use reverse time ---*/
+ if (adjoint) {
+ /*--- Set the first adjoint mesh position to the final direct one ---*/
+ if (iter == 0) dt = ((su2double)config->GetnTime_Iter()-1) * dt;
+ /*--- Reverse the rotation direction for the adjoint ---*/
+ else dt = -1.0*dt;
+ } else {
+ /*--- No rotation at all for the first direct solution ---*/
+ if (iter == 0) dt = 0;
+ }
- config->SetRefOriginMoment_X(jMarker, Center_Aux[0]+VarCoord[0]);
- config->SetRefOriginMoment_Y(jMarker, Center_Aux[1]+VarCoord[1]);
- config->SetRefOriginMoment_Z(jMarker, Center_Aux[2]+VarCoord[2]);
- }
-}
-
-void CSurfaceMovement::AeroelasticDeform(CGeometry *geometry, CConfig *config, unsigned long TimeIter, unsigned short iMarker, unsigned short iMarker_Monitoring, vector& displacements) {
-
- /* The sign conventions of these are those of the Typical Section Wing Model, below the signs are corrected */
- su2double dh = -displacements[0]; // relative plunge
- su2double dalpha = -displacements[1]; // relative pitch
- su2double dh_x, dh_y;
- su2double Center[2];
- unsigned short iDim;
- su2double Lref = config->GetLength_Ref();
- su2double *Coord;
- unsigned long iPoint, iVertex;
- su2double x_new, y_new;
- su2double VarCoord[3];
- string Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring);
-
- /*--- Calculate the plunge displacement for the Typical Section Wing Model taking into account rotation ---*/
- if (config->GetKind_GridMovement() == AEROELASTIC_RIGID_MOTION) {
- su2double Omega, dt, psi;
- dt = config->GetDelta_UnstTimeND();
- Omega = (config->GetRotation_Rate(3)/config->GetOmega_Ref());
- psi = Omega*(dt*TimeIter);
+ /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
- /*--- Correct for the airfoil starting position (This is hardcoded in here) ---*/
- if (Monitoring_Tag == "Airfoil1") {
- psi = psi + 0.0;
- }
- else if (Monitoring_Tag == "Airfoil2") {
- psi = psi + 2.0/3.0*PI_NUMBER;
- }
- else if (Monitoring_Tag == "Airfoil3") {
- psi = psi + 4.0/3.0*PI_NUMBER;
- }
- else
- cout << "WARNING: There is a marker that we are monitoring that doesn't match the values hardcoded above!" << endl;
+ dtheta = Omega[0]*dt;
+ dphi = Omega[1]*dt;
+ dpsi = Omega[2]*dt;
- dh_x = -dh*sin(psi);
- dh_y = dh*cos(psi);
+ /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
- } else {
- dh_x = 0;
- dh_y = dh;
- }
-
- /*--- Pitching origin from config. ---*/
-
- Center[0] = config->GetRefOriginMoment_X(iMarker_Monitoring);
- Center[1] = config->GetRefOriginMoment_Y(iMarker_Monitoring);
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- /*--- Coordinates of the current point ---*/
- Coord = geometry->node[iPoint]->GetCoord();
+ cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
+ sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
- /*--- Calculate non-dim. position from rotation center ---*/
- su2double r[2] = {0,0};
- for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
- r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
+ /*--- Compute the rotation matrix. Note that the implicit
+ ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
- /*--- Compute delta of transformed point coordinates ---*/
- // The deltas are needed for the FEA grid deformation Method.
- // rotation contribution - previous position + plunging contribution
- x_new = cos(dalpha)*r[0] - sin(dalpha)*r[1] -r[0] + dh_x;
- y_new = sin(dalpha)*r[0] + cos(dalpha)*r[1] -r[1] + dh_y;
+ rotMatrix[0][0] = cosPhi*cosPsi;
+ rotMatrix[1][0] = cosPhi*sinPsi;
+ rotMatrix[2][0] = -sinPhi;
- VarCoord[0] = x_new;
- VarCoord[1] = y_new;
- VarCoord[2] = 0.0;
-
- /*--- Store new delta node locations for the surface ---*/
- geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
- }
- /*--- Set the elastic axis to the new location after incrementing the position with the plunge ---*/
- config->SetRefOriginMoment_X(iMarker_Monitoring, Center[0]+dh_x);
- config->SetRefOriginMoment_Y(iMarker_Monitoring, Center[1]+dh_y);
-
-
-}
-
-void CSurfaceMovement::SetBoundary_Flutter3D(CGeometry *geometry, CConfig *config,
- CFreeFormDefBox **FFDBox, unsigned long iter, unsigned short iZone) {
-
- su2double omega, deltaT;
- su2double alpha, alpha_new, alpha_old;
- su2double time_new, time_old;
- su2double Omega[3], Ampl[3];
- su2double DEG2RAD = PI_NUMBER/180.0;
- bool adjoint = (config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint());
- unsigned short iDim = 0;
-
- /*--- Retrieve values from the config file ---*/
-
- deltaT = config->GetDelta_UnstTimeND();
-
- /*--- Pitching origin, frequency, and amplitude from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Omega[iDim] = config->GetPitching_Omega(iDim)/config->GetOmega_Ref();
- Ampl[iDim] = config->GetPitching_Ampl(iDim)*DEG2RAD;
- }
-
- /*--- Compute delta time based on physical time step ---*/
-
- if (adjoint) {
-
- /*--- For the unsteady adjoint, we integrate backwards through
- physical time, so perform mesh motion in reverse. ---*/
-
- unsigned long nFlowIter = config->GetnTime_Iter();
- unsigned long directIter = nFlowIter - iter - 1;
- time_new = static_cast(directIter)*deltaT;
- time_old = time_new;
- if (iter != 0) time_old = (static_cast(directIter)+1.0)*deltaT;
- } else {
-
- /*--- Forward time for the direct problem ---*/
-
- time_new = static_cast(iter)*deltaT;
- time_old = time_new;
- if (iter != 0) time_old = (static_cast(iter)-1.0)*deltaT;
- }
-
- /*--- Update the pitching angle at this time step. Flip sign for
- nose-up positive convention. ---*/
-
- omega = Omega[2];
- alpha_new = Ampl[2]*sin(omega*time_new);
- alpha_old = Ampl[2]*sin(omega*time_old);
- alpha = (1E-10 + (alpha_new - alpha_old))*(-PI_NUMBER/180.0);
-
- if (rank == MASTER_NODE)
- cout << "New dihedral angle (alpha): " << alpha_new/DEG2RAD << " degrees." << endl;
-
- unsigned short iOrder, jOrder, kOrder;
- short iFFDBox;
- su2double movement[3] = {0.0,0.0,0.0};
- bool *move = new bool [nFFDBox];
- unsigned short *index = new unsigned short[3];
-
- move[0] = true; move[1] = true; move[2] = true;
-
- /*--- Change the value of the control point if move is true ---*/
-
- for (iFFDBox = 0; iFFDBox < nFFDBox; iFFDBox++)
- if (move[iFFDBox])
- for (iOrder = 0; iOrder < FFDBox[iFFDBox]->GetlOrder(); iOrder++)
- for (jOrder = 0; jOrder < FFDBox[iFFDBox]->GetmOrder(); jOrder++)
- for (kOrder = 0; kOrder < FFDBox[iFFDBox]->GetnOrder(); kOrder++) {
- index[0] = iOrder; index[1] = jOrder; index[2] = kOrder;
- su2double *coord = FFDBox[iFFDBox]->GetCoordControlPoints(iOrder, jOrder, kOrder);
- movement[0] = 0.0; movement[1] = 0.0; movement[2] = coord[1]*tan(alpha);
- FFDBox[iFFDBox]->SetControlPoints(index, movement);
- }
-
- /*--- Recompute cartesian coordinates using the new control points position ---*/
-
- for (iFFDBox = 0; iFFDBox < nFFDBox; iFFDBox++)
- SetCartesianCoord(geometry, config, FFDBox[iFFDBox], iFFDBox, false);
-
- delete [] index;
- delete [] move;
-
-}
-
-void CSurfaceMovement::SetExternal_Deformation(CGeometry *geometry, CConfig *config, unsigned short iZone, unsigned long iter) {
-
- /*--- Local variables ---*/
-
- unsigned short iDim, nDim;
- unsigned long iPoint = 0, flowIter = 0;
- unsigned long jPoint, GlobalIndex;
- su2double VarCoord[3], *Coord_Old = NULL, *Coord_New = NULL, Center[3] = {0.0,0.0,0.0};
- su2double Lref = config->GetLength_Ref();
- su2double NewCoord[3] = {0.0,0.0,0.0}, rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
- su2double r[3] = {0.0,0.0,0.0}, rotCoord[3] = {0.0,0.0,0.0};
- unsigned long iVertex;
- unsigned short iMarker;
- char buffer[50];
- string DV_Filename, UnstExt, text_line;
- ifstream surface_positions;
- bool unsteady = config->GetTime_Marching();
- bool adjoint = (config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint());
-
- /*--- Load stuff from config ---*/
-
- nDim = geometry->GetnDim();
- DV_Filename = config->GetDV_Filename();
-
- /*--- Set the extension for the correct unsteady mesh motion file ---*/
-
- if (unsteady) {
- if (adjoint) {
- /*--- For the unsteady adjoint, we integrate backwards through
- physical time, so perform mesh motion in reverse. ---*/
- unsigned long nFlowIter = config->GetnTime_Iter() - 1;
- flowIter = nFlowIter - iter;
- unsigned short lastindex = DV_Filename.find_last_of(".");
- DV_Filename = DV_Filename.substr(0, lastindex);
- if ((SU2_TYPE::Int(flowIter) >= 0) && (SU2_TYPE::Int(flowIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 10) && (SU2_TYPE::Int(flowIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 100) && (SU2_TYPE::Int(flowIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 1000) && (SU2_TYPE::Int(flowIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(flowIter));
- if (SU2_TYPE::Int(flowIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(flowIter));
- UnstExt = string(buffer);
- DV_Filename.append(UnstExt);
- } else {
- /*--- Forward time for the direct problem ---*/
- flowIter = iter;
- unsigned short lastindex = DV_Filename.find_last_of(".");
- DV_Filename = DV_Filename.substr(0, lastindex);
- if ((SU2_TYPE::Int(flowIter) >= 0) && (SU2_TYPE::Int(flowIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 10) && (SU2_TYPE::Int(flowIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 100) && (SU2_TYPE::Int(flowIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(flowIter));
- if ((SU2_TYPE::Int(flowIter) >= 1000) && (SU2_TYPE::Int(flowIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(flowIter));
- if (SU2_TYPE::Int(flowIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(flowIter));
- UnstExt = string(buffer);
- DV_Filename.append(UnstExt);
- }
-
- if (rank == MASTER_NODE)
- cout << "Reading in the arbitrary mesh motion from direct iteration " << flowIter << "." << endl;
- }
-
- /*--- Open the motion file ---*/
-
- surface_positions.open(DV_Filename.data(), ios::in);
-
- /*--- Throw error if there is no file ---*/
-
- if (surface_positions.fail()) {
- SU2_MPI::Error(string("There is no surface positions file ") + DV_Filename, CURRENT_FUNCTION);
- }
-
- /*--- Read in and store the new mesh node locations ---*/
-
- while (getline(surface_positions, text_line)) {
- istringstream point_line(text_line);
- if (nDim == 2) point_line >> iPoint >> NewCoord[0] >> NewCoord[1];
- if (nDim == 3) point_line >> iPoint >> NewCoord[0] >> NewCoord[1] >> NewCoord[2];
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if ((config->GetMarker_All_DV(iMarker) == YES && config->GetKind_SU2() == SU2_DEF) ||
- (config->GetMarker_All_Moving(iMarker) == YES && config->GetKind_SU2() == SU2_CFD)) {
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
- jPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- GlobalIndex = geometry->node[jPoint]->GetGlobalIndex();
- if (GlobalIndex == iPoint) {
- geometry->vertex[iMarker][iVertex]->SetVarCoord(NewCoord);
- break;
- }
- }
- }
- }
- }
-
- /*--- Close the surface positions file ---*/
-
- surface_positions.close();
-
- /*--- If rotating as well, prepare the rotation matrix ---*/
-
- if (config->GetKind_GridMovement() == EXTERNAL_ROTATION) {
-
- /*--- Variables needed only for rotation ---*/
-
- su2double Omega[3], dt;
- su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
- su2double cosPhi, sinPhi, cosPsi, sinPsi;
-
- /*--- Center of rotation & angular velocity vector from config ---*/
- Center[0] = config->GetMotion_Origin(0);
- Center[1] = config->GetMotion_Origin(1);
- Center[2] = config->GetMotion_Origin(2);
-
- /*--- Angular velocity vector from config ---*/
-
- dt = static_cast(iter)*config->GetDelta_UnstTimeND();
- Omega[0] = config->GetRotation_Rate(0);
- Omega[1] = config->GetRotation_Rate(1);
- Omega[2] = config->GetRotation_Rate(2);
-
- /*--- For the unsteady adjoint, use reverse time ---*/
- if (adjoint) {
- /*--- Set the first adjoint mesh position to the final direct one ---*/
- if (iter == 0) dt = ((su2double)config->GetnTime_Iter()-1) * dt;
- /*--- Reverse the rotation direction for the adjoint ---*/
- else dt = -1.0*dt;
- } else {
- /*--- No rotation at all for the first direct solution ---*/
- if (iter == 0) dt = 0;
- }
-
- /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
-
- dtheta = Omega[0]*dt;
- dphi = Omega[1]*dt;
- dpsi = Omega[2]*dt;
-
- /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
-
- cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
- sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
-
- /*--- Compute the rotation matrix. Note that the implicit
- ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
-
- rotMatrix[0][0] = cosPhi*cosPsi;
- rotMatrix[1][0] = cosPhi*sinPsi;
- rotMatrix[2][0] = -sinPhi;
-
- rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
- rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
- rotMatrix[2][1] = sinTheta*cosPhi;
-
- rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
- rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
- rotMatrix[2][2] = cosTheta*cosPhi;
+ rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
+ rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
+ rotMatrix[2][1] = sinTheta*cosPhi;
+
+ rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
+ rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
+ rotMatrix[2][2] = cosTheta*cosPhi;
}
@@ -9109,817 +8528,6 @@ su2double CFreeFormDefBox::GetDerivative5(su2double *uvw, unsigned short dim, un
return value;
}
-
-
-CElasticityMovement::CElasticityMovement(CGeometry *geometry, CConfig *config) : CVolumetricMovement(), System(true) {
-
- size = SU2_MPI::GetSize();
- rank = SU2_MPI::GetRank();
-
- /*--- Initialize the number of spatial dimensions, length of the state
- vector (same as spatial dimensions for grid deformation), and grid nodes. ---*/
-
- unsigned short iDim, jDim;
-
- nDim = geometry->GetnDim();
- nVar = geometry->GetnDim();
- nPoint = geometry->GetnPoint();
- nPointDomain = geometry->GetnPointDomain();
-
- nIterMesh = 0;
- valResidual = 0.0;
-
- MinVolume = 0.0;
- MaxVolume = 0.0;
-
- Residual = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Residual[iDim] = 0.0;
- Solution = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Solution[iDim] = 0.0;
-
- /*--- Initialize matrix, solution, and r.h.s. structures for the linear solver. ---*/
-
- LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0);
- LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0);
- StiffMatrix.Initialize(nPoint, nPointDomain, nVar, nVar, false, geometry, config);
-
- /*--- Matrices to impose boundary conditions ---*/
-
- matrixZeros = new su2double *[nDim];
- matrixId = new su2double *[nDim];
- for(iDim = 0; iDim < nDim; iDim++){
- matrixZeros[iDim] = new su2double[nDim];
- matrixId[iDim] = new su2double[nDim];
- }
-
- for(iDim = 0; iDim < nDim; iDim++){
- for (jDim = 0; jDim < nDim; jDim++){
- matrixZeros[iDim][jDim] = 0.0;
- matrixId[iDim][jDim] = 0.0;
- }
- matrixId[iDim][iDim] = 1.0;
- }
-
- /*--- Structural parameters ---*/
-
- E = config->GetDeform_ElasticityMod();
- Nu = config->GetDeform_PoissonRatio();
-
- Mu = E / (2.0*(1.0 + Nu));
- Lambda = Nu*E/((1.0+Nu)*(1.0-2.0*Nu));
-
- /*--- Element container structure ---*/
-
- element_container = new CElement* [MAX_FE_KINDS];
- for (unsigned short iKind = 0; iKind < MAX_FE_KINDS; iKind++) {
- element_container[iKind] = NULL;
- }
- if (nDim == 2){
- element_container[EL_TRIA] = new CTRIA1();
- element_container[EL_QUAD] = new CQUAD4();
- }
- else {
- element_container[EL_TETRA] = new CTETRA1();
- element_container[EL_HEXA] = new CHEXA8();
- element_container[EL_PYRAM] = new CPYRAM5();
- element_container[EL_PRISM] = new CPRISM6();
- }
-
- /*--- Term ij of the Jacobian ---*/
-
- Jacobian_ij = new su2double*[nDim];
- for (iDim = 0; iDim < nDim; iDim++) {
- Jacobian_ij[iDim] = new su2double [nDim];
- for (jDim = 0; jDim < nDim; jDim++) {
- Jacobian_ij[iDim][jDim] = 0.0;
- }
- }
-
- KAux_ab = new su2double* [nDim];
- for (iDim = 0; iDim < nDim; iDim++) {
- KAux_ab[iDim] = new su2double[nDim];
- }
-
- unsigned short iVar;
-
- if (nDim == 2){
- Ba_Mat = new su2double* [3];
- Bb_Mat = new su2double* [3];
- D_Mat = new su2double* [3];
- GradNi_Ref_Mat = new su2double* [4];
- for (iVar = 0; iVar < 3; iVar++) {
- Ba_Mat[iVar] = new su2double[nDim];
- Bb_Mat[iVar] = new su2double[nDim];
- D_Mat[iVar] = new su2double[3];
- }
- for (iVar = 0; iVar < 4; iVar++) {
- GradNi_Ref_Mat[iVar] = new su2double[nDim];
- }
- }
- else if (nDim == 3){
- Ba_Mat = new su2double* [6];
- Bb_Mat = new su2double* [6];
- D_Mat = new su2double* [6];
- GradNi_Ref_Mat = new su2double* [8];
- for (iVar = 0; iVar < 6; iVar++) {
- Ba_Mat[iVar] = new su2double[nDim];
- Bb_Mat[iVar] = new su2double[nDim];
- D_Mat[iVar] = new su2double[6];
- }
- for (iVar = 0; iVar < 8; iVar++) {
- GradNi_Ref_Mat[iVar] = new su2double[nDim];
- }
- }
-
-
-
-}
-
-CElasticityMovement::~CElasticityMovement(void) {
-
- unsigned short iDim, iVar;
-
- delete [] Residual;
- delete [] Solution;
-
- for (iDim = 0; iDim < nDim; iDim++) {
- delete [] matrixZeros[iDim];
- delete [] matrixId[iDim];
- delete [] Jacobian_ij[iDim];
- delete [] KAux_ab[iDim];
- }
- delete [] matrixZeros;
- delete [] matrixId;
- delete [] Jacobian_ij;
- delete [] KAux_ab;
-
- if (nDim == 2){
- for (iVar = 0; iVar < 3; iVar++){
- delete [] Ba_Mat[iVar];
- delete [] Bb_Mat[iVar];
- delete [] D_Mat[iVar];
- }
- for (iVar = 0; iVar < 4; iVar++){
- delete [] GradNi_Ref_Mat[iVar];
- }
- }
- else if (nDim == 3){
- for (iVar = 0; iVar < 6; iVar++){
- delete [] Ba_Mat[iVar];
- delete [] Bb_Mat[iVar];
- delete [] D_Mat[iVar];
- }
- for (iVar = 0; iVar < 8; iVar++){
- delete [] GradNi_Ref_Mat[iVar];
- }
- }
-
- delete [] Ba_Mat;
- delete [] Bb_Mat;
- delete [] D_Mat;
- delete [] GradNi_Ref_Mat;
-
- if (element_container != NULL) {
- for (iVar = 0; iVar < MAX_FE_KINDS; iVar++){
- if (element_container[iVar] != NULL) delete element_container[iVar];
- }
- delete [] element_container;
- }
-
-}
-
-
-void CElasticityMovement::SetVolume_Deformation_Elas(CGeometry *geometry, CConfig *config, bool UpdateGeo, bool screen_output, bool Derivative){
-
- unsigned long iNonlinear_Iter, Nonlinear_Iter = 0;
-
- bool discrete_adjoint = config->GetDiscrete_Adjoint();
-
- /*--- Retrieve number or internal iterations from config ---*/
-
- Nonlinear_Iter = config->GetGridDef_Nonlinear_Iter();
-
- /*--- Loop over the total number of grid deformation iterations. The surface
- deformation can be divided into increments to help with stability. ---*/
-
- for (iNonlinear_Iter = 0; iNonlinear_Iter < Nonlinear_Iter; iNonlinear_Iter++) {
-
- /*--- Initialize vector and sparse matrix ---*/
- LinSysSol.SetValZero();
- LinSysRes.SetValZero();
- StiffMatrix.SetValZero();
-
- if ((rank == MASTER_NODE) && (!discrete_adjoint) && screen_output)
- cout << "Computing volumes of the grid elements." << endl;
-
- /*--- Compute the minimum and maximum area/volume for the mesh. ---*/
- SetMinMaxVolume(geometry, config);
- if ((rank == MASTER_NODE) && (!discrete_adjoint) && screen_output) {
- if (nDim == 2) cout << scientific << "Min. area: "<< MinVolume <<", max. area: " << MaxVolume <<"." << endl;
- else cout << scientific << "Min. volume: "<< MinVolume <<", max. volume: " << MaxVolume <<"." << endl;
- }
-
- /*--- Compute the stiffness matrix. ---*/
- SetStiffnessMatrix(geometry, config);
-
- /*--- Impose boundary conditions (all of them are ESSENTIAL BC's - displacements). ---*/
- SetBoundaryDisplacements(geometry, config);
-
- /*--- Solve the linear system. ---*/
-
-#ifdef CODI_REVERSE_TYPE
- /*--- We need to guard the SendReceive_Solution otherwise the FSI adjoint breaks. ---*/
- bool TapeActive = NO;
- if (config->GetDiscrete_Adjoint()) {
- TapeActive = AD::globalTape.isActive();
- AD::StopRecording();
- }
-#endif
- StiffMatrix.InitiateComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
- StiffMatrix.CompleteComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
-
- StiffMatrix.InitiateComms(LinSysRes, geometry, config, SOLUTION_MATRIX);
- StiffMatrix.CompleteComms(LinSysRes, geometry, config, SOLUTION_MATRIX);
-#ifdef CODI_REVERSE_TYPE
- if (TapeActive) AD::StartRecording();
-#endif
- nIterMesh = System.Solve(StiffMatrix, LinSysRes, LinSysSol, geometry, config);
- valResidual = System.GetResidual();
-
- /*--- Update the grid coordinates and cell volumes using the solution
- of the linear system (usol contains the x, y, z displacements). ---*/
- UpdateGridCoord(geometry, config);
-
- if (UpdateGeo)
- UpdateDualGrid(geometry, config);
-
- /*--- Check for failed deformation (negative volumes). ---*/
- /*--- In order to do this, we recompute the minimum and maximum area/volume for the mesh. ---*/
- SetMinMaxVolume(geometry, config);
-
- if ((rank == MASTER_NODE) && (!discrete_adjoint) && screen_output) {
- cout << scientific << "Non-linear iter.: " << iNonlinear_Iter+1 << "/" << Nonlinear_Iter << ". Linear iter.: " << nIterMesh << ". ";
- if (nDim == 2) cout << "Min. area: " << MinVolume << ". Error: " << valResidual << "." << endl;
- else cout << "Min. volume: " << MinVolume << ". Error: " << valResidual << "." << endl;
- }
-
- }
-
-}
-
-
-void CElasticityMovement::UpdateGridCoord(CGeometry *geometry, CConfig *config){
-
- unsigned short iDim;
- unsigned long iPoint, total_index;
- su2double new_coord;
-
- /*--- Update the grid coordinates using the solution of the linear system
- after grid deformation (LinSysSol contains the x, y, z displacements). ---*/
-
- for (iPoint = 0; iPoint < nPoint; iPoint++)
- for (iDim = 0; iDim < nDim; iDim++) {
- total_index = iPoint*nDim + iDim;
- new_coord = geometry->node[iPoint]->GetCoord(iDim)+LinSysSol[total_index];
- if (fabs(new_coord) < EPS*EPS) new_coord = 0.0;
- geometry->node[iPoint]->SetCoord(iDim, new_coord);
- }
-
- /* --- LinSysSol contains the non-transformed displacements in the periodic halo cells.
- * Hence we still need a communication of the transformed coordinates, otherwise periodicity
- * is not maintained. ---*/
-
- geometry->InitiateComms(geometry, config, COORDINATES);
- geometry->CompleteComms(geometry, config, COORDINATES);
-
-}
-
-
-void CElasticityMovement::UpdateDualGrid(CGeometry *geometry, CConfig *config){
-
- /*--- After moving all nodes, update the dual mesh. Recompute the edges and
- dual mesh control volumes in the domain and on the boundaries. ---*/
-
- geometry->SetCoord_CG();
- geometry->SetControlVolume(config, UPDATE);
- geometry->SetBoundControlVolume(config, UPDATE);
- geometry->SetMaxLength(config);
-
-}
-
-
-void CElasticityMovement::UpdateMultiGrid(CGeometry **geometry, CConfig *config){
-
- unsigned short iMGfine, iMGlevel, nMGlevel = config->GetnMGLevels();
-
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
-
- for (iMGlevel = 1; iMGlevel <= nMGlevel; iMGlevel++) {
- iMGfine = iMGlevel-1;
- geometry[iMGlevel]->SetControlVolume(config, geometry[iMGfine], UPDATE);
- geometry[iMGlevel]->SetBoundControlVolume(config, geometry[iMGfine],UPDATE);
- geometry[iMGlevel]->SetCoord(geometry[iMGfine]);
- if (config->GetGrid_Movement())
- geometry[iMGlevel]->SetRestricted_GridVelocity(geometry[iMGfine], config);
- }
-
-}
-
-void CElasticityMovement::SetBoundaryDisplacements(CGeometry *geometry, CConfig *config){
-
- /*--- Get the SU2 module. SU2_CFD will use this routine for dynamically
- deforming meshes (MARKER_FSI_INTERFACE). ---*/
-
- unsigned short Kind_SU2 = config->GetKind_SU2();
-
- /*--- Share halo vertex displacements across ranks using the solution vector.
- The transfer routines do not do this, i.e. halo vertices have wrong values. ---*/
-
- unsigned short iMarker, iDim;
- unsigned long iNode, iVertex;
-
- su2double VarIncrement = 1.0/su2double(config->GetGridDef_Nonlinear_Iter());
-
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
-
- if ((config->GetMarker_All_ZoneInterface(iMarker) != 0 ||
- config->GetMarker_All_Moving(iMarker))
- && (Kind_SU2 == SU2_CFD)) {
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Get node index ---*/
- iNode = geometry->vertex[iMarker][iVertex]->GetNode();
-
- if (geometry->node[iNode]->GetDomain()) {
-
- /*--- Get the displacement on the vertex ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- Solution[iDim] = geometry->vertex[iMarker][iVertex]->GetVarCoord()[iDim] * VarIncrement;
-
- /*--- Initialize the solution vector ---*/
- LinSysSol.SetBlock(iNode, Solution);
- }
- }
- }
- }
- StiffMatrix.InitiateComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
- StiffMatrix.CompleteComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
-
- /*--- Apply displacement boundary conditions to the FSI interfaces. ---*/
-
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if ((config->GetMarker_All_ZoneInterface(iMarker) != 0 ||
- config->GetMarker_All_Moving(iMarker))
- && (Kind_SU2 == SU2_CFD)) {
- SetMoving_Boundary(geometry, config, iMarker);
- }
- }
-
- /*--- Now, set to zero displacements of all the other boundary conditions, except the symmetry
- plane, the receive boundaries and periodic boundaries. ---*/
-
-
- /*--- As initialization, set to zero displacements of all the surfaces except the symmetry
- plane, the receive boundaries and periodic boundaries. ---*/
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if (((config->GetMarker_All_KindBC(iMarker) != SYMMETRY_PLANE) &&
- (config->GetMarker_All_KindBC(iMarker) != SEND_RECEIVE) &&
- (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY))
- && !config->GetMarker_All_Moving(iMarker)) {
-
- /*--- We must note that the FSI surfaces are not clamped ---*/
- if (config->GetMarker_All_ZoneInterface(iMarker) == 0){
- SetClamped_Boundary(geometry, config, iMarker);
- }
- }
- }
-
- /*--- All others are pending. ---*/
-
-}
-
-
-void CElasticityMovement::SetClamped_Boundary(CGeometry *geometry, CConfig *config, unsigned short val_marker){
-
- unsigned long iNode, iVertex;
-
- Solution[0] = 0.0;
- Solution[1] = 0.0;
- if (nDim==3) Solution[2] = 0.0;
-
- for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
-
- /*--- Get node index ---*/
- iNode = geometry->vertex[val_marker][iVertex]->GetNode();
-
- /*--- Set and enforce solution ---*/
- LinSysSol.SetBlock(iNode, Solution);
- StiffMatrix.EnforceSolutionAtNode(iNode, Solution, LinSysRes);
-
- }
-
-}
-
-void CElasticityMovement::SetMoving_Boundary(CGeometry *geometry, CConfig *config, unsigned short val_marker){
-
- unsigned long iNode, iVertex;
-
- for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
-
- /*--- Get node index ---*/
- iNode = geometry->vertex[val_marker][iVertex]->GetNode();
-
- /*--- Enforce solution ---*/
- StiffMatrix.EnforceSolutionAtNode(iNode, LinSysSol.GetBlock(iNode), LinSysRes);
-
- }
-
-}
-
-void CElasticityMovement::SetMinMaxVolume(CGeometry *geometry, CConfig *config) {
-
- unsigned long iElem, ElemCounter = 0;
- unsigned short iNode, iDim, nNodes = 0;
- unsigned long indexNode[8]={0,0,0,0,0,0,0,0};
- su2double val_Coord;
- int EL_KIND = 0;
-
- bool RightVol = true;
-
- su2double ElemVolume;
-
- MaxVolume = -1E22; MinVolume = 1E22;
-
- /*--- Loops over all the elements ---*/
-
- for (iElem = 0; iElem < geometry->GetnElem(); iElem++) {
-
- if (geometry->elem[iElem]->GetVTK_Type() == TRIANGLE) {nNodes = 3; EL_KIND = EL_TRIA;}
- if (geometry->elem[iElem]->GetVTK_Type() == QUADRILATERAL) {nNodes = 4; EL_KIND = EL_QUAD;}
- if (geometry->elem[iElem]->GetVTK_Type() == TETRAHEDRON) {nNodes = 4; EL_KIND = EL_TETRA;}
- if (geometry->elem[iElem]->GetVTK_Type() == PYRAMID) {nNodes = 5; EL_KIND = EL_PYRAM;}
- if (geometry->elem[iElem]->GetVTK_Type() == PRISM) {nNodes = 6; EL_KIND = EL_PRISM;}
- if (geometry->elem[iElem]->GetVTK_Type() == HEXAHEDRON) {nNodes = 8; EL_KIND = EL_HEXA;}
-
- /*--- For the number of nodes, we get the coordinates from the connectivity matrix and the geometry structure ---*/
-
- for (iNode = 0; iNode < nNodes; iNode++) {
-
- indexNode[iNode] = geometry->elem[iElem]->GetNode(iNode);
-
- for (iDim = 0; iDim < nDim; iDim++) {
- val_Coord = geometry->node[indexNode[iNode]]->GetCoord(iDim);
- element_container[EL_KIND]->SetRef_Coord(iNode, iDim, val_Coord);
- }
-
- }
-
- /*--- Compute the volume of the element (or the area in 2D cases ) ---*/
-
- if (nDim == 2) ElemVolume = element_container[EL_KIND]->ComputeArea();
- else ElemVolume = element_container[EL_KIND]->ComputeVolume();
-
- RightVol = true;
- if (ElemVolume < 0.0) RightVol = false;
-
- MaxVolume = max(MaxVolume, ElemVolume);
- MinVolume = min(MinVolume, ElemVolume);
- geometry->elem[iElem]->SetVolume(ElemVolume);
-
- if (!RightVol) ElemCounter++;
-
- }
-
-#ifdef HAVE_MPI
- unsigned long ElemCounter_Local = ElemCounter; ElemCounter = 0;
- su2double MaxVolume_Local = MaxVolume; MaxVolume = 0.0;
- su2double MinVolume_Local = MinVolume; MinVolume = 0.0;
- SU2_MPI::Allreduce(&ElemCounter_Local, &ElemCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MaxVolume_Local, &MaxVolume, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MinVolume_Local, &MinVolume, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
-#endif
-
- /*--- Volume from 0 to 1 ---*/
-
- for (iElem = 0; iElem < geometry->GetnElem(); iElem++) {
- ElemVolume = geometry->elem[iElem]->GetVolume()/MaxVolume;
- geometry->elem[iElem]->SetVolume(ElemVolume);
- }
-
- if ((ElemCounter != 0) && (rank == MASTER_NODE))
- cout <<"There are " << ElemCounter << " elements with negative volume.\n" << endl;
-
-}
-
-
-void CElasticityMovement::SetStiffnessMatrix(CGeometry *geometry, CConfig *config){
-
- unsigned long iElem;
- unsigned short iNode, iDim, jDim, nNodes = 0;
- unsigned long indexNode[8]={0,0,0,0,0,0,0,0};
- su2double val_Coord;
- int EL_KIND = 0;
-
- const su2double *Kab = NULL;
- unsigned short NelNodes, jNode;
-
- su2double ElemVolume;
-
- /*--- Loops over all the elements ---*/
-
- for (iElem = 0; iElem < geometry->GetnElem(); iElem++) {
-
- if (geometry->elem[iElem]->GetVTK_Type() == TRIANGLE) {nNodes = 3; EL_KIND = EL_TRIA;}
- if (geometry->elem[iElem]->GetVTK_Type() == QUADRILATERAL) {nNodes = 4; EL_KIND = EL_QUAD;}
- if (geometry->elem[iElem]->GetVTK_Type() == TETRAHEDRON) {nNodes = 4; EL_KIND = EL_TETRA;}
- if (geometry->elem[iElem]->GetVTK_Type() == PYRAMID) {nNodes = 5; EL_KIND = EL_PYRAM;}
- if (geometry->elem[iElem]->GetVTK_Type() == PRISM) {nNodes = 6; EL_KIND = EL_PRISM;}
- if (geometry->elem[iElem]->GetVTK_Type() == HEXAHEDRON) {nNodes = 8; EL_KIND = EL_HEXA;}
-
- /*--- For the number of nodes, we get the coordinates from the connectivity matrix and the geometry structure ---*/
-
- for (iNode = 0; iNode < nNodes; iNode++) {
-
- indexNode[iNode] = geometry->elem[iElem]->GetNode(iNode);
-
- for (iDim = 0; iDim < nDim; iDim++) {
- val_Coord = geometry->node[indexNode[iNode]]->GetCoord(iDim);
- element_container[EL_KIND]->SetRef_Coord(iNode, iDim, val_Coord);
- }
-
- }
-
- /*--- Retrieve the volume of the element (previously computed in SetMinMaxVolume()) ---*/
-
- ElemVolume = geometry->elem[iElem]->GetVolume();
-
- /*--- Compute the stiffness of the element ---*/
- Set_Element_Stiffness(ElemVolume, config);
-
- /*--- Compute the element contribution to the stiffness matrix ---*/
-
- Compute_Element_Contribution(element_container[EL_KIND], config);
-
- /*--- Retrieve number of nodes ---*/
-
- NelNodes = element_container[EL_KIND]->GetnNodes();
-
- /*--- Assemble the stiffness matrix ---*/
-
- for (iNode = 0; iNode < NelNodes; iNode++){
-
- for (jNode = 0; jNode < NelNodes; jNode++){
-
- Kab = element_container[EL_KIND]->Get_Kab(iNode, jNode);
-
- for (iDim = 0; iDim < nDim; iDim++){
- for (jDim = 0; jDim < nDim; jDim++){
- Jacobian_ij[iDim][jDim] = Kab[iDim*nDim+jDim];
- }
- }
-
- StiffMatrix.AddBlock(indexNode[iNode], indexNode[jNode], Jacobian_ij);
-
- }
-
- }
-
- }
-
-}
-
-
-void CElasticityMovement::Set_Element_Stiffness(su2double ElemVolume, CConfig *config) {
-
- switch (config->GetDeform_Stiffness_Type()) {
- case INVERSE_VOLUME:
- E = 1.0 / ElemVolume; // Stiffness inverse of the volume of the element
- Nu = config->GetDeform_Coeff(); // Nu is normally a very large number, for rigid-body rotations, see Dwight (2009)
- break;
- case SOLID_WALL_DISTANCE:
- SU2_MPI::Error("SOLID_WALL DISTANCE METHOD NOT YET IMPLEMENTED FOR THIS APPROACH!!", CURRENT_FUNCTION);
- break;
- case CONSTANT_STIFFNESS:
- E = config->GetDeform_ElasticityMod();
- Nu = config->GetDeform_PoissonRatio();
- break;
- }
-
- /*--- Lamé parameters ---*/
-
- Mu = E / (2.0*(1.0 + Nu));
- Lambda = Nu*E/((1.0+Nu)*(1.0-2.0*Nu));
-
-}
-
-
-void CElasticityMovement::Compute_Element_Contribution(CElement *element, CConfig *config){
-
- unsigned short iVar, jVar, kVar;
- unsigned short iGauss, nGauss;
- unsigned short iNode, jNode, nNode;
- unsigned short iDim;
- unsigned short bDim;
-
- su2double Weight, Jac_X;
-
- su2double AuxMatrix[3][6];
-
- /*--- Initialize auxiliary matrices ---*/
-
- if (nDim == 2) bDim = 3;
- else bDim = 6;
-
- for (iVar = 0; iVar < bDim; iVar++){
- for (jVar = 0; jVar < nDim; jVar++){
- Ba_Mat[iVar][jVar] = 0.0;
- Bb_Mat[iVar][jVar] = 0.0;
- }
- }
-
- for (iVar = 0; iVar < 3; iVar++){
- for (jVar = 0; jVar < 6; jVar++){
- AuxMatrix[iVar][jVar] = 0.0;
- }
- }
-
- element->ClearElement(); /*--- Restarts the element: avoids adding over previous results in other elements --*/
- element->ComputeGrad_Linear();
- nNode = element->GetnNodes();
- nGauss = element->GetnGaussPoints();
-
- /*--- Compute the constitutive matrix (D_Mat) for the element - it only depends on lambda and mu, constant for the element ---*/
- Compute_Constitutive_Matrix();
-
- for (iGauss = 0; iGauss < nGauss; iGauss++){
-
- Weight = element->GetWeight(iGauss);
- Jac_X = element->GetJ_X(iGauss);
-
- /*--- Retrieve the values of the gradients of the shape functions for each node ---*/
- /*--- This avoids repeated operations ---*/
- for (iNode = 0; iNode < nNode; iNode++){
- for (iDim = 0; iDim < nDim; iDim++){
- GradNi_Ref_Mat[iNode][iDim] = element->GetGradNi_X(iNode,iGauss,iDim);
- }
- }
-
- for (iNode = 0; iNode < nNode; iNode++){
-
- if (nDim == 2){
- Ba_Mat[0][0] = GradNi_Ref_Mat[iNode][0];
- Ba_Mat[1][1] = GradNi_Ref_Mat[iNode][1];
- Ba_Mat[2][0] = GradNi_Ref_Mat[iNode][1];
- Ba_Mat[2][1] = GradNi_Ref_Mat[iNode][0];
- }
- else if (nDim == 3){
- Ba_Mat[0][0] = GradNi_Ref_Mat[iNode][0];
- Ba_Mat[1][1] = GradNi_Ref_Mat[iNode][1];
- Ba_Mat[2][2] = GradNi_Ref_Mat[iNode][2];
- Ba_Mat[3][0] = GradNi_Ref_Mat[iNode][1];
- Ba_Mat[3][1] = GradNi_Ref_Mat[iNode][0];
- Ba_Mat[4][0] = GradNi_Ref_Mat[iNode][2];
- Ba_Mat[4][2] = GradNi_Ref_Mat[iNode][0];
- Ba_Mat[5][1] = GradNi_Ref_Mat[iNode][2];
- Ba_Mat[5][2] = GradNi_Ref_Mat[iNode][1];
- }
-
- /*--- Compute the BT.D Matrix ---*/
-
- for (iVar = 0; iVar < nDim; iVar++){
- for (jVar = 0; jVar < bDim; jVar++){
- AuxMatrix[iVar][jVar] = 0.0;
- for (kVar = 0; kVar < bDim; kVar++){
- AuxMatrix[iVar][jVar] += Ba_Mat[kVar][iVar]*D_Mat[kVar][jVar];
- }
- }
- }
-
- /*--- Assumming symmetry ---*/
- for (jNode = iNode; jNode < nNode; jNode++){
- if (nDim == 2){
- Bb_Mat[0][0] = GradNi_Ref_Mat[jNode][0];
- Bb_Mat[1][1] = GradNi_Ref_Mat[jNode][1];
- Bb_Mat[2][0] = GradNi_Ref_Mat[jNode][1];
- Bb_Mat[2][1] = GradNi_Ref_Mat[jNode][0];
- }
- else if (nDim ==3){
- Bb_Mat[0][0] = GradNi_Ref_Mat[jNode][0];
- Bb_Mat[1][1] = GradNi_Ref_Mat[jNode][1];
- Bb_Mat[2][2] = GradNi_Ref_Mat[jNode][2];
- Bb_Mat[3][0] = GradNi_Ref_Mat[jNode][1];
- Bb_Mat[3][1] = GradNi_Ref_Mat[jNode][0];
- Bb_Mat[4][0] = GradNi_Ref_Mat[jNode][2];
- Bb_Mat[4][2] = GradNi_Ref_Mat[jNode][0];
- Bb_Mat[5][1] = GradNi_Ref_Mat[jNode][2];
- Bb_Mat[5][2] = GradNi_Ref_Mat[jNode][1];
- }
-
- for (iVar = 0; iVar < nDim; iVar++){
- for (jVar = 0; jVar < nDim; jVar++){
- KAux_ab[iVar][jVar] = 0.0;
- for (kVar = 0; kVar < bDim; kVar++){
- KAux_ab[iVar][jVar] += Weight * AuxMatrix[iVar][kVar] * Bb_Mat[kVar][jVar] * Jac_X;
- }
- }
- }
-
- element->Add_Kab(iNode, jNode, KAux_ab);
- /*--- Symmetric terms --*/
- if (iNode != jNode){
- element->Add_Kab_T(jNode, iNode, KAux_ab);
- }
-
- }
-
- }
-
- }
-
-}
-
-void CElasticityMovement::Compute_Constitutive_Matrix(void){
-
- /*--- Compute the D Matrix (for plane strain and 3-D)---*/
-
- if (nDim == 2){
-
- /*--- Assuming plane strain ---*/
- D_Mat[0][0] = Lambda + 2.0*Mu; D_Mat[0][1] = Lambda; D_Mat[0][2] = 0.0;
- D_Mat[1][0] = Lambda; D_Mat[1][1] = Lambda + 2.0*Mu; D_Mat[1][2] = 0.0;
- D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = Mu;
-
- }
- else if (nDim == 3){
-
- D_Mat[0][0] = Lambda + 2.0*Mu; D_Mat[0][1] = Lambda; D_Mat[0][2] = Lambda; D_Mat[0][3] = 0.0; D_Mat[0][4] = 0.0; D_Mat[0][5] = 0.0;
- D_Mat[1][0] = Lambda; D_Mat[1][1] = Lambda + 2.0*Mu; D_Mat[1][2] = Lambda; D_Mat[1][3] = 0.0; D_Mat[1][4] = 0.0; D_Mat[1][5] = 0.0;
- D_Mat[2][0] = Lambda; D_Mat[2][1] = Lambda; D_Mat[2][2] = Lambda + 2.0*Mu; D_Mat[2][3] = 0.0; D_Mat[2][4] = 0.0; D_Mat[2][5] = 0.0;
- D_Mat[3][0] = 0.0; D_Mat[3][1] = 0.0; D_Mat[3][2] = 0.0; D_Mat[3][3] = Mu; D_Mat[3][4] = 0.0; D_Mat[3][5] = 0.0;
- D_Mat[4][0] = 0.0; D_Mat[4][1] = 0.0; D_Mat[4][2] = 0.0; D_Mat[4][3] = 0.0; D_Mat[4][4] = Mu; D_Mat[4][5] = 0.0;
- D_Mat[5][0] = 0.0; D_Mat[5][1] = 0.0; D_Mat[5][2] = 0.0; D_Mat[5][3] = 0.0; D_Mat[5][4] = 0.0; D_Mat[5][5] = Mu;
-
- }
-
-}
-
-void CElasticityMovement::Transfer_Boundary_Displacements(CGeometry *geometry, CConfig *config, unsigned short val_marker){
-
- unsigned short iDim;
- unsigned long iNode, iVertex;
-
- su2double *VarCoord;
- su2double new_coord;
-
- for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
-
- /*--- Get node index ---*/
-
- iNode = geometry->vertex[val_marker][iVertex]->GetNode();
-
- /*--- Get the displacement on the vertex ---*/
-
- VarCoord = geometry->vertex[val_marker][iVertex]->GetVarCoord();
-
- if (geometry->node[iNode]->GetDomain()) {
-
- /*--- Update the grid coordinates using the solution of the structural problem
- *--- recorded in VarCoord. */
-
- for (iDim = 0; iDim < nDim; iDim++) {
- new_coord = geometry->node[iNode]->GetCoord(iDim)+VarCoord[iDim];
- if (fabs(new_coord) < EPS*EPS) new_coord = 0.0;
- geometry->node[iNode]->SetCoord(iDim, new_coord);
- }
- }
-
- }
-
-}
-
-void CElasticityMovement::Boundary_Dependencies(CGeometry **geometry, CConfig *config){
-
-
- unsigned short iMarker;
-
- /*--- Get the SU2 module. SU2_CFD will use this routine for dynamically
- deforming meshes (MARKER_FSI_INTERFACE). ---*/
-
- unsigned short Kind_SU2 = config->GetKind_SU2();
-
- /*--- Set the dependencies on the FSI interfaces. ---*/
-
- for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if ((config->GetMarker_All_ZoneInterface(iMarker) != 0) && (Kind_SU2 == SU2_CFD)) {
- Transfer_Boundary_Displacements(geometry[MESH_0], config, iMarker);
- }
- }
-
- UpdateDualGrid(geometry[MESH_0], config);
-
-}
-
-
CFreeFormBlending::CFreeFormBlending(){}
CFreeFormBlending::~CFreeFormBlending(){}
diff --git a/Common/src/interface_interpolation/CInterpolator.cpp b/Common/src/interface_interpolation/CInterpolator.cpp
new file mode 100644
index 000000000000..977fe378a621
--- /dev/null
+++ b/Common/src/interface_interpolation/CInterpolator.cpp
@@ -0,0 +1,404 @@
+/*!
+ * \file CInterpolator.cpp
+ * \brief Definition of the base class for interface interpolation.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CInterpolator.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+
+
+CInterpolator::CInterpolator(CGeometry ****geometry_container, const CConfig* const* config,
+ unsigned int iZone, unsigned int jZone) :
+ rank(SU2_MPI::GetRank()),
+ size(SU2_MPI::GetSize()),
+ donorZone(iZone),
+ targetZone(jZone),
+ Geometry(geometry_container),
+ donor_geometry(geometry_container[iZone][INST_0][MESH_0]),
+ target_geometry(geometry_container[jZone][INST_0][MESH_0]) {
+}
+
+int CInterpolator::FindInterfaceMarker(const CConfig *config, unsigned short val_marker_interface) {
+
+ for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ /*--- If the tag GetMarker_All_ZoneInterface(iMarker) equals the interface we are looking for. ---*/
+ if (config->GetMarker_All_ZoneInterface(iMarker) == val_marker_interface) return iMarker;
+ }
+ return -1;
+}
+
+bool CInterpolator::CheckInterfaceBoundary(int markDonor, int markTarget) {
+
+ /*--- Determine whether the boundary is not on the rank because of
+ * the partition or because it is not part of the zone. ---*/
+ int donorCheck = -1, targetCheck = -1;
+ SU2_MPI::Allreduce(&markDonor, &donorCheck, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&markTarget, &targetCheck, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
+ return (donorCheck != -1) && (targetCheck != -1);
+}
+
+bool CInterpolator::CheckZonesInterface(const CConfig* donor, const CConfig* target) {
+
+ /*--- Loop over all interface markers to find if the 2 zones share any interface boundary. ---*/
+ for (auto iInter = 1u; iInter <= (donor->GetMarker_n_ZoneInterface()/2); iInter++) {
+ if (CheckInterfaceBoundary(FindInterfaceMarker(donor, iInter), FindInterfaceMarker(target, iInter)))
+ return true;
+ }
+ return false;
+}
+
+void CInterpolator::Determine_ArraySize(int markDonor, int markTarget,
+ unsigned long nVertexDonor, unsigned short nDim) {
+
+ /*--- Count donor vertices. ---*/
+ auto nLocalVertex_Donor = 0ul;
+ for (auto iVertex = 0ul; iVertex < nVertexDonor; iVertex++) {
+ auto iPointDonor = donor_geometry->vertex[markDonor][iVertex]->GetNode();
+ nLocalVertex_Donor += donor_geometry->node[iPointDonor]->GetDomain();
+ }
+
+ Buffer_Send_nVertex_Donor[0] = nLocalVertex_Donor;
+
+ /*--- Send Interface vertex information --*/
+ SU2_MPI::Allreduce(&nLocalVertex_Donor, &MaxLocalVertex_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_nVertex_Donor, 1, MPI_UNSIGNED_LONG,
+ Buffer_Receive_nVertex_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+}
+
+void CInterpolator::Collect_VertexInfo(int markDonor, int markTarget,
+ unsigned long nVertexDonor, unsigned short nDim) {
+
+ unsigned long iVertex;
+ unsigned short iDim;
+
+ for (iVertex = 0; iVertex < MaxLocalVertex_Donor; iVertex++) Buffer_Send_GlobalPoint[iVertex] = -1;
+
+ for (iVertex = 0; iVertex < MaxLocalVertex_Donor*nDim; iVertex++) Buffer_Send_Coord[iVertex] = 0.0;
+
+ /*--- Copy coordinates and point to the auxiliar vector --*/
+ auto iLocalVertexDonor = 0ul;
+
+ for (iVertex = 0; iVertex < nVertexDonor; iVertex++) {
+ auto iPointDonor = donor_geometry->vertex[markDonor][iVertex]->GetNode();
+ if (donor_geometry->node[iPointDonor]->GetDomain()) {
+ Buffer_Send_GlobalPoint[iLocalVertexDonor] = donor_geometry->node[iPointDonor]->GetGlobalIndex();
+ for (iDim = 0; iDim < nDim; iDim++)
+ Buffer_Send_Coord[iLocalVertexDonor*nDim+iDim] = donor_geometry->node[iPointDonor]->GetCoord(iDim);
+ iLocalVertexDonor++;
+ }
+ }
+ auto nBuffer_Coord = MaxLocalVertex_Donor*nDim;
+ auto nBuffer_Point = MaxLocalVertex_Donor;
+
+ SU2_MPI::Allgather(Buffer_Send_Coord, nBuffer_Coord, MPI_DOUBLE,
+ Buffer_Receive_Coord, nBuffer_Coord, MPI_DOUBLE, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_GlobalPoint, nBuffer_Point, MPI_LONG,
+ Buffer_Receive_GlobalPoint, nBuffer_Point, MPI_LONG, MPI_COMM_WORLD);
+}
+
+unsigned long CInterpolator::Collect_ElementInfo(int markDonor, unsigned short nDim, bool compress,
+ vector& allNumElem, vector& numNodes,
+ su2matrix& idxNodes) const {
+
+ const auto maxElemNodes = (nDim == 2u)? 2u : 4u; // line and quad respectively
+
+ unsigned long nElemDonor = 0;
+ if (markDonor != -1) nElemDonor = donor_geometry->GetnElem_Bound(markDonor);
+
+ allNumElem.resize(size);
+ SU2_MPI::Allgather(&nElemDonor, 1, MPI_UNSIGNED_LONG, allNumElem.data(), 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+
+ auto nMaxElemDonor = *max_element(allNumElem.begin(), allNumElem.end());
+
+ vector bufferSendNum(nMaxElemDonor);
+ su2matrix bufferSendIdx(nMaxElemDonor, maxElemNodes);
+
+ numNodes.resize(nMaxElemDonor*size);
+ idxNodes.resize(nMaxElemDonor*size, maxElemNodes);
+
+ for (auto iElem = 0ul; iElem < nElemDonor; ++iElem) {
+
+ const auto nNode = donor_geometry->bound[markDonor][iElem]->GetnNodes();
+ bufferSendNum[iElem] = nNode;
+ assert(nNode <= maxElemNodes && "Donor element has too many nodes.");
+
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
+ auto iPoint = donor_geometry->bound[markDonor][iElem]->GetNode(iNode);
+ auto iPointGlobal = donor_geometry->node[iPoint]->GetGlobalIndex();
+ bufferSendIdx(iElem, iNode) = iPointGlobal;
+ }
+ }
+
+ SU2_MPI::Allgather(bufferSendNum.data(), bufferSendNum.size(), MPI_UNSIGNED_SHORT,
+ numNodes.data(), bufferSendNum.size(), MPI_UNSIGNED_SHORT, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(bufferSendIdx.data(), bufferSendIdx.size(), MPI_LONG,
+ idxNodes.data(), bufferSendIdx.size(), MPI_LONG, MPI_COMM_WORLD);
+
+ if (!compress)
+ return accumulate(allNumElem.begin(), allNumElem.end(), 0ul);
+
+ /*--- Compress the information (overlapping copy do not use memcpy). ---*/
+
+ unsigned long dstIdx = 0;
+ for (int iProcessor = 0; iProcessor < size; ++iProcessor) {
+ auto srcOffset = iProcessor * nMaxElemDonor;
+ for (auto idx = 0u; idx < allNumElem[iProcessor]; ++idx) {
+ numNodes[dstIdx] = numNodes[srcOffset+idx];
+ for (auto iNode = 0u; iNode < maxElemNodes; ++iNode)
+ idxNodes(dstIdx, iNode) = idxNodes(srcOffset+idx, iNode);
+ ++dstIdx;
+ }
+ }
+
+ return dstIdx;
+}
+
+void CInterpolator::ReconstructBoundary(unsigned long val_zone, int val_marker){
+
+ CGeometry *geom = Geometry[val_zone][INST_0][MESH_0];
+
+ unsigned long iVertex, jVertex, kVertex;
+
+ unsigned long count, iTmp, *uptr, dPoint, EdgeIndex, jEdge, nEdges, nNodes, nVertex, iDim, nDim, iPoint;
+
+ unsigned long nGlobalLinkedNodes, nLocalVertex, nLocalLinkedNodes;
+
+ nDim = geom->GetnDim();
+
+ if( val_marker != -1 )
+ nVertex = geom->GetnVertex( val_marker );
+ else
+ nVertex = 0;
+
+
+ su2double *Buffer_Send_Coord = new su2double [ nVertex * nDim ];
+ unsigned long *Buffer_Send_GlobalPoint = new unsigned long [ nVertex ];
+
+ unsigned long *Buffer_Send_nLinkedNodes = new unsigned long [ nVertex ];
+ unsigned long *Buffer_Send_StartLinkedNodes = new unsigned long [ nVertex ];
+ unsigned long **Aux_Send_Map = new unsigned long*[ nVertex ];
+
+#ifdef HAVE_MPI
+ int nProcessor = size, iRank;
+ unsigned long iTmp2, tmp_index, tmp_index_2;
+#endif
+
+ /*--- Copy coordinates and point to the auxiliar vector ---*/
+
+ nGlobalVertex = 0;
+ nLocalVertex = 0;
+ nLocalLinkedNodes = 0;
+
+ for (iVertex = 0; iVertex < nVertex; iVertex++) {
+
+ Buffer_Send_nLinkedNodes[iVertex] = 0;
+ Aux_Send_Map[iVertex] = NULL;
+
+ iPoint = geom->vertex[val_marker][iVertex]->GetNode();
+
+ if (geom->node[iPoint]->GetDomain()) {
+ Buffer_Send_GlobalPoint[nLocalVertex] = geom->node[iPoint]->GetGlobalIndex();
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ Buffer_Send_Coord[nLocalVertex*nDim+iDim] = geom->node[iPoint]->GetCoord(iDim);
+
+ nNodes = 0;
+ nEdges = geom->node[iPoint]->GetnPoint();
+
+ for (jEdge = 0; jEdge < nEdges; jEdge++){
+ EdgeIndex = geom->node[iPoint]->GetEdge(jEdge);
+
+ if( iPoint == geom->edge[EdgeIndex]->GetNode(0) )
+ dPoint = geom->edge[EdgeIndex]->GetNode(1);
+ else
+ dPoint = geom->edge[EdgeIndex]->GetNode(0);
+
+ if ( geom->node[dPoint]->GetVertex(val_marker) != -1 )
+ nNodes++;
+ }
+
+ Buffer_Send_StartLinkedNodes[nLocalVertex] = nLocalLinkedNodes;
+ Buffer_Send_nLinkedNodes[nLocalVertex] = nNodes;
+
+ nLocalLinkedNodes += nNodes;
+
+ Aux_Send_Map[nLocalVertex] = new unsigned long[ nNodes ];
+ nNodes = 0;
+
+ for (jEdge = 0; jEdge < nEdges; jEdge++){
+ EdgeIndex = geom->node[iPoint]->GetEdge(jEdge);
+
+ if( iPoint == geom->edge[EdgeIndex]->GetNode(0) )
+ dPoint = geom->edge[EdgeIndex]->GetNode(1);
+ else
+ dPoint = geom->edge[EdgeIndex]->GetNode(0);
+
+ if ( geom->node[dPoint]->GetVertex(val_marker) != -1 ){
+ Aux_Send_Map[nLocalVertex][nNodes] = geom->node[dPoint]->GetGlobalIndex();
+ nNodes++;
+ }
+ }
+ nLocalVertex++;
+ }
+ }
+
+ unsigned long *Buffer_Send_LinkedNodes = new unsigned long [ nLocalLinkedNodes ];
+
+ nLocalLinkedNodes = 0;
+
+ for (iVertex = 0; iVertex < nLocalVertex; iVertex++){
+ for (jEdge = 0; jEdge < Buffer_Send_nLinkedNodes[iVertex]; jEdge++){
+ Buffer_Send_LinkedNodes[nLocalLinkedNodes] = Aux_Send_Map[iVertex][jEdge];
+ nLocalLinkedNodes++;
+ }
+ }
+
+ for (iVertex = 0; iVertex < nVertex; iVertex++){
+ if( Aux_Send_Map[iVertex] != NULL )
+ delete [] Aux_Send_Map[iVertex];
+ }
+ delete [] Aux_Send_Map; Aux_Send_Map = NULL;
+
+ /*--- Reconstruct boundary by gathering data from all ranks ---*/
+
+ SU2_MPI::Allreduce( &nLocalVertex, &nGlobalVertex, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&nLocalLinkedNodes, &nGlobalLinkedNodes, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+
+ Buffer_Receive_Coord = new su2double [ nGlobalVertex * nDim ];
+ Buffer_Receive_GlobalPoint = new long[ nGlobalVertex ];
+ Buffer_Receive_Proc = new unsigned long[ nGlobalVertex ];
+
+ Buffer_Receive_nLinkedNodes = new unsigned long[ nGlobalVertex ];
+ Buffer_Receive_LinkedNodes = new unsigned long[ nGlobalLinkedNodes ];
+ Buffer_Receive_StartLinkedNodes = new unsigned long[ nGlobalVertex ];
+
+#ifdef HAVE_MPI
+ if (rank == MASTER_NODE){
+
+ for (iVertex = 0; iVertex < nDim*nLocalVertex; iVertex++)
+ Buffer_Receive_Coord[iVertex] = Buffer_Send_Coord[iVertex];
+
+ for (iVertex = 0; iVertex < nLocalVertex; iVertex++){
+ Buffer_Receive_GlobalPoint[iVertex] = Buffer_Send_GlobalPoint[iVertex];
+ Buffer_Receive_Proc[iVertex] = MASTER_NODE;
+ Buffer_Receive_nLinkedNodes[iVertex] = Buffer_Send_nLinkedNodes[iVertex];
+ Buffer_Receive_StartLinkedNodes[iVertex] = Buffer_Send_StartLinkedNodes[iVertex];
+ }
+
+ for (iVertex = 0; iVertex < nLocalLinkedNodes; iVertex++)
+ Buffer_Receive_LinkedNodes[iVertex] = Buffer_Send_LinkedNodes[iVertex];
+
+ tmp_index = nLocalVertex;
+ tmp_index_2 = nLocalLinkedNodes;
+
+ for(iRank = 1; iRank < nProcessor; iRank++){
+
+ SU2_MPI::Recv( &iTmp2, 1, MPI_UNSIGNED_LONG, iRank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+ SU2_MPI::Recv(&Buffer_Receive_LinkedNodes[tmp_index_2], iTmp2, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+ SU2_MPI::Recv( &iTmp, 1, MPI_UNSIGNED_LONG, iRank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+ SU2_MPI::Recv(&Buffer_Receive_Coord[tmp_index*nDim], nDim*iTmp, MPI_DOUBLE, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+ SU2_MPI::Recv( &Buffer_Receive_GlobalPoint[tmp_index], iTmp, MPI_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+ SU2_MPI::Recv( &Buffer_Receive_nLinkedNodes[tmp_index], iTmp, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+ SU2_MPI::Recv(&Buffer_Receive_StartLinkedNodes[tmp_index], iTmp, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+ for (iVertex = 0; iVertex < iTmp; iVertex++){
+ Buffer_Receive_Proc[ tmp_index + iVertex ] = iRank;
+ Buffer_Receive_StartLinkedNodes[ tmp_index + iVertex ] += tmp_index_2;
+ }
+
+ tmp_index += iTmp;
+ tmp_index_2 += iTmp2;
+ }
+ }
+ else{
+ SU2_MPI::Send( &nLocalLinkedNodes, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
+ SU2_MPI::Send(Buffer_Send_LinkedNodes, nLocalLinkedNodes, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
+
+ SU2_MPI::Send( &nLocalVertex, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
+ SU2_MPI::Send(Buffer_Send_Coord, nDim * nLocalVertex, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
+
+ SU2_MPI::Send( Buffer_Send_GlobalPoint, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
+ SU2_MPI::Send( Buffer_Send_nLinkedNodes, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
+ SU2_MPI::Send(Buffer_Send_StartLinkedNodes, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
+ }
+#else
+ for (iVertex = 0; iVertex < nDim * nGlobalVertex; iVertex++)
+ Buffer_Receive_Coord[iVertex] = Buffer_Send_Coord[iVertex];
+
+ for (iVertex = 0; iVertex < nGlobalVertex; iVertex++){
+ Buffer_Receive_GlobalPoint[iVertex] = Buffer_Send_GlobalPoint[iVertex];
+ Buffer_Receive_Proc[iVertex] = MASTER_NODE;
+ Buffer_Receive_nLinkedNodes[iVertex] = Buffer_Send_nLinkedNodes[iVertex];
+ Buffer_Receive_StartLinkedNodes[iVertex] = Buffer_Send_StartLinkedNodes[iVertex];
+ }
+
+ for (iVertex = 0; iVertex < nGlobalLinkedNodes; iVertex++)
+ Buffer_Receive_LinkedNodes[iVertex] = Buffer_Send_LinkedNodes[iVertex];
+#endif
+
+ if (rank == MASTER_NODE){
+ for (iVertex = 0; iVertex < nGlobalVertex; iVertex++){
+ count = 0;
+ uptr = &Buffer_Receive_LinkedNodes[ Buffer_Receive_StartLinkedNodes[iVertex] ];
+
+ for (jVertex = 0; jVertex < Buffer_Receive_nLinkedNodes[iVertex]; jVertex++){
+ iTmp = uptr[ jVertex ];
+ for (kVertex = 0; kVertex < nGlobalVertex; kVertex++){
+ if( Buffer_Receive_GlobalPoint[kVertex] == long(iTmp) ){
+ uptr[ jVertex ] = kVertex;
+ count++;
+ break;
+ }
+ }
+
+ if( count != (jVertex+1) ){
+ for (kVertex = jVertex; kVertex < Buffer_Receive_nLinkedNodes[iVertex]-1; kVertex++){
+ uptr[ kVertex ] = uptr[ kVertex + 1];
+ }
+ Buffer_Receive_nLinkedNodes[iVertex]--;
+ jVertex--;
+ }
+ }
+ }
+ }
+
+ SU2_MPI::Bcast(Buffer_Receive_GlobalPoint, nGlobalVertex, MPI_LONG, 0, MPI_COMM_WORLD);
+ SU2_MPI::Bcast(Buffer_Receive_Coord, nGlobalVertex*nDim, MPI_DOUBLE, 0, MPI_COMM_WORLD);
+ SU2_MPI::Bcast(Buffer_Receive_Proc, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+
+ SU2_MPI::Bcast(Buffer_Receive_nLinkedNodes, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+ SU2_MPI::Bcast(Buffer_Receive_StartLinkedNodes, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+ SU2_MPI::Bcast(Buffer_Receive_LinkedNodes, nGlobalLinkedNodes, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+
+ delete [] Buffer_Send_Coord; Buffer_Send_Coord = NULL;
+ delete [] Buffer_Send_GlobalPoint; Buffer_Send_GlobalPoint = NULL;
+ delete [] Buffer_Send_LinkedNodes; Buffer_Send_LinkedNodes = NULL;
+ delete [] Buffer_Send_nLinkedNodes; Buffer_Send_nLinkedNodes = NULL;
+ delete [] Buffer_Send_StartLinkedNodes; Buffer_Send_StartLinkedNodes = NULL;
+
+}
diff --git a/Common/src/interface_interpolation/CInterpolatorFactory.cpp b/Common/src/interface_interpolation/CInterpolatorFactory.cpp
new file mode 100644
index 000000000000..7a02ebabb1a7
--- /dev/null
+++ b/Common/src/interface_interpolation/CInterpolatorFactory.cpp
@@ -0,0 +1,90 @@
+/*!
+ * \file CInterpolatorFactory.cpp
+ * \brief Factory to generate interpolator objects.
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/CConfig.hpp"
+
+#include "../../include/interface_interpolation/CInterpolatorFactory.hpp"
+#include "../../include/interface_interpolation/CIsoparametric.hpp"
+#include "../../include/interface_interpolation/CMirror.hpp"
+#include "../../include/interface_interpolation/CNearestNeighbor.hpp"
+#include "../../include/interface_interpolation/CRadialBasisFunction.hpp"
+#include "../../include/interface_interpolation/CSlidingMesh.hpp"
+
+namespace CInterpolatorFactory {
+CInterpolator* createInterpolator(CGeometry ****geometry_container,
+ const CConfig* const* config,
+ unsigned iZone, unsigned jZone, bool verbose) {
+
+ CInterpolator* interpolator = nullptr;
+
+ /*--- Only print information on master node. ---*/
+ verbose &= (SU2_MPI::GetRank() == MASTER_NODE);
+
+ /*--- Type of interpolation defined by donor. ---*/
+ const auto type = config[iZone]->GetKindInterpolation();
+
+ if (verbose) cout << " Setting coupling ";
+
+ /*--- Conservative interpolation is not applicable to the sliding
+ * mesh approach so that case is handled first. Then we either
+ * return a CMirror if the target requires conservative inter-
+ * polation, or the type of interpolator defined by "type". ---*/
+
+ if (type == WEIGHTED_AVERAGE) {
+ if (verbose) cout << "using a sliding mesh approach." << endl;
+ interpolator = new CSlidingMesh(geometry_container, config, iZone, jZone);
+ }
+ else if (config[jZone]->GetConservativeInterpolation()) {
+ if (verbose) cout << "using a mirror approach, \"transposing\" coefficients from opposite mesh." << endl;
+ interpolator = new CMirror(geometry_container, config, iZone, jZone);
+ }
+ else {
+ switch(type) {
+ case ISOPARAMETRIC:
+ if (verbose) cout << "using the isoparametric approach." << endl;
+ interpolator = new CIsoparametric(geometry_container, config, iZone, jZone);
+ break;
+
+ case NEAREST_NEIGHBOR:
+ if (verbose) cout << "using a nearest-neighbor approach." << endl;
+ interpolator = new CNearestNeighbor(geometry_container, config, iZone, jZone);
+ break;
+
+ case RADIAL_BASIS_FUNCTION:
+ if (verbose) cout << "using a radial basis function approach." << endl;
+ interpolator = new CRadialBasisFunction(geometry_container, config, iZone, jZone);
+ break;
+
+ default:
+ SU2_MPI::Error("Unknown type of interpolation.", CURRENT_FUNCTION);
+ }
+ }
+
+ if (verbose) interpolator->PrintStatistics();
+
+ return interpolator;
+}
+} // end namespace
diff --git a/Common/src/interface_interpolation/CIsoparametric.cpp b/Common/src/interface_interpolation/CIsoparametric.cpp
new file mode 100644
index 000000000000..9a6fc0934dc3
--- /dev/null
+++ b/Common/src/interface_interpolation/CIsoparametric.cpp
@@ -0,0 +1,451 @@
+/*!
+ * \file CIsoparametric.cpp
+ * \brief Implementation isoparametric interpolation (using FE shape functions).
+ * \author P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CIsoparametric.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+#include "../../include/geometry/elements/CElement.hpp"
+#include "../../include/toolboxes/geometry_toolbox.hpp"
+#include
+
+using namespace GeometryToolbox;
+
+
+/*! \brief Helper struct to store information about candidate donor elements. */
+struct DonorInfo {
+ su2double isoparams[4] = {0.0}; /*!< \brief Interpolation coefficients. */
+ su2double distance = 0.0; /*!< \brief Distance from target to final mapped point on donor plane. */
+ su2double checkSum = 0.0; /*!< \brief Sum of absolute coefficients (should be 1). */
+ unsigned iElem = 0; /*!< \brief Identification of the element. */
+ int error = 0; /*!< \brief If the mapped point is "outside" of the donor. */
+
+ bool operator< (const DonorInfo& other) const {
+ /*--- Best donor is one for which the mapped point is within bounds and closest to target. ---*/
+ return (fabs(checkSum-other.checkSum)<1e-6)? (distance < other.distance) : (checkSum < other.checkSum);
+ }
+};
+
+CIsoparametric::CIsoparametric(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone,
+ unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
+ SetTransferCoeff(config);
+}
+
+void CIsoparametric::PrintStatistics(void) const {
+ if (rank != MASTER_NODE) return;
+ cout << " Maximum distance to closest donor element: " << MaxDistance << ".\n"
+ << " Interpolation mitigated for " << ErrorCounter << " (" << ErrorRate << "%) target vertices." << endl;
+}
+
+void CIsoparametric::SetTransferCoeff(const CConfig* const* config) {
+
+ const int nProcessor = size;
+ const auto nMarkerInt = config[donorZone]->GetMarker_n_ZoneInterface()/2;
+ const auto nDim = donor_geometry->GetnDim();
+
+ Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
+
+ /*--- Init stats. ---*/
+ MaxDistance = 0.0; ErrorCounter = 0;
+ unsigned long nGlobalVertexTarget = 0;
+
+ /*--- Cycle over nMarkersInt interface to determine communication pattern. ---*/
+
+ for (unsigned short iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
+
+ /* High level procedure:
+ * - Loop through vertices of the target grid;
+ * - Find nearest element;
+ * - Compute and set the transfer coefficients.
+ */
+
+ /*--- On the donor side: find the tag of the boundary sharing the interface. ---*/
+ const auto markDonor = FindInterfaceMarker(config[donorZone], iMarkerInt);
+
+ /*--- On the target side: find the tag of the boundary sharing the interface. ---*/
+ const auto markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt);
+
+ /*--- Checks if the zone contains the interface, if not continue to the next step. ---*/
+ if (!CheckInterfaceBoundary(markDonor, markTarget)) continue;
+
+ unsigned long nVertexDonor = 0, nVertexTarget = 0;
+ if (markDonor != -1) nVertexDonor = donor_geometry->GetnVertex(markDonor);
+ if (markTarget != -1) nVertexTarget = target_geometry->GetnVertex(markTarget);
+
+ /*--- Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor. ---*/
+ Determine_ArraySize(markDonor, markTarget, nVertexDonor, nDim);
+
+ const auto nGlobalVertexDonor = accumulate(Buffer_Receive_nVertex_Donor,
+ Buffer_Receive_nVertex_Donor+nProcessor, 0ul);
+
+ Buffer_Send_Coord = new su2double [ MaxLocalVertex_Donor * nDim ];
+ Buffer_Send_GlobalPoint = new long [ MaxLocalVertex_Donor ];
+ Buffer_Receive_Coord = new su2double [ nProcessor * MaxLocalVertex_Donor * nDim ];
+ Buffer_Receive_GlobalPoint = new long [ nProcessor * MaxLocalVertex_Donor ];
+
+ /*--- Collect coordinates and global point indices. ---*/
+ Collect_VertexInfo(markDonor, markTarget, nVertexDonor, nDim);
+
+ /*--- Compress the vertex information, and build a map of global point to "compressed
+ * index" to then reconstruct the donor elements in local index space. ---*/
+
+ su2activematrix donorCoord(nGlobalVertexDonor, nDim);
+ vector donorPoint(nGlobalVertexDonor);
+ vector donorProc(nGlobalVertexDonor);
+ unordered_map globalToLocalMap;
+
+ auto iCount = 0ul;
+ for (int iProcessor = 0; iProcessor < nProcessor; ++iProcessor) {
+ auto offset = iProcessor * MaxLocalVertex_Donor;
+ for (auto iVertex = 0ul; iVertex < Buffer_Receive_nVertex_Donor[iProcessor]; ++iVertex) {
+ for (int iDim = 0; iDim < nDim; ++iDim)
+ donorCoord(iCount,iDim) = Buffer_Receive_Coord[(offset+iVertex)*nDim + iDim];
+ donorPoint[iCount] = Buffer_Receive_GlobalPoint[offset+iVertex];
+ donorProc[iCount] = iProcessor;
+ assert((globalToLocalMap.count(donorPoint[iCount]) == 0) && "Duplicate donor point found.");
+ globalToLocalMap[donorPoint[iCount]] = iCount;
+ ++iCount;
+ }
+ }
+ assert((iCount == nGlobalVertexDonor) && "Global donor point count mismatch.");
+
+ delete[] Buffer_Send_Coord;
+ delete[] Buffer_Send_GlobalPoint;
+ delete[] Buffer_Receive_Coord;
+ delete[] Buffer_Receive_GlobalPoint;
+
+ /*--- Collect donor element (face) information. ---*/
+
+ vector allNumElem;
+ vector elemNumNodes;
+ su2matrix elemIdxNodes;
+
+ const auto nGlobalElemDonor = Collect_ElementInfo(markDonor, nDim, true,
+ allNumElem, elemNumNodes, elemIdxNodes);
+
+ su2activematrix elemCentroid(nGlobalElemDonor, nDim);
+
+ SU2_OMP_PARALLEL
+ {
+ /*--- Compute element centroids to then find the closest one to a given target point. ---*/
+
+ SU2_OMP_FOR_STAT(roundUpDiv(nGlobalElemDonor,omp_get_max_threads()))
+ for (auto iElem = 0u; iElem < nGlobalElemDonor; ++iElem) {
+
+ const auto nNode = elemNumNodes[iElem];
+
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
+ elemCentroid(iElem, iDim) = 0.0;
+
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
+ /*--- Map the node to "local" coordinates. ---*/
+ assert(globalToLocalMap.count(elemIdxNodes(iElem,iNode)) &&
+ "Unknown donor point referenced by donor element.");
+ const auto iVertex = globalToLocalMap.at(elemIdxNodes(iElem,iNode));
+ elemIdxNodes(iElem,iNode) = iVertex;
+
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
+ elemCentroid(iElem, iDim) += donorCoord(iVertex, iDim) / nNode;
+ }
+ }
+
+ /*--- Compute transfer coefficients for each target point. ---*/
+ su2double maxDist = 0.0;
+ unsigned long errorCount = 0, totalCount = 0;
+ vector nearElems(nGlobalElemDonor);
+ vector candidateElems(min(NUM_CANDIDATE_DONORS, nGlobalElemDonor));
+
+ SU2_OMP_FOR_DYN(roundUpDiv(nVertexTarget,2*omp_get_max_threads()))
+ for (auto iVertexTarget = 0u; iVertexTarget < nVertexTarget; ++iVertexTarget) {
+
+ auto target_vertex = target_geometry->vertex[markTarget][iVertexTarget];
+ const auto iPoint = target_vertex->GetNode();
+
+ if (!target_geometry->node[iPoint]->GetDomain()) continue;
+ totalCount += 1;
+
+ /*--- Coordinates of the target point. ---*/
+ const su2double* coord_i = target_geometry->node[iPoint]->GetCoord();
+
+ /*--- Find "n" closest candidate donor elements (the naive way). ---*/
+ iota(nearElems.begin(), nearElems.end(), 0);
+ partial_sort(nearElems.begin(), nearElems.begin()+candidateElems.size(), nearElems.end(),
+ [&](unsigned iElem, unsigned jElem) {
+ return SquaredDistance(nDim, coord_i, elemCentroid[iElem]) <
+ SquaredDistance(nDim, coord_i, elemCentroid[jElem]);
+ }
+ );
+
+ /*--- Evaluate interpolation for the candidates. ---*/
+ for (auto i = 0u; i < candidateElems.size(); ++i) {
+ const auto iElem = nearElems[i];
+
+ /*--- Fetch element info. ---*/
+ auto& candidate = candidateElems[i];
+ candidate.iElem = iElem;
+ const auto nNode = elemNumNodes[iElem];
+ su2double coords[4][3] = {{0.0}};
+
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
+ const auto iVertex = elemIdxNodes(iElem, iNode);
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
+ coords[iNode][iDim] = donorCoord(iVertex,iDim);
+ }
+
+ /*--- Compute the interpolation coefficients. ---*/
+ switch (nNode) {
+ case 2: candidate.error = LineIsoparameters(coords, coord_i, candidate.isoparams); break;
+ case 3: candidate.error = TriangleIsoparameters(coords, coord_i, candidate.isoparams); break;
+ case 4: candidate.error = QuadrilateralIsoparameters(coords, coord_i, candidate.isoparams); break;
+ }
+
+ /*--- Evaluate distance from target to final mapped point. ---*/
+ su2double finalCoord[3] = {0.0};
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
+ for (auto iNode = 0u; iNode < nNode; ++iNode)
+ finalCoord[iDim] += coords[iNode][iDim] * candidate.isoparams[iNode];
+
+ candidate.checkSum = 0.0;
+ for (auto iNode = 0u; iNode < nNode; ++iNode)
+ candidate.checkSum += fabs(candidate.isoparams[iNode]);
+
+ candidate.distance = Distance(nDim, coord_i, finalCoord);
+ if (candidate.distance != candidate.distance) // NaN check
+ candidate.error = 2;
+ }
+
+ /*--- Find best donor. ---*/
+ const auto donor = min_element(candidateElems.begin(), candidateElems.end());
+
+ if (donor->error > 1)
+ SU2_MPI::Error("Isoparametric interpolation failed, NaN detected.", CURRENT_FUNCTION);
+
+ errorCount += donor->error;
+ maxDist = max(maxDist, donor->distance);
+
+ const auto nNode = elemNumNodes[donor->iElem];
+
+ target_vertex->Allocate_DonorInfo(nNode);
+
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
+ const auto iVertex = elemIdxNodes(donor->iElem, iNode);
+ target_vertex->SetDonorCoeff(iNode, donor->isoparams[iNode]);
+ target_vertex->SetInterpDonorPoint(iNode, donorPoint[iVertex]);
+ target_vertex->SetInterpDonorProcessor(iNode, donorProc[iVertex]);
+ }
+
+ }
+ SU2_OMP_CRITICAL
+ {
+ MaxDistance = max(MaxDistance, maxDist);
+ ErrorCounter += errorCount;
+ nGlobalVertexTarget += totalCount;
+ }
+ } // end SU2_OMP_PARALLEL
+
+ } // end nMarkerInt loop
+
+ /*--- Final reduction of statistics. ---*/
+ su2double tmp = MaxDistance;
+ unsigned long tmp1 = ErrorCounter, tmp2 = nGlobalVertexTarget;
+ SU2_MPI::Allreduce(&tmp, &MaxDistance, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&tmp1, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&tmp2, &nGlobalVertexTarget, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+
+ ErrorRate = 100*su2double(ErrorCounter) / nGlobalVertexTarget;
+
+}
+
+int CIsoparametric::LineIsoparameters(const su2double X[][3], const su2double *xj, su2double *isoparams) {
+
+ const su2double extrapTol = 1.5;
+
+ /*--- Project the target point onto the line. ---*/
+
+ su2double normal[2] = {0.0};
+ LineNormal(X, normal);
+ su2double xprj[2] = {0.0};
+ PointPlaneProjection(xj, X[0], normal, xprj);
+
+ su2double l01 = Distance(2, X[0], X[1]);
+ su2double l0j = Distance(2, X[0], xprj);
+ su2double lj1 = Distance(2, xprj, X[1]);
+
+ /*--- Detect out of bounds point. ---*/
+
+ const int outOfBounds = (l0j+lj1) > (extrapTol*l01);
+
+ isoparams[0] = max(1.0-extrapTol, min(lj1/l01, extrapTol));
+ isoparams[1] = 1.0 - isoparams[0];
+
+ return outOfBounds;
+}
+
+int CIsoparametric::TriangleIsoparameters(const su2double X[][3], const su2double *xj, su2double *isoparams) {
+
+ /*--- The isoparameters are the solution to the determined system X^T * isoparams = xj.
+ * This is consistent with the shape functions of the linear triangular element. ---*/
+
+ const su2double extrapTol = -0.5;
+
+ /*--- Project the target point onto the triangle. ---*/
+
+ su2double normal[3] = {0.0};
+ TriangleNormal(X, normal);
+ PointPlaneProjection(xj, X[0], normal, isoparams); // use isoparams as rhs
+
+ su2double A[3][3]; // = X^T
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 3; ++j)
+ A[i][j] = X[j][i];
+
+ /*--- Solve system by in-place Gaussian elimination without pivoting. ---*/
+
+ /*--- Transform system in Upper Matrix. ---*/
+ for (int i = 1; i < 3; ++i) {
+ for (int j = 0; j < i; ++j) {
+ su2double w = A[i][j] / A[j][j];
+ for (int k = j; k < 3; ++k)
+ A[i][k] -= w * A[j][k];
+ isoparams[i] -= w * isoparams[j];
+ }
+ }
+ /*--- Backwards substitution. ---*/
+ for (int i = 2; i >= 0; --i) {
+ for (int j = i+1; j < 3; ++j)
+ isoparams[i] -= A[i][j] * isoparams[j];
+ isoparams[i] /= A[i][i];
+ }
+
+ /*--- Detect out of bounds point. ---*/
+ const int outOfBounds = (isoparams[0] < extrapTol) ||
+ (isoparams[1] < extrapTol) ||
+ (isoparams[2] < extrapTol);
+
+ /*--- Mitigation. ---*/
+ if (outOfBounds) {
+ /*--- Clamp. ---*/
+ su2double sum = 0.0;
+ for (int i = 0; i < 3; ++i) {
+ isoparams[i] = max(isoparams[i], extrapTol);
+ sum += isoparams[i];
+ }
+ /*--- Enforce unit sum. ---*/
+ for (int i = 0; i < 3; ++i)
+ isoparams[i] /= sum;
+ }
+
+ return outOfBounds;
+}
+
+int CIsoparametric::QuadrilateralIsoparameters(const su2double X[][3], const su2double *xj, su2double *isoparams) {
+
+ /*--- The isoparameters are the shape functions (Ni) evaluated at xj, for that we need
+ * the corresponding Xi and Eta, which are obtained by solving the overdetermined
+ * nonlinear system r = xj - X^T * Ni(Xi,Eta) = 0 via the modified Marquardt method.
+ * It is not necessary to project the point as minimizing ||r|| is equivalent. ---*/
+
+ const su2double extrapTol = 3.0;
+
+ constexpr int NITER = 20;
+ const su2double tol = 1e-10, lambda = 0.05;
+
+ su2double Xi = 0.0, Eta = 0.0, eps;
+
+ /*--- Finding Xi and Eta is a "third order" effect that we do not
+ * differentiate (also because we need to iterate). ---*/
+ const bool tapeActive = AD::TapeActive();
+ AD::StopRecording();
+
+ for (int iter = 0; iter < NITER; ++iter) {
+
+ /*--- Evaluate the residual. ---*/
+ su2double r[3] = {xj[0], xj[1], xj[2]};
+ su2double Ni[4] = {0.0};
+ CQUAD4::ShapeFunctions(Xi, Eta, Ni);
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 4; ++j)
+ r[i] -= X[j][i] * Ni[j];
+
+ /*--- Evaluate the residual Jacobian. ---*/
+ su2double dNi[4][2] = {{0.0}};
+ CQUAD4::ShapeFunctionJacobian(Xi, Eta, dNi);
+
+ su2double jac[3][2] = {{0.0}};
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 2; ++j)
+ for (int k = 0; k < 4; ++k)
+ jac[i][j] -= X[k][i] * dNi[k][j];
+
+ /*--- Compute the correction (normal equations and Cramer's rule). ---*/
+ su2double A[2][2] = {{0.0}}, b[2] = {0.0};
+ for (int i = 0; i < 2; ++i) {
+ for (int j = i; j < 2; ++j)
+ for (int k = 0; k < 3; ++k)
+ A[i][j] += jac[k][i] * jac[k][j];
+
+ A[i][i] *= (1.0+lambda);
+
+ for (int k = 0; k < 3; ++k)
+ b[i] += jac[k][i] * r[k];
+ }
+ A[1][0] = A[0][1];
+
+ su2double detA = 1.0 / (A[0][0]*A[1][1] - A[0][1]*A[1][0]);
+ su2double dXi = (b[0]*A[1][1] - b[1]*A[0][1]) * detA;
+ su2double dEta = (A[0][0]*b[1] - A[1][0]*b[0]) * detA;
+ Xi -= dXi;
+ Eta -= dEta;
+
+ eps = fabs(dXi)+fabs(dEta);
+ if (eps < tol) break;
+ }
+
+ if (tapeActive) AD::StartRecording();
+
+ int outOfBounds = 0;
+
+ if (eps > 0.01) {
+ /*--- Iteration diverged, hard fallback. ---*/
+ Xi = Eta = 0.0;
+ outOfBounds = 1;
+ }
+ else {
+ /*--- Check bounds. ---*/
+ outOfBounds = (fabs(Xi) > extrapTol) || (fabs(Eta) > extrapTol);
+
+ /*--- Mitigate by clamping coordinates. ---*/
+ if (outOfBounds) {
+ Xi = max(-extrapTol, min(Xi, extrapTol));
+ Eta = max(-extrapTol, min(Eta, extrapTol));
+ }
+ }
+
+ /*--- Evaluate isoparameters at final Xi and Eta. ---*/
+ CQUAD4::ShapeFunctions(Xi, Eta, isoparams);
+
+ return outOfBounds;
+}
diff --git a/Common/src/interface_interpolation/CMirror.cpp b/Common/src/interface_interpolation/CMirror.cpp
new file mode 100644
index 000000000000..88d65c24c92e
--- /dev/null
+++ b/Common/src/interface_interpolation/CMirror.cpp
@@ -0,0 +1,200 @@
+/*!
+ * \file CMirror.cpp
+ * \brief Implementation of mirror interpolation (conservative approach in FSI problems).
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CMirror.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+#include "../../include/toolboxes/printing_toolbox.hpp"
+
+
+CMirror::CMirror(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone,
+ unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
+ using PrintingToolbox::to_string;
+ if (jZone < iZone) {
+ SU2_MPI::Error(string("The order of the zones does not allow conservative interpolation to be setup.\n"
+ "Swap zones ") + to_string(iZone) + string(" and ") + to_string(jZone) + string("."),CURRENT_FUNCTION);
+ }
+ SetTransferCoeff(config);
+}
+
+void CMirror::SetTransferCoeff(const CConfig* const* config) {
+
+ const int nProcessor = size;
+
+ Buffer_Receive_nFace_Donor = new unsigned long [nProcessor];
+ Buffer_Receive_nFaceNodes_Donor = new unsigned long [nProcessor];
+
+ /*--- Number of markers on the interface ---*/
+ const auto nMarkerInt = (config[targetZone]->GetMarker_n_ZoneInterface())/2;
+
+ /*--- For the number of markers on the interface... ---*/
+ for (unsigned short iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
+ /*--- Procedure:
+ * - Loop through vertices of the aero grid
+ * - Find nearest element and allocate enough space in the aero grid donor point info
+ * - Set the transfer coefficient values
+ */
+
+ /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
+ const auto markDonor = FindInterfaceMarker(config[donorZone], iMarkerInt);
+
+ /*--- On the target side: find the tag of the boundary sharing the interface ---*/
+ const auto markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt);
+
+ /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
+ if(!CheckInterfaceBoundary(markDonor, markTarget)) continue;
+
+ unsigned long nVertexDonor = 0, nVertexTarget = 0;
+ if (markDonor != -1) nVertexDonor = donor_geometry->GetnVertex( markDonor );
+ if (markTarget != -1) nVertexTarget = target_geometry->GetnVertex( markTarget );
+
+ /*-- Collect the number of donor nodes: re-use 'Face' containers --*/
+ auto nLocalFace_Donor = 0ul;
+ auto nLocalFaceNodes_Donor = 0ul;
+ for (auto jVertex = 0ul; jVertexvertex[markDonor][jVertex]->GetNode(); // Local index of jVertex
+
+ if (donor_geometry->node[Point_Donor]->GetDomain()) {
+ auto nNodes = donor_geometry->vertex[markDonor][jVertex]->GetnDonorPoints();
+ nLocalFaceNodes_Donor += nNodes;
+ nLocalFace_Donor++;
+ }
+ }
+
+ Buffer_Send_nFace_Donor[0] = nLocalFace_Donor;
+ Buffer_Send_nFaceNodes_Donor[0] = nLocalFaceNodes_Donor;
+
+ /*--- Send Interface vertex information --*/
+ SU2_MPI::Allreduce(&nLocalFaceNodes_Donor, &MaxFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&nLocalFace_Donor, &MaxFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_nFace_Donor, 1, MPI_UNSIGNED_LONG,
+ Buffer_Receive_nFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG,
+ Buffer_Receive_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ MaxFace_Donor++;
+
+ /*-- Send donor info and init to 0 --*/
+ Buffer_Send_FaceIndex = new unsigned long[MaxFace_Donor] ();
+ Buffer_Send_FaceNodes = new unsigned long[MaxFaceNodes_Donor] ();
+ Buffer_Send_GlobalPoint = new long[MaxFaceNodes_Donor] ();
+ auto Buffer_Send_Coeff = new su2double[MaxFaceNodes_Donor] ();
+
+ Buffer_Receive_FaceIndex = new unsigned long[MaxFace_Donor*nProcessor];
+ Buffer_Receive_FaceNodes = new unsigned long[MaxFaceNodes_Donor*nProcessor];
+ Buffer_Receive_GlobalPoint = new long[MaxFaceNodes_Donor*nProcessor];
+ auto Buffer_Receive_Coeff = new su2double[MaxFaceNodes_Donor*nProcessor];
+
+ Buffer_Send_FaceIndex[0]=rank*MaxFaceNodes_Donor;
+ nLocalFace_Donor=0;
+ nLocalFaceNodes_Donor=0;
+
+ for (auto jVertex = 0ul; jVertex < nVertexDonor; jVertex++) {
+
+ auto Point_Donor = donor_geometry->vertex[markDonor][jVertex]->GetNode(); // Local index of jVertex
+
+ if (!donor_geometry->node[Point_Donor]->GetDomain()) continue;
+
+ auto nNodes = donor_geometry->vertex[markDonor][jVertex]->GetnDonorPoints();
+ for (auto iDonor = 0; iDonor < nNodes; iDonor++) {
+ Buffer_Send_FaceNodes[nLocalFaceNodes_Donor] = donor_geometry->node[Point_Donor]->GetGlobalIndex();
+ Buffer_Send_GlobalPoint[nLocalFaceNodes_Donor] =
+ donor_geometry->vertex[markDonor][jVertex]->GetInterpDonorPoint(iDonor);
+ Buffer_Send_Coeff[nLocalFaceNodes_Donor] =
+ donor_geometry->vertex[markDonor][jVertex]->GetDonorCoeff(iDonor);
+ nLocalFaceNodes_Donor++;
+ }
+ Buffer_Send_FaceIndex[nLocalFace_Donor+1] =Buffer_Send_FaceIndex[nLocalFace_Donor]+nNodes;
+ nLocalFace_Donor++;
+ }
+
+ SU2_MPI::Allgather(Buffer_Send_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG,
+ Buffer_Receive_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_GlobalPoint, MaxFaceNodes_Donor, MPI_LONG,
+ Buffer_Receive_GlobalPoint, MaxFaceNodes_Donor, MPI_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_Coeff, MaxFaceNodes_Donor, MPI_DOUBLE,
+ Buffer_Receive_Coeff, MaxFaceNodes_Donor, MPI_DOUBLE, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG,
+ Buffer_Receive_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+
+ /*--- Loop over the vertices on the target Marker ---*/
+ SU2_OMP_PARALLEL_(for schedule(dynamic,roundUpDiv(nVertexTarget,2*omp_get_max_threads())))
+ for (auto iVertex = 0ul; iVertex < nVertexTarget; iVertex++) {
+
+ auto target_vertex = target_geometry->vertex[markTarget][iVertex];
+ auto iPoint = target_vertex->GetNode();
+
+ if (!target_geometry->node[iPoint]->GetDomain()) continue;
+
+ const long Global_Point = target_geometry->node[iPoint]->GetGlobalIndex();
+
+ auto nNodes = 0;
+ for (int iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
+ for (auto iFace = 0ul; iFace < Buffer_Receive_nFace_Donor[iProcessor]; iFace++) {
+ auto faceindex = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace]; // first index of this face
+ auto iNodes = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace+1] - faceindex;
+ for (auto iTarget = 0ul; iTargetAllocate_DonorInfo(nNodes);
+
+ for (int iProcessor = 0, iDonor = 0; iProcessor < nProcessor; iProcessor++) {
+ for (auto iFace = 0ul; iFace < Buffer_Receive_nFace_Donor[iProcessor]; iFace++) {
+
+ auto faceindex = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace]; // first index of this face
+ auto iNodes = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace+1] - faceindex;
+
+ for (auto iTarget = 0ul; iTarget < iNodes; iTarget++) {
+ if (Global_Point == long(Buffer_Receive_GlobalPoint[faceindex+iTarget])) {
+ auto coeff = Buffer_Receive_Coeff[faceindex+iTarget];
+ auto pGlobalPoint = Buffer_Receive_FaceNodes[faceindex+iTarget];
+ target_vertex->SetInterpDonorPoint(iDonor,pGlobalPoint);
+ target_vertex->SetDonorCoeff(iDonor,coeff);
+ target_vertex->SetInterpDonorProcessor(iDonor, iProcessor);
+ iDonor++;
+ }
+ }
+ }
+ }
+ }
+
+ delete[] Buffer_Send_FaceIndex;
+ delete[] Buffer_Send_FaceNodes;
+ delete[] Buffer_Send_GlobalPoint;
+ delete[] Buffer_Send_Coeff;
+
+ delete[] Buffer_Receive_FaceIndex;
+ delete[] Buffer_Receive_FaceNodes;
+ delete[] Buffer_Receive_GlobalPoint;
+ delete[] Buffer_Receive_Coeff;
+ }
+
+ delete[] Buffer_Receive_nFace_Donor;
+ delete[] Buffer_Receive_nFaceNodes_Donor;
+
+}
diff --git a/Common/src/interface_interpolation/CNearestNeighbor.cpp b/Common/src/interface_interpolation/CNearestNeighbor.cpp
new file mode 100644
index 000000000000..1ab489bd8d94
--- /dev/null
+++ b/Common/src/interface_interpolation/CNearestNeighbor.cpp
@@ -0,0 +1,192 @@
+/*!
+ * \file CNearestNeighbor.cpp
+ * \brief Implementation of nearest neighbor interpolation.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CNearestNeighbor.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+#include "../../include/toolboxes/geometry_toolbox.hpp"
+
+
+/*! \brief Helper struct to (partially) sort neighbours according to distance while
+ * keeping track of the origin of the point (i.e. index and processor). */
+struct DonorInfo {
+ su2double dist;
+ unsigned pidx;
+ int proc;
+ DonorInfo(su2double d = 0.0, unsigned i = 0, int p = 0) :
+ dist(d), pidx(i), proc(p) { }
+ bool operator< (const DonorInfo& other) const {
+ /*--- Global index is used as tie-breaker to make sorted order independent of initial. ---*/
+ return (dist != other.dist)? (dist < other.dist) : (pidx < other.pidx);
+ }
+};
+
+CNearestNeighbor::CNearestNeighbor(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone,
+ unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
+ SetTransferCoeff(config);
+}
+
+void CNearestNeighbor::PrintStatistics() const {
+ if (rank != MASTER_NODE) return;
+ cout << " Avg/max distance to closest donor point: " << AvgDistance << "/" << MaxDistance << endl;
+}
+
+void CNearestNeighbor::SetTransferCoeff(const CConfig* const* config) {
+
+ /*--- Desired number of donor points. ---*/
+ const auto nDonor = max(config[donorZone]->GetNumNearestNeighbors(), 1);
+
+ /*--- Epsilon used to avoid division by zero. ---*/
+ const su2double eps = numeric_limits::epsilon();
+
+ const int nProcessor = size;
+ const auto nMarkerInt = config[donorZone]->GetMarker_n_ZoneInterface()/2;
+ const auto nDim = donor_geometry->GetnDim();
+
+ Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
+
+ vector > DonorInfoVec(omp_get_max_threads());
+
+ /*--- Cycle over nMarkersInt interface to determine communication pattern. ---*/
+
+ AvgDistance = MaxDistance = 0.0;
+ unsigned long totalTargetPoints = 0;
+
+ for (unsigned short iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
+
+ /*--- On the donor side: find the tag of the boundary sharing the interface. ---*/
+ const auto markDonor = FindInterfaceMarker(config[donorZone], iMarkerInt);
+
+ /*--- On the target side: find the tag of the boundary sharing the interface. ---*/
+ const auto markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt);
+
+ /*--- Checks if the zone contains the interface, if not continue to the next step. ---*/
+ if (!CheckInterfaceBoundary(markDonor, markTarget)) continue;
+
+ unsigned long nVertexDonor = 0, nVertexTarget = 0;
+ if (markDonor != -1) nVertexDonor = donor_geometry->GetnVertex(markDonor);
+ if (markTarget != -1) nVertexTarget = target_geometry->GetnVertex(markTarget);
+
+ /*--- Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor. ---*/
+ Determine_ArraySize(markDonor, markTarget, nVertexDonor, nDim);
+
+ const auto nPossibleDonor = accumulate(Buffer_Receive_nVertex_Donor,
+ Buffer_Receive_nVertex_Donor+nProcessor, 0ul);
+
+ Buffer_Send_Coord = new su2double [ MaxLocalVertex_Donor * nDim ];
+ Buffer_Send_GlobalPoint = new long [ MaxLocalVertex_Donor ];
+ Buffer_Receive_Coord = new su2double [ nProcessor * MaxLocalVertex_Donor * nDim ];
+ Buffer_Receive_GlobalPoint = new long [ nProcessor * MaxLocalVertex_Donor ];
+
+ /*--- Collect coordinates and global point indices. ---*/
+ Collect_VertexInfo(markDonor, markTarget, nVertexDonor, nDim);
+
+ /*--- Find the closest donor points to each target. ---*/
+ SU2_OMP_PARALLEL
+ {
+ /*--- Working array for this thread. ---*/
+ auto& donorInfo = DonorInfoVec[omp_get_thread_num()];
+ donorInfo.resize(nPossibleDonor);
+
+ su2double avgDist = 0.0, maxDist = 0.0;
+ unsigned long numTarget = 0;
+
+ SU2_OMP_FOR_DYN(roundUpDiv(nVertexTarget,2*omp_get_max_threads()))
+ for (auto iVertexTarget = 0ul; iVertexTarget < nVertexTarget; iVertexTarget++) {
+
+ auto target_vertex = target_geometry->vertex[markTarget][iVertexTarget];
+ const auto Point_Target = target_vertex->GetNode();
+
+ if (!target_geometry->node[Point_Target]->GetDomain()) continue;
+
+ /*--- Coordinates of the target point. ---*/
+ const su2double* Coord_i = target_geometry->node[Point_Target]->GetCoord();
+
+ /*--- Compute all distances. ---*/
+ for (int iProcessor = 0, iDonor = 0; iProcessor < nProcessor; ++iProcessor) {
+ for (auto jVertex = 0ul; jVertex < Buffer_Receive_nVertex_Donor[iProcessor]; ++jVertex) {
+
+ const auto idx = iProcessor*MaxLocalVertex_Donor + jVertex;
+ const auto pGlobalPoint = Buffer_Receive_GlobalPoint[idx];
+ const su2double* Coord_j = &Buffer_Receive_Coord[idx*nDim];
+ const auto dist2 = GeometryToolbox::SquaredDistance(nDim, Coord_i, Coord_j);
+
+ donorInfo[iDonor++] = DonorInfo(dist2, pGlobalPoint, iProcessor);
+ }
+ }
+
+ /*--- Find k closest points. ---*/
+ partial_sort(donorInfo.begin(), donorInfo.begin()+nDonor, donorInfo.end());
+
+ /*--- Update stats. ---*/
+ numTarget += 1;
+ su2double d = sqrt(donorInfo[0].dist);
+ avgDist += d;
+ maxDist = max(maxDist, d);
+
+ /*--- Compute interpolation numerators and denominator. ---*/
+ su2double denom = 0.0;
+ for (auto iDonor = 0ul; iDonor < nDonor; ++iDonor) {
+ donorInfo[iDonor].dist = 1.0 / (donorInfo[iDonor].dist + eps);
+ denom += donorInfo[iDonor].dist;
+ }
+
+ /*--- Set interpolation coefficients. ---*/
+ target_vertex->Allocate_DonorInfo(nDonor);
+
+ for (auto iDonor = 0ul; iDonor < nDonor; ++iDonor) {
+ target_vertex->SetInterpDonorPoint(iDonor, donorInfo[iDonor].pidx);
+ target_vertex->SetInterpDonorProcessor(iDonor, donorInfo[iDonor].proc);
+ target_vertex->SetDonorCoeff(iDonor, donorInfo[iDonor].dist/denom);
+ }
+ }
+ SU2_OMP_CRITICAL
+ {
+ totalTargetPoints += numTarget;
+ AvgDistance += avgDist;
+ MaxDistance = max(MaxDistance, maxDist);
+ }
+ } // end SU2_OMP_PARALLEL
+
+ delete[] Buffer_Send_Coord;
+ delete[] Buffer_Send_GlobalPoint;
+
+ delete[] Buffer_Receive_Coord;
+ delete[] Buffer_Receive_GlobalPoint;
+
+ }
+
+ delete[] Buffer_Receive_nVertex_Donor;
+
+ unsigned long tmp = totalTargetPoints;
+ SU2_MPI::Allreduce(&tmp, &totalTargetPoints, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+ su2double tmp1 = AvgDistance, tmp2 = MaxDistance;
+ SU2_MPI::Allreduce(&tmp1, &AvgDistance, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&tmp2, &MaxDistance, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+ AvgDistance /= totalTargetPoints;
+
+}
diff --git a/Common/src/interface_interpolation/CRadialBasisFunction.cpp b/Common/src/interface_interpolation/CRadialBasisFunction.cpp
new file mode 100644
index 000000000000..909f852eb535
--- /dev/null
+++ b/Common/src/interface_interpolation/CRadialBasisFunction.cpp
@@ -0,0 +1,594 @@
+/*!
+ * \file CRadialBasisFunction.cpp
+ * \brief Implementation of RBF interpolation.
+ * \author Joel Ho, P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CRadialBasisFunction.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+#include "../../include/toolboxes/CSymmetricMatrix.hpp"
+#include "../../include/toolboxes/geometry_toolbox.hpp"
+
+#if defined(HAVE_MKL)
+#include "mkl.h"
+#ifndef HAVE_LAPACK
+#define HAVE_LAPACK
+#endif
+#elif defined(HAVE_LAPACK)
+// dgemm(opA, opB, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc)
+extern "C" void dgemm_(const char*, const char*, const int*, const int*, const int*,
+ const passivedouble*, const passivedouble*, const int*, const passivedouble*,
+ const int*, const passivedouble*, passivedouble*, const int*);
+#define DGEMM dgemm_
+#endif
+
+
+CRadialBasisFunction::CRadialBasisFunction(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone,
+ unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
+ SetTransferCoeff(config);
+}
+
+void CRadialBasisFunction::PrintStatistics() const {
+ if (rank != MASTER_NODE) return;
+ cout.precision(3);
+ cout << " Min/avg/max number of RBF donors per target point: "
+ << MinDonors << "/" << AvgDonors << "/" << MaxDonors << "\n"
+ << " Avg/max correction factor after pruning: " << AvgCorrection << "/" << MaxCorrection;
+ if (MaxCorrection < 1.1 || AvgCorrection < 1.02) cout << " (ok)\n";
+ else if (MaxCorrection < 2.0 && AvgCorrection < 1.05) cout << " (warning)\n";
+ else cout << " <<< WARNING >>>\n";
+ cout << " Interpolation matrix is " << Density << "% dense." << endl;
+ cout.unsetf(ios::floatfield);
+}
+
+su2double CRadialBasisFunction::Get_RadialBasisValue(ENUM_RADIALBASIS type, const su2double radius, const su2double dist)
+{
+ su2double rbf = dist/radius;
+
+ switch (type) {
+
+ case WENDLAND_C2:
+ if(rbf < 1) rbf = pow(pow((1-rbf),2),2)*(4*rbf+1); // double use of pow(x,2) for optimization
+ else rbf = 0.0;
+ break;
+
+ case GAUSSIAN:
+ rbf = exp(-rbf*rbf);
+ break;
+
+ case THIN_PLATE_SPLINE:
+ if(rbf < numeric_limits::min()) rbf = 0.0;
+ else rbf *= rbf*log(rbf);
+ break;
+
+ case MULTI_QUADRIC:
+ case INV_MULTI_QUADRIC:
+ rbf = sqrt(1.0+rbf*rbf);
+ if(type == INV_MULTI_QUADRIC) rbf = 1.0/rbf;
+ break;
+ }
+
+ return rbf;
+}
+
+void CRadialBasisFunction::SetTransferCoeff(const CConfig* const* config) {
+
+ /*--- RBF options. ---*/
+ const auto kindRBF = static_cast(config[donorZone]->GetKindRadialBasisFunction());
+ const bool usePolynomial = config[donorZone]->GetRadialBasisFunctionPolynomialOption();
+ const su2double paramRBF = config[donorZone]->GetRadialBasisFunctionParameter();
+ const su2double pruneTol = config[donorZone]->GetRadialBasisFunctionPruneTol();
+
+ const auto nMarkerInt = config[donorZone]->GetMarker_n_ZoneInterface()/2;
+ const int nDim = donor_geometry->GetnDim();
+
+ const int nProcessor = size;
+ Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
+
+ /*--- Process interface patches in parallel, fetch all donor point coordinates,
+ * then distribute interpolation matrix computation over ranks and threads.
+ * To avoid repeating calls to Collect_VertexInfo we also save the global
+ * indices of the donor points and the mpi rank index that owns them. ---*/
+
+ vector donorCoordinates(nMarkerInt);
+ vector > donorGlobalPoint(nMarkerInt);
+ vector > donorProcessor(nMarkerInt);
+ vector assignedProcessor(nMarkerInt,-1);
+ vector totalWork(nProcessor,0);
+
+ for (unsigned short iMarkerInt = 0; iMarkerInt < nMarkerInt; ++iMarkerInt) {
+
+ /*--- On the donor side: find the tag of the boundary sharing the interface. ---*/
+ const auto markDonor = FindInterfaceMarker(config[donorZone], iMarkerInt+1);
+
+ /*--- On the target side: find the tag of the boundary sharing the interface. ---*/
+ const auto markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt+1);
+
+ /*--- If the zone does not contain the interface continue to the next pair of markers. ---*/
+ if (!CheckInterfaceBoundary(markDonor,markTarget)) continue;
+
+ unsigned long nVertexDonor = 0;
+ if (markDonor != -1) nVertexDonor = donor_geometry->GetnVertex(markDonor);
+
+ /*--- Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor. ---*/
+ Determine_ArraySize(markDonor, markTarget, nVertexDonor, nDim);
+
+ /*--- Compute total number of donor vertices. ---*/
+ const auto nGlobalVertexDonor = accumulate(Buffer_Receive_nVertex_Donor,
+ Buffer_Receive_nVertex_Donor+nProcessor, 0ul);
+
+ /*--- Gather coordinates and global point indices. ---*/
+ Buffer_Send_Coord = new su2double [ MaxLocalVertex_Donor * nDim ];
+ Buffer_Send_GlobalPoint = new long [ MaxLocalVertex_Donor ];
+ Buffer_Receive_Coord = new su2double [ nProcessor * MaxLocalVertex_Donor * nDim ];
+ Buffer_Receive_GlobalPoint = new long [ nProcessor * MaxLocalVertex_Donor ];
+
+ Collect_VertexInfo(markDonor, markTarget, nVertexDonor, nDim);
+
+ /*--- Compresses the gathered donor point information to simplify computations. ---*/
+ auto& donorCoord = donorCoordinates[iMarkerInt];
+ auto& donorPoint = donorGlobalPoint[iMarkerInt];
+ auto& donorProc = donorProcessor[iMarkerInt];
+ donorCoord.resize(nGlobalVertexDonor, nDim);
+ donorPoint.resize(nGlobalVertexDonor);
+ donorProc.resize(nGlobalVertexDonor);
+
+ auto iCount = 0ul;
+ for (int iProcessor = 0; iProcessor < nProcessor; ++iProcessor) {
+ auto offset = iProcessor * MaxLocalVertex_Donor;
+ for (auto iVertex = 0ul; iVertex < Buffer_Receive_nVertex_Donor[iProcessor]; ++iVertex) {
+ for (int iDim = 0; iDim < nDim; ++iDim)
+ donorCoord(iCount,iDim) = Buffer_Receive_Coord[(offset+iVertex)*nDim + iDim];
+ donorPoint[iCount] = Buffer_Receive_GlobalPoint[offset+iVertex];
+ donorProc[iCount] = iProcessor;
+ ++iCount;
+ }
+ }
+ assert((iCount == nGlobalVertexDonor) && "Global donor point count mismatch.");
+
+ delete[] Buffer_Send_Coord;
+ delete[] Buffer_Send_GlobalPoint;
+ delete[] Buffer_Receive_Coord;
+ delete[] Buffer_Receive_GlobalPoint;
+
+ /*--- Give an MPI-independent order to the points (required due to high condition
+ * number of the RBF matrix, avoids diff results with diff number of ranks. ---*/
+ vector order(nGlobalVertexDonor);
+ iota(order.begin(), order.end(), 0);
+ sort(order.begin(), order.end(), [&donorPoint](int i, int j){return donorPoint[i] < donorPoint[j];});
+
+ for (int i = 0; i < int(nGlobalVertexDonor); ++i) {
+ int j = order[i];
+ while (j < i) j = order[j];
+ if (i == j) continue;
+ swap(donorProc[i], donorProc[j]);
+ swap(donorPoint[i], donorPoint[j]);
+ for (int iDim = 0; iDim < nDim; ++iDim)
+ swap(donorCoord(i,iDim), donorCoord(j,iDim));
+ }
+
+ /*--- Static work scheduling over ranks based on which one has less work currently. ---*/
+ int iProcessor = 0;
+ for (int i = 1; i < nProcessor; ++i)
+ if (totalWork[i] < totalWork[iProcessor]) iProcessor = i;
+
+ totalWork[iProcessor] += pow(nGlobalVertexDonor,3); // based on matrix inversion.
+
+ assignedProcessor[iMarkerInt] = iProcessor;
+
+ }
+ delete[] Buffer_Receive_nVertex_Donor;
+
+ /*--- Compute the interpolation matrices for each patch of coordinates
+ * assigned to the rank. Subdivide work further by threads. ---*/
+ vector nPolynomialVec(nMarkerInt,-1);
+ vector > keepPolynomialRowVec(nMarkerInt, vector(nDim,1));
+ vector CinvTrucVec(nMarkerInt);
+
+ SU2_OMP_PARALLEL_(for schedule(dynamic,1))
+ for (unsigned short iMarkerInt = 0; iMarkerInt < nMarkerInt; ++iMarkerInt) {
+ if (rank == assignedProcessor[iMarkerInt]) {
+ ComputeGeneratorMatrix(kindRBF, usePolynomial, paramRBF,
+ donorCoordinates[iMarkerInt], nPolynomialVec[iMarkerInt],
+ keepPolynomialRowVec[iMarkerInt], CinvTrucVec[iMarkerInt]);
+ }
+ }
+
+ /*--- Final loop over interface markers to compute the interpolation coefficients. ---*/
+
+ /*--- Initialize variables for interpolation statistics. ---*/
+ unsigned long totalTargetPoints = 0, totalDonorPoints = 0, denseSize = 0;
+ MinDonors = 1<<30; MaxDonors = 0; MaxCorrection = 0.0; AvgCorrection = 0.0;
+
+ for (unsigned short iMarkerInt = 0; iMarkerInt < nMarkerInt; iMarkerInt++) {
+
+ /*--- Identify the rank that computed the interpolation matrix for this marker. ---*/
+ const int iProcessor = assignedProcessor[iMarkerInt];
+ /*--- If no processor was assigned to work, the zone does not contain the interface. ---*/
+ if (iProcessor < 0) continue;
+
+ /*--- Setup target information. ---*/
+ const int markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt+1);
+ unsigned long nVertexTarget = 0;
+ if (markTarget != -1) nVertexTarget = target_geometry->GetnVertex(markTarget);
+
+ /*--- Set references to donor information. ---*/
+ auto& donorCoord = donorCoordinates[iMarkerInt];
+ auto& donorPoint = donorGlobalPoint[iMarkerInt];
+ auto& donorProc = donorProcessor[iMarkerInt];
+
+ auto& C_inv_trunc = CinvTrucVec[iMarkerInt];
+ auto& nPolynomial = nPolynomialVec[iMarkerInt];
+ auto& keepPolynomialRow = keepPolynomialRowVec[iMarkerInt];
+
+ const auto nGlobalVertexDonor = donorCoord.rows();
+
+#ifdef HAVE_MPI
+ /*--- For simplicity, broadcast small information about the interpolation matrix. ---*/
+ SU2_MPI::Bcast(&nPolynomial, 1, MPI_INT, iProcessor, MPI_COMM_WORLD);
+ SU2_MPI::Bcast(keepPolynomialRow.data(), nDim, MPI_INT, iProcessor, MPI_COMM_WORLD);
+
+ /*--- Send C_inv_trunc only to the ranks that need it (those with target points),
+ * partial broadcast. MPI wrapper not used due to passive double. ---*/
+ vector allNumVertex(nProcessor);
+ SU2_MPI::Allgather(&nVertexTarget, 1, MPI_UNSIGNED_LONG,
+ allNumVertex.data(), 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+
+ if (rank == iProcessor) {
+ for (int jProcessor = 0; jProcessor < nProcessor; ++jProcessor)
+ if ((jProcessor != iProcessor) && (allNumVertex[jProcessor] != 0))
+ MPI_Send(C_inv_trunc.data(), C_inv_trunc.size(),
+ MPI_DOUBLE, jProcessor, 0, MPI_COMM_WORLD);
+ }
+ else if (nVertexTarget != 0) {
+ C_inv_trunc.resize(1+nPolynomial+nGlobalVertexDonor, nGlobalVertexDonor);
+ MPI_Recv(C_inv_trunc.data(), C_inv_trunc.size(), MPI_DOUBLE,
+ iProcessor, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+ }
+#endif
+
+ /*--- Compute interpolation matrix (H). This is a large matrix-matrix product with
+ * the generator matrix (C_inv_trunc) on the right. We avoid instantiation
+ * of the entire function matrix (A) and of the result (H), but work
+ * on a slab (set of rows) of A/H to amortize accesses to C_inv_trunc. ---*/
+
+ /*--- Fetch domain target vertices. ---*/
+
+ vector targetVertices; targetVertices.reserve(nVertexTarget);
+ vector targetCoord; targetCoord.reserve(nVertexTarget);
+
+ for (auto iVertexTarget = 0ul; iVertexTarget < nVertexTarget; ++iVertexTarget) {
+
+ auto targetVertex = target_geometry->vertex[markTarget][iVertexTarget];
+ auto pointTarget = targetVertex->GetNode();
+
+ if (target_geometry->node[pointTarget]->GetDomain()) {
+ targetVertices.push_back(targetVertex);
+ targetCoord.push_back(target_geometry->node[pointTarget]->GetCoord());
+ }
+ }
+ nVertexTarget = targetVertices.size();
+ totalTargetPoints += nVertexTarget;
+ denseSize += nVertexTarget*nGlobalVertexDonor;
+
+ /*--- Distribute target slabs over the threads in the rank for processing. ---*/
+
+ SU2_OMP_PARALLEL
+ if (nVertexTarget > 0) {
+
+ constexpr unsigned long targetSlabSize = 32;
+
+ su2passivematrix funcMat(targetSlabSize, 1+nPolynomial+nGlobalVertexDonor);
+ su2passivematrix interpMat(targetSlabSize, nGlobalVertexDonor);
+
+ /*--- Thread-local variables for statistics. ---*/
+ unsigned long minDonors = 1<<30, maxDonors = 0, totalDonors = 0;
+ passivedouble sumCorr = 0.0, maxCorr = 0.0;
+
+ SU2_OMP_FOR_DYN(1)
+ for (auto iVertexTarget = 0ul; iVertexTarget < nVertexTarget; iVertexTarget += targetSlabSize) {
+
+ const auto iLastVertex = min(nVertexTarget, iVertexTarget+targetSlabSize);
+ const auto slabSize = iLastVertex - iVertexTarget;
+
+ /*--- Prepare matrix of functions A (the targets to donors matrix). ---*/
+
+ /*--- Polynominal part: ---*/
+ if (usePolynomial) {
+ /*--- Constant term. ---*/
+ for (auto k = 0ul; k < slabSize; ++k) funcMat(k,0) = 1.0;
+
+ /*--- Linear terms. ---*/
+ for (int iDim = 0, idx = 1; iDim < nDim; ++iDim) {
+ /*--- Of which one may have been excluded. ---*/
+ if (!keepPolynomialRow[iDim]) continue;
+ for (auto k = 0ul; k < slabSize; ++k)
+ funcMat(k, idx) = SU2_TYPE::GetValue(targetCoord[iVertexTarget+k][iDim]);
+ idx += 1;
+ }
+ }
+ /*--- RBF terms: ---*/
+ for (auto iVertexDonor = 0ul; iVertexDonor < nGlobalVertexDonor; ++iVertexDonor) {
+ for (auto k = 0ul; k < slabSize; ++k) {
+ auto dist = GeometryToolbox::Distance(nDim, targetCoord[iVertexTarget+k], donorCoord[iVertexDonor]);
+ auto rbf = Get_RadialBasisValue(kindRBF, paramRBF, dist);
+ funcMat(k, 1+nPolynomial+iVertexDonor) = SU2_TYPE::GetValue(rbf);
+ }
+ }
+
+ /*--- Compute slab of the interpolation matrix. ---*/
+#ifdef HAVE_LAPACK
+ /*--- interpMat = funcMat * C_inv_trunc, but order of gemm arguments
+ * is swapped due to row-major storage of su2passivematrix. ---*/
+ const char op = 'N';
+ const int M = interpMat.cols(), N = slabSize, K = funcMat.cols();
+ // lda = C_inv_trunc.cols() = M; ldb = funcMat.cols() = K; ldc = interpMat.cols() = M;
+ const passivedouble alpha = 1.0, beta = 0.0;
+ DGEMM(&op, &op, &M, &N, &K, &alpha, C_inv_trunc[0], &M, funcMat[0], &K, &beta, interpMat[0], &M);
+#else
+ /*--- Naive product, loop order considers short-wide
+ * nature of funcMat and interpMat. ---*/
+ interpMat = 0.0;
+ for (auto k = 0ul; k < funcMat.cols(); ++k)
+ for (auto i = 0ul; i < slabSize; ++i)
+ for (auto j = 0ul; j < interpMat.cols(); ++j)
+ interpMat(i,j) += funcMat(i,k) * C_inv_trunc(k,j);
+#endif
+ /*--- Set interpolation coefficients. ---*/
+
+ for (auto k = 0ul; k < slabSize; ++k) {
+ auto targetVertex = targetVertices[iVertexTarget+k];
+
+ /*--- Prune small coefficients. ---*/
+ auto info = PruneSmallCoefficients(SU2_TYPE::GetValue(pruneTol), interpMat.cols(), interpMat[k]);
+ auto nnz = info.first;
+ totalDonors += nnz;
+ minDonors = min(minDonors, nnz);
+ maxDonors = max(maxDonors, nnz);
+ auto corr = fabs(info.second-1.0); // far from 1 either way is bad;
+ sumCorr += corr;
+ maxCorr = max(maxCorr, corr);
+
+ /*--- Allocate and set donor information for this target point. ---*/
+ targetVertex->Allocate_DonorInfo(nnz);
+
+ for (unsigned long iVertex = 0, iSet = 0; iVertex < nGlobalVertexDonor; ++iVertex) {
+ auto coeff = interpMat(k,iVertex);
+ if (fabs(coeff) > 0.0) {
+ targetVertex->SetInterpDonorProcessor(iSet, donorProc[iVertex]);
+ targetVertex->SetInterpDonorPoint(iSet, donorPoint[iVertex]);
+ targetVertex->SetDonorCoeff(iSet, coeff);
+ ++iSet;
+ }
+ }
+ }
+ } // end target vertex loop
+
+ SU2_OMP_CRITICAL
+ {
+ totalDonorPoints += totalDonors;
+ MinDonors = min(MinDonors, minDonors);
+ MaxDonors = max(MaxDonors, maxDonors);
+ AvgCorrection += sumCorr;
+ MaxCorrection = max(MaxCorrection, maxCorr);
+ }
+ } // end SU2_OMP_PARALLEL
+
+ /*--- Free global data that will no longer be used. ---*/
+ donorCoord.resize(0,0);
+ vector().swap(donorPoint);
+ vector().swap(donorProc);
+ C_inv_trunc.resize(0,0);
+
+ } // end loop over interface markers
+
+ /*--- Final reduction of interpolation statistics and basic sanity checks. ---*/
+ auto Reduce = [](SU2_MPI::Op op, unsigned long &val) {
+ auto tmp = val;
+ SU2_MPI::Allreduce(&tmp, &val, 1, MPI_UNSIGNED_LONG, op, MPI_COMM_WORLD);
+ };
+ Reduce(MPI_SUM, totalTargetPoints);
+ Reduce(MPI_SUM, totalDonorPoints);
+ Reduce(MPI_SUM, denseSize);
+ Reduce(MPI_MIN, MinDonors);
+ Reduce(MPI_MAX, MaxDonors);
+#ifdef HAVE_MPI
+ passivedouble tmp1 = AvgCorrection, tmp2 = MaxCorrection;
+ MPI_Allreduce(&tmp1, &AvgCorrection, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ MPI_Allreduce(&tmp2, &MaxCorrection, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+#endif
+ if (totalTargetPoints == 0)
+ SU2_MPI::Error("Somehow there are no target interpolation points.", CURRENT_FUNCTION);
+
+ if (MinDonors == 0)
+ SU2_MPI::Error("One or more target points have no donors, either:\n"
+ " - The interface surfaces are not in contact.\n"
+ " - The RBF radius is too small.\n"
+ " - The pruning tolerance is too aggressive.", CURRENT_FUNCTION);
+
+ MaxCorrection += 1.0; // put back the reference "1"
+ AvgCorrection = AvgCorrection / totalTargetPoints + 1.0;
+ AvgDonors = totalDonorPoints / totalTargetPoints;
+ Density = totalDonorPoints / (0.01*denseSize);
+
+}
+
+void CRadialBasisFunction::ComputeGeneratorMatrix(ENUM_RADIALBASIS type, bool usePolynomial,
+ su2double radius, const su2activematrix& coords, int& nPolynomial,
+ vector& keepPolynomialRow, su2passivematrix& C_inv_trunc) {
+
+ const su2double interfaceCoordTol = 1e6 * numeric_limits::epsilon();
+
+ const int nVertexDonor = coords.rows();
+ const int nDim = coords.cols();
+
+ /*--- Populate interpolation kernel. ---*/
+ CSymmetricMatrix global_M(nVertexDonor);
+
+ for (int iVertex = 0; iVertex < nVertexDonor; ++iVertex)
+ for (int jVertex = iVertex; jVertex < nVertexDonor; ++jVertex)
+ global_M(iVertex, jVertex) = SU2_TYPE::GetValue(Get_RadialBasisValue(type, radius,
+ GeometryToolbox::Distance(nDim, coords[iVertex], coords[jVertex])));
+
+ /*--- Invert M matrix (operation is in-place). ---*/
+ const bool kernelIsSPD = (type==WENDLAND_C2) || (type==GAUSSIAN) || (type==INV_MULTI_QUADRIC);
+ global_M.Invert(kernelIsSPD);
+
+ /*--- Compute C_inv_trunc. ---*/
+ if (usePolynomial) {
+
+ /*--- Fill P matrix (P for points, with an extra top row of ones). ---*/
+ su2passivematrix P(1+nDim, nVertexDonor);
+
+ for (int iVertex = 0; iVertex < nVertexDonor; iVertex++) {
+ P(0, iVertex) = 1.0;
+ for (int iDim = 0; iDim < nDim; ++iDim)
+ P(1+iDim, iVertex) = SU2_TYPE::GetValue(coords(iVertex, iDim));
+ }
+
+ /*--- Check if points lie on a plane and remove one coordinate from P if so. ---*/
+ nPolynomial = CheckPolynomialTerms(interfaceCoordTol, keepPolynomialRow, P);
+
+ /*--- Compute Q = P * M^-1 ---*/
+ su2passivematrix Q;
+ global_M.MatMatMult('R', P, Q);
+
+ /*--- Compute Mp = (Q * P^T)^-1 ---*/
+ CSymmetricMatrix Mp(nPolynomial+1);
+
+ for (int i = 0; i <= nPolynomial; ++i)
+ for (int j = i; j <= nPolynomial; ++j) {
+ Mp(i,j) = 0.0;
+ for (int k = 0; k < nVertexDonor; ++k)
+ Mp(i,j) += Q(i,k) * P(j,k);
+ }
+ Mp.Invert(false);
+
+ /*--- Compute M_p * Q, the top part of C_inv_trunc. ---*/
+ su2passivematrix C_inv_top;
+ Mp.MatMatMult('L', Q, C_inv_top);
+
+ /*--- Compute M^-1 - Q^T * C_inv_top, the bottom (main) part of C_inv_trunc. ---*/
+ su2passivematrix C_inv_bot = global_M.StealData();
+#ifdef HAVE_LAPACK
+ /*--- Order of gemm arguments swapped due to row-major storage. ---*/
+ const char opa = 'N', opb = 'T';
+ const int M = nVertexDonor, N = nVertexDonor, K = nPolynomial+1;
+ // lda = C_inv_top.cols() = M; ldb = Q.cols() = M; ldc = C_inv_bot.cols() = M;
+ const passivedouble alpha = -1.0, beta = 1.0;
+ DGEMM(&opa, &opb, &M, &N, &K, &alpha, C_inv_top[0], &M, Q[0], &M, &beta, C_inv_bot[0], &M);
+#else // naive product
+ for (int i = 0; i < nVertexDonor; ++i)
+ for (int j = 0; j < nVertexDonor; ++j)
+ for (int k = 0; k <= nPolynomial; ++k)
+ C_inv_bot(i,j) -= Q(k,i) * C_inv_top(k,j);
+#endif
+
+ /*--- Merge top and bottom of C_inv_trunc. More intrusive memory
+ * management, or separate handling of top and bottom, would
+ * avoid these copies (and associated temporary vars). ---*/
+ C_inv_trunc.resize(1+nPolynomial+nVertexDonor, nVertexDonor);
+ memcpy(C_inv_trunc[0], C_inv_top.data(), C_inv_top.size()*sizeof(passivedouble));
+ memcpy(C_inv_trunc[1+nPolynomial], C_inv_bot.data(), C_inv_bot.size()*sizeof(passivedouble));
+ }
+ else {
+ /*--- No polynomial term used in the interpolation, C_inv_trunc = M^-1. ---*/
+
+ C_inv_trunc = global_M.StealData();
+
+ } // end usePolynomial
+
+}
+
+int CRadialBasisFunction::CheckPolynomialTerms(su2double max_diff_tol, vector& keep_row,
+ su2passivematrix &P) {
+ const int m = P.rows();
+ const int n = P.cols();
+
+ /*--- The first row of P is all ones and we do not care about it for this analysis. ---*/
+ const int n_rows = m-1;
+ keep_row.resize(n_rows);
+
+ /*--- By default assume points are not on a plane (all rows kept). ---*/
+ int n_polynomial = n_rows;
+ keep_row.resize(n_rows);
+ for (int i = 0; i < n_rows; ++i) keep_row[i] = 1;
+
+ /*--- Fit a plane through the points in P. ---*/
+
+ /*--- Compute P times its transpose and invert. ---*/
+ CSymmetricMatrix PPT(n_rows);
+
+ for (int i = 0; i < n_rows; ++i)
+ for (int j = i; j < n_rows; ++j) {
+ PPT(i,j) = 0.0;
+ for (int k = 0; k < n; ++k) PPT(i,j) += P(i+1,k) * P(j+1,k);
+ }
+ PPT.Invert(true);
+
+ /*--- RHS for the least squares fit (vector of ones times P). ---*/
+ vector rhs(n_rows,0.0), coeff(n_rows);
+
+ for (int i = 0; i < n_rows; ++i)
+ for (int j = 0; j < n; ++j)
+ rhs[i] += P(i+1,j);
+
+ /*--- Multiply the RHS by the inverse thus obtaining the coefficients. ---*/
+ PPT.MatVecMult(rhs.begin(), coeff.begin());
+
+ /*--- Determine the maximum deviation of the points from the fitted plane. ---*/
+ passivedouble max_diff = 0.0;
+
+ for (int j = 0; j < n; ++j)
+ {
+ passivedouble sum = 0.0;
+ for (int i = 0; i < n_rows; ++i) sum += coeff[i] * P(i+1,j);
+
+ /*--- 1.0 is the arbitrary constant we are assuming when fitting
+ the plane, i.e. the vector of ones used to generate the RHS. ---*/
+ max_diff = max(abs(1.0-sum), max_diff);
+ }
+
+ /*--- If points lie on plane remove row associated with the maximum coefficient. ---*/
+ if (max_diff < max_diff_tol)
+ {
+ /*--- Find the max coeff and mark the corresponding row for removal. ---*/
+ int remove_row = 0;
+ for (int i = 1; i < n_rows; ++i)
+ if (abs(coeff[i]) > abs(coeff[remove_row]))
+ remove_row = i;
+
+ /*--- Mark row as removed and adjust number of polynomial terms. ---*/
+ n_polynomial = n_rows-1;
+ keep_row[remove_row] = 0;
+
+ /*--- Truncated P by shifting rows "up". ---*/
+ for (auto i = remove_row+1; i < m-1; ++i)
+ for (int j = 0; j < n; ++j)
+ P(i,j) = P(i+1,j);
+ }
+
+ return n_polynomial;
+}
diff --git a/Common/src/interface_interpolation/CSlidingMesh.cpp b/Common/src/interface_interpolation/CSlidingMesh.cpp
new file mode 100644
index 000000000000..979d3df45e74
--- /dev/null
+++ b/Common/src/interface_interpolation/CSlidingMesh.cpp
@@ -0,0 +1,1265 @@
+/*!
+ * \file CSlidingMesh.cpp
+ * \brief Implementation of sliding mesh interpolation.
+ * \author H. Kline
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/interface_interpolation/CSlidingMesh.hpp"
+#include "../../include/CConfig.hpp"
+#include "../../include/geometry/CGeometry.hpp"
+#include "../../include/toolboxes/geometry_toolbox.hpp"
+
+
+CSlidingMesh::CSlidingMesh(CGeometry ****geometry_container, const CConfig* const* config, unsigned int iZone,
+ unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
+ SetTransferCoeff(config);
+}
+
+void CSlidingMesh::SetTransferCoeff(const CConfig* const* config) {
+
+ /* 0 - Variable declaration */
+
+ /* --- General variables --- */
+
+ bool check;
+
+ unsigned short iDim;
+
+ unsigned long ii, jj, *uptr;
+ unsigned long vPoint;
+ unsigned long iEdgeVisited, nEdgeVisited, iNodeVisited;
+ unsigned long nAlreadyVisited, nToVisit, StartVisited;
+
+ unsigned long *alreadyVisitedDonor, *ToVisit, *tmpVect;
+ unsigned long *storeProc, *tmp_storeProc;
+
+ su2double dTMP;
+ su2double *Coeff_Vect, *tmp_Coeff_Vect;
+
+ /* --- Geometrical variables --- */
+
+ su2double *Coord_i, *Coord_j, dist, mindist, *Normal;
+ su2double Area, Area_old, tmp_Area;
+ su2double LineIntersectionLength, *Direction, length;
+
+
+ /* --- Markers Variables --- */
+
+ unsigned short iMarkerInt, nMarkerInt;
+
+ unsigned long iVertex, nVertexTarget;
+
+ int markDonor, markTarget;
+
+ /* --- Target variables --- */
+
+ unsigned long target_iPoint, jVertexTarget;
+ unsigned long nEdges_target, nNode_target;
+
+ unsigned long *Target_nLinkedNodes, *Target_LinkedNodes, *Target_StartLinkedNodes, *target_segment;
+ unsigned long *Target_Proc;
+ long *Target_GlobalPoint, *Donor_GlobalPoint;
+
+ su2double *TargetPoint_Coord, *target_iMidEdge_point, *target_jMidEdge_point, **target_element;
+
+ /* --- Donor variables --- */
+
+ unsigned long donor_StartIndex, donor_forward_point, donor_backward_point, donor_iPoint, donor_OldiPoint;
+ unsigned long nEdges_donor, nNode_donor, nGlobalVertex_Donor;
+
+ unsigned long nDonorPoints, iDonor;
+ unsigned long *Donor_Vect, *tmp_Donor_Vect;
+ unsigned long *Donor_nLinkedNodes, *Donor_LinkedNodes, *Donor_StartLinkedNodes;
+ unsigned long *Donor_Proc;
+
+ su2double *donor_iMidEdge_point, *donor_jMidEdge_point;
+ su2double **donor_element, *DonorPoint_Coord;
+
+ /* 1 - Variable pre-processing */
+
+ const unsigned short nDim = donor_geometry->GetnDim();
+
+ /*--- Setting up auxiliary vectors ---*/
+
+ Donor_Vect = nullptr;
+ Coeff_Vect = nullptr;
+ storeProc = nullptr;
+
+ tmp_Donor_Vect = nullptr;
+ tmp_Coeff_Vect = nullptr;
+ tmp_storeProc = nullptr;
+
+ Normal = new su2double[nDim];
+ Direction = new su2double[nDim];
+
+
+ /* 2 - Find boundary tag between touching grids */
+
+ /*--- Number of markers on the FSI interface ---*/
+ nMarkerInt = (int)( config[ donorZone ]->GetMarker_n_ZoneInterface() ) / 2;
+
+ /*--- For the number of markers on the interface... ---*/
+ for ( iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++ ){
+
+ /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
+ markDonor = FindInterfaceMarker(config[donorZone], iMarkerInt);
+
+ /*--- On the target side: find the tag of the boundary sharing the interface ---*/
+ markTarget = FindInterfaceMarker(config[targetZone], iMarkerInt);
+
+ /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
+ if(!CheckInterfaceBoundary(markDonor, markTarget)) continue;
+
+ if(markTarget != -1)
+ nVertexTarget = target_geometry->GetnVertex( markTarget );
+ else
+ nVertexTarget = 0;
+
+ /*
+ 3 -Reconstruct the boundaries from parallel partitioning
+ */
+
+ /*--- Target boundary ---*/
+ ReconstructBoundary(targetZone, markTarget);
+
+ nGlobalVertex_Target = nGlobalVertex;
+
+ TargetPoint_Coord = Buffer_Receive_Coord;
+ Target_GlobalPoint = Buffer_Receive_GlobalPoint;
+ Target_nLinkedNodes = Buffer_Receive_nLinkedNodes;
+ Target_StartLinkedNodes = Buffer_Receive_StartLinkedNodes;
+ Target_LinkedNodes = Buffer_Receive_LinkedNodes;
+ Target_Proc = Buffer_Receive_Proc;
+
+ /*--- Donor boundary ---*/
+ ReconstructBoundary(donorZone, markDonor);
+
+ nGlobalVertex_Donor = nGlobalVertex;
+
+ DonorPoint_Coord = Buffer_Receive_Coord;
+ Donor_GlobalPoint = Buffer_Receive_GlobalPoint;
+ Donor_nLinkedNodes = Buffer_Receive_nLinkedNodes;
+ Donor_StartLinkedNodes = Buffer_Receive_StartLinkedNodes;
+ Donor_LinkedNodes = Buffer_Receive_LinkedNodes;
+ Donor_Proc = Buffer_Receive_Proc;
+
+ /*--- Starts building the supermesh layer (2D or 3D) ---*/
+ /* - For each target node, it first finds the closest donor point
+ * - Then it creates the supermesh in the close proximity of the target point:
+ * - Starting from the closest donor node, it expands the supermesh by including
+ * donor elements neighboring the initial one, until the overall target area is fully covered.
+ */
+
+ if(nDim == 2){
+
+ target_iMidEdge_point = new su2double[nDim];
+ target_jMidEdge_point = new su2double[nDim];
+
+ donor_iMidEdge_point = new su2double[nDim];
+ donor_jMidEdge_point = new su2double[nDim];
+
+ /*--- Starts with supermesh reconstruction ---*/
+
+ target_segment = new unsigned long[2];
+
+ for (iVertex = 0; iVertex < nVertexTarget; iVertex++) {
+
+ nDonorPoints = 0;
+
+ /*--- Stores coordinates of the target node ---*/
+
+ target_iPoint = target_geometry->vertex[markTarget][iVertex]->GetNode();
+
+ if (target_geometry->node[target_iPoint]->GetDomain()){
+
+ Coord_i = target_geometry->node[target_iPoint]->GetCoord();
+
+ /*--- Brute force to find the closest donor_node ---*/
+
+ mindist = 1E6;
+ donor_StartIndex = 0;
+
+ for (donor_iPoint = 0; donor_iPoint < nGlobalVertex_Donor; donor_iPoint++) {
+
+ Coord_j = &DonorPoint_Coord[ donor_iPoint * nDim ];
+
+ dist = GeometryToolbox::Distance(nDim, Coord_i, Coord_j);
+
+ if (dist < mindist) {
+ mindist = dist;
+ donor_StartIndex = donor_iPoint;
+ }
+
+ if (dist == 0.0){
+ donor_StartIndex = donor_iPoint;
+ break;
+ }
+ }
+
+ donor_iPoint = donor_StartIndex;
+ donor_OldiPoint = donor_iPoint;
+
+ /*--- Contruct information regarding the target cell ---*/
+
+ long dPoint = target_geometry->node[target_iPoint]->GetGlobalIndex();
+ for (jVertexTarget = 0; jVertexTarget < nGlobalVertex_Target; jVertexTarget++)
+ if( dPoint == Target_GlobalPoint[jVertexTarget] )
+ break;
+
+ if ( Target_nLinkedNodes[jVertexTarget] == 1 ){
+ target_segment[0] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] ];
+ target_segment[1] = jVertexTarget;
+ }
+ else{
+ target_segment[0] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] ];
+ target_segment[1] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] + 1];
+ }
+
+ dTMP = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ target_iMidEdge_point[iDim] = ( TargetPoint_Coord[ nDim * target_segment[0] + iDim ] +
+ target_geometry->node[ target_iPoint ]->GetCoord(iDim) ) / 2;
+ target_jMidEdge_point[iDim] = ( TargetPoint_Coord[ nDim * target_segment[1] + iDim ] +
+ target_geometry->node[ target_iPoint ]->GetCoord(iDim) ) / 2;
+
+ Direction[iDim] = target_jMidEdge_point[iDim] - target_iMidEdge_point[iDim];
+ dTMP += Direction[iDim] * Direction[iDim];
+ }
+
+ dTMP = sqrt(dTMP);
+ for(iDim = 0; iDim < nDim; iDim++)
+ Direction[iDim] /= dTMP;
+
+ length = GeometryToolbox::Distance(nDim, target_iMidEdge_point, target_jMidEdge_point);
+
+ check = false;
+
+ /*--- Proceeds along the forward direction (depending on which connected boundary node is found first) ---*/
+
+ while( !check ){
+
+ /*--- Proceeds until the value of the intersection area is null ---*/
+
+ if ( Donor_nLinkedNodes[donor_iPoint] == 1 ){
+ donor_forward_point = Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
+ donor_backward_point = donor_iPoint;
+ }
+ else{
+ uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
+
+ if( donor_OldiPoint != uptr[0] ){
+ donor_forward_point = uptr[0];
+ donor_backward_point = uptr[1];
+ }
+ else{
+ donor_forward_point = uptr[1];
+ donor_backward_point = uptr[0];
+ }
+ }
+
+ if(donor_iPoint >= nGlobalVertex_Donor){
+ check = true;
+ continue;
+ }
+
+ for(iDim = 0; iDim < nDim; iDim++){
+ donor_iMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_forward_point * nDim + iDim] +
+ DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
+ donor_jMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_backward_point * nDim + iDim] +
+ DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
+ }
+
+ LineIntersectionLength = ComputeLineIntersectionLength(nDim, target_iMidEdge_point, target_jMidEdge_point,
+ donor_iMidEdge_point, donor_jMidEdge_point, Direction);
+
+ if ( LineIntersectionLength == 0.0 ){
+ check = true;
+ continue;
+ }
+
+ /*--- In case the element intersects the target cell, update the auxiliary communication data structure ---*/
+
+ tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
+ tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
+ tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
+
+ for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
+ tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
+ tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
+ tmp_storeProc[iDonor] = storeProc[iDonor];
+ }
+
+ tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
+ tmp_Coeff_Vect[ nDonorPoints ] = LineIntersectionLength / length;
+ tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
+
+ if (Donor_Vect != nullptr) delete [] Donor_Vect;
+ if (Coeff_Vect != nullptr) delete [] Coeff_Vect;
+ if (storeProc != nullptr) delete [] storeProc;
+
+ Donor_Vect = tmp_Donor_Vect;
+ Coeff_Vect = tmp_Coeff_Vect;
+ storeProc = tmp_storeProc;
+
+ donor_OldiPoint = donor_iPoint;
+ donor_iPoint = donor_forward_point;
+
+ nDonorPoints++;
+ }
+
+ if ( Donor_nLinkedNodes[donor_StartIndex] == 2 ){
+ check = false;
+
+ uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_StartIndex] ];
+
+ donor_iPoint = uptr[1];
+ donor_OldiPoint = donor_StartIndex;
+ }
+ else
+ check = true;
+
+ /*--- Proceeds along the backward direction (depending on which connected boundary node is found first) ---*/
+
+ while( !check ){
+
+ /*--- Proceeds until the value of the intersection length is null ---*/
+ if ( Donor_nLinkedNodes[donor_iPoint] == 1 ){
+ donor_forward_point = donor_OldiPoint;
+ donor_backward_point = donor_iPoint;
+ }
+ else{
+ uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
+
+ if( donor_OldiPoint != uptr[0] ){
+ donor_forward_point = uptr[0];
+ donor_backward_point = uptr[1];
+ }
+ else{
+ donor_forward_point = uptr[1];
+ donor_backward_point = uptr[0];
+ }
+ }
+
+ if(donor_iPoint >= nGlobalVertex_Donor){
+ check = true;
+ continue;
+ }
+
+ for(iDim = 0; iDim < nDim; iDim++){
+ donor_iMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_forward_point * nDim + iDim] +
+ DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
+ donor_jMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_backward_point * nDim + iDim] +
+ DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
+ }
+
+ LineIntersectionLength = ComputeLineIntersectionLength(nDim, target_iMidEdge_point, target_jMidEdge_point,
+ donor_iMidEdge_point, donor_jMidEdge_point, Direction);
+
+ if ( LineIntersectionLength == 0.0 ){
+ check = true;
+ continue;
+ }
+
+ /*--- In case the element intersects the target cell, update the auxiliary communication data structure ---*/
+
+ tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
+ tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
+ tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
+
+ for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
+ tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
+ tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
+ tmp_storeProc[iDonor] = storeProc[iDonor];
+ }
+
+ tmp_Coeff_Vect[ nDonorPoints ] = LineIntersectionLength / length;
+ tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
+ tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
+
+ if (Donor_Vect != nullptr) delete [] Donor_Vect;
+ if (Coeff_Vect != nullptr) delete [] Coeff_Vect;
+ if (storeProc != nullptr) delete [] storeProc;
+
+ Donor_Vect = tmp_Donor_Vect;
+ Coeff_Vect = tmp_Coeff_Vect;
+ storeProc = tmp_storeProc;
+
+ donor_OldiPoint = donor_iPoint;
+ donor_iPoint = donor_forward_point;
+
+ nDonorPoints++;
+ }
+
+ /*--- Set the communication data structure and copy data from the auxiliary vectors ---*/
+
+ target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo(nDonorPoints);
+
+ for ( iDonor = 0; iDonor < nDonorPoints; iDonor++ ){
+ target_geometry->vertex[markTarget][iVertex]->SetDonorCoeff(iDonor, Coeff_Vect[iDonor]);
+ target_geometry->vertex[markTarget][iVertex]->SetInterpDonorPoint(iDonor, Donor_GlobalPoint[Donor_Vect[iDonor]]);
+ target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, storeProc[iDonor]);
+ }
+ }
+ }
+
+ delete [] target_segment;
+
+ delete [] target_iMidEdge_point;
+ delete [] target_jMidEdge_point;
+
+ delete [] donor_iMidEdge_point;
+ delete [] donor_jMidEdge_point;
+ }
+ else{
+ /* --- 3D geometry, creates a superficial super-mesh --- */
+
+ for (iVertex = 0; iVertex < nVertexTarget; iVertex++) {
+
+ nDonorPoints = 0;
+
+ /*--- Stores coordinates of the target node ---*/
+
+ target_iPoint = target_geometry->vertex[markTarget][iVertex]->GetNode();
+
+ if (!target_geometry->node[target_iPoint]->GetDomain()) continue;
+
+ Coord_i = target_geometry->node[target_iPoint]->GetCoord();
+
+ target_geometry->vertex[markTarget][iVertex]->GetNormal(Normal);
+
+ /*--- The value of Area computed here includes also portion of boundary belonging to different marker ---*/
+ Area = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++)
+ Area += Normal[iDim]*Normal[iDim];
+ Area = sqrt(Area);
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ Normal[iDim] /= Area;
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ Coord_i[iDim] = target_geometry->node[target_iPoint]->GetCoord(iDim);
+
+ long dPoint = target_geometry->node[target_iPoint]->GetGlobalIndex();
+ for (target_iPoint = 0; target_iPoint < nGlobalVertex_Target; target_iPoint++){
+ if( dPoint == Target_GlobalPoint[target_iPoint] )
+ break;
+ }
+
+ /*--- Build local surface dual mesh for target element ---*/
+
+ nEdges_target = Target_nLinkedNodes[target_iPoint];
+
+ nNode_target = 2*(nEdges_target + 1);
+
+ target_element = new su2double*[nNode_target];
+ for (ii = 0; ii < nNode_target; ii++)
+ target_element[ii] = new su2double[nDim];
+
+ nNode_target = Build_3D_surface_element(Target_LinkedNodes, Target_StartLinkedNodes, Target_nLinkedNodes,
+ TargetPoint_Coord, target_iPoint, target_element);
+
+ /*--- Brute force to find the closest donor_node ---*/
+
+ mindist = 1E6;
+ donor_StartIndex = 0;
+
+ for (donor_iPoint = 0; donor_iPoint < nGlobalVertex_Donor; donor_iPoint++) {
+
+ Coord_j = &DonorPoint_Coord[ donor_iPoint * nDim ];
+
+ dist = GeometryToolbox::Distance(nDim, Coord_i, Coord_j);
+
+ if (dist < mindist) {
+ mindist = dist;
+ donor_StartIndex = donor_iPoint;
+ }
+
+ if (dist == 0.0){
+ donor_StartIndex = donor_iPoint;
+ break;
+ }
+ }
+
+ donor_iPoint = donor_StartIndex;
+
+ nEdges_donor = Donor_nLinkedNodes[donor_iPoint];
+
+ donor_element = new su2double*[ 2*nEdges_donor + 2 ];
+ for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
+ donor_element[ii] = new su2double[nDim];
+
+ nNode_donor = Build_3D_surface_element(Donor_LinkedNodes, Donor_StartLinkedNodes, Donor_nLinkedNodes,
+ DonorPoint_Coord, donor_iPoint, donor_element);
+
+ Area = 0;
+ for (ii = 1; ii < nNode_target-1; ii++){
+ for (jj = 1; jj < nNode_donor-1; jj++){
+ Area += Compute_Triangle_Intersection(target_element[0], target_element[ii], target_element[ii+1],
+ donor_element[0], donor_element[jj], donor_element[jj+1], Normal);
+ }
+ }
+
+ for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
+ delete [] donor_element[ii];
+ delete [] donor_element;
+
+ nDonorPoints = 1;
+
+ /*--- In case the element intersect the target cell update the auxiliary communication data structure ---*/
+
+ Coeff_Vect = new su2double[ nDonorPoints ];
+ Donor_Vect = new unsigned long[ nDonorPoints ];
+ storeProc = new unsigned long[ nDonorPoints ];
+
+ Coeff_Vect[0] = Area;
+ Donor_Vect[0] = donor_iPoint;
+ storeProc[0] = Donor_Proc[donor_iPoint];
+
+ alreadyVisitedDonor = new unsigned long[1];
+
+ alreadyVisitedDonor[0] = donor_iPoint;
+ nAlreadyVisited = 1;
+ StartVisited = 0;
+
+ Area_old = -1;
+
+ while( Area > Area_old ){
+
+ /*
+ * - Starting from the closest donor_point, it expands the supermesh by a countour search pattern.
+ * - The closest donor element becomes the core, at each iteration a new layer of elements around the core is taken into account
+ */
+
+ Area_old = Area;
+
+ ToVisit = nullptr;
+ nToVisit = 0;
+
+ for( iNodeVisited = StartVisited; iNodeVisited < nAlreadyVisited; iNodeVisited++ ){
+
+ vPoint = alreadyVisitedDonor[ iNodeVisited ];
+
+ nEdgeVisited = Donor_nLinkedNodes[vPoint];
+
+ for (iEdgeVisited = 0; iEdgeVisited < nEdgeVisited; iEdgeVisited++){
+
+ donor_iPoint = Donor_LinkedNodes[ Donor_StartLinkedNodes[vPoint] + iEdgeVisited];
+
+ /*--- Check if the node to visit is already listed in the data structure to avoid double visits ---*/
+
+ check = 0;
+
+ for( jj = 0; jj < nAlreadyVisited; jj++ ){
+ if( donor_iPoint == alreadyVisitedDonor[jj] ){
+ check = 1;
+ break;
+ }
+ }
+
+ if( check == 0 && ToVisit != nullptr){
+ for( jj = 0; jj < nToVisit; jj++ )
+ if( donor_iPoint == ToVisit[jj] ){
+ check = 1;
+ break;
+ }
+ }
+
+ if( check == 0 ){
+ /*--- If the node was not already visited, visit it and list it into data structure ---*/
+
+ tmpVect = new unsigned long[ nToVisit + 1 ];
+
+ for( jj = 0; jj < nToVisit; jj++ )
+ tmpVect[jj] = ToVisit[jj];
+ tmpVect[nToVisit] = donor_iPoint;
+
+ if( ToVisit != nullptr )
+ delete [] ToVisit;
+
+ ToVisit = tmpVect;
+ tmpVect = nullptr;
+
+ nToVisit++;
+
+ /*--- Find the value of the intersection area between the current donor element and the target element --- */
+
+ nEdges_donor = Donor_nLinkedNodes[donor_iPoint];
+
+ donor_element = new su2double*[ 2*nEdges_donor + 2 ];
+ for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
+ donor_element[ii] = new su2double[nDim];
+
+ nNode_donor = Build_3D_surface_element(Donor_LinkedNodes, Donor_StartLinkedNodes, Donor_nLinkedNodes,
+ DonorPoint_Coord, donor_iPoint, donor_element);
+
+ tmp_Area = 0;
+ for (ii = 1; ii < nNode_target-1; ii++)
+ for (jj = 1; jj < nNode_donor-1; jj++)
+ tmp_Area += Compute_Triangle_Intersection(target_element[0], target_element[ii], target_element[ii+1],
+ donor_element[0], donor_element[jj], donor_element[jj+1], Normal);
+
+ for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
+ delete [] donor_element[ii];
+ delete [] donor_element;
+
+ /*--- In case the element intersect the target cell update the auxiliary communication data structure ---*/
+
+ tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
+ tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
+ tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
+
+ for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
+ tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
+ tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
+ tmp_storeProc[iDonor] = storeProc[iDonor];
+ }
+
+ tmp_Coeff_Vect[ nDonorPoints ] = tmp_Area;
+ tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
+ tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
+
+ if (Donor_Vect != nullptr) {delete [] Donor_Vect; }
+ if (Coeff_Vect != nullptr) {delete [] Coeff_Vect; }
+ if (storeProc != nullptr) {delete [] storeProc; }
+
+ Donor_Vect = tmp_Donor_Vect;
+ Coeff_Vect = tmp_Coeff_Vect;
+ storeProc = tmp_storeProc;
+
+ tmp_Coeff_Vect = nullptr;
+ tmp_Donor_Vect = nullptr;
+ tmp_storeProc = nullptr;
+
+ nDonorPoints++;
+
+ Area += tmp_Area;
+ }
+ }
+ }
+
+ /*--- Update auxiliary data structure ---*/
+
+ StartVisited = nAlreadyVisited;
+
+ tmpVect = new unsigned long[ nAlreadyVisited + nToVisit ];
+
+ for( jj = 0; jj < nAlreadyVisited; jj++ )
+ tmpVect[jj] = alreadyVisitedDonor[jj];
+
+ for( jj = 0; jj < nToVisit; jj++ )
+ tmpVect[ nAlreadyVisited + jj ] = ToVisit[jj];
+
+ if( alreadyVisitedDonor != nullptr )
+ delete [] alreadyVisitedDonor;
+
+ alreadyVisitedDonor = tmpVect;
+
+ nAlreadyVisited += nToVisit;
+
+ delete [] ToVisit;
+ }
+
+ delete [] alreadyVisitedDonor;
+
+ /*--- Set the communication data structure and copy data from the auxiliary vectors ---*/
+
+ target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo(nDonorPoints);
+
+ for ( iDonor = 0; iDonor < nDonorPoints; iDonor++ ){
+ target_geometry->vertex[markTarget][iVertex]->SetDonorCoeff(iDonor, Coeff_Vect[iDonor]/Area);
+ target_geometry->vertex[markTarget][iVertex]->SetInterpDonorPoint( iDonor, Donor_GlobalPoint[ Donor_Vect[iDonor] ] );
+ target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, storeProc[iDonor]);
+ }
+
+ for (ii = 0; ii < 2*nEdges_target + 2; ii++)
+ delete [] target_element[ii];
+ delete [] target_element;
+
+ delete [] Donor_Vect; Donor_Vect = nullptr;
+ delete [] Coeff_Vect; Coeff_Vect = nullptr;
+ delete [] storeProc; storeProc = nullptr;
+ }
+ }
+
+ delete [] TargetPoint_Coord;
+ delete [] Target_GlobalPoint;
+ delete [] Target_Proc;
+ delete [] Target_nLinkedNodes;
+ delete [] Target_LinkedNodes;
+ delete [] Target_StartLinkedNodes;
+
+ delete [] DonorPoint_Coord;
+ delete [] Donor_GlobalPoint;
+ delete [] Donor_Proc;
+ delete [] Donor_nLinkedNodes;
+ delete [] Donor_StartLinkedNodes;
+ delete [] Donor_LinkedNodes;
+
+ }
+
+ delete [] Normal;
+ delete [] Direction;
+
+ if (Donor_Vect != nullptr) delete [] Donor_Vect;
+ if (Coeff_Vect != nullptr) delete [] Coeff_Vect;
+ if (storeProc != nullptr) delete [] storeProc;
+}
+
+int CSlidingMesh::Build_3D_surface_element(const unsigned long *map, const unsigned long *startIndex,
+ const unsigned long* nNeighbor, const su2double *coord,
+ unsigned long centralNode, su2double** element) {
+
+ /*--- Given a node "centralNode", this routines reconstruct the vertex centered
+ * surface element around the node and store it into "element" ---*/
+
+ unsigned long iNode, jNode, kNode, iElementNode, iPoint, jPoint, nOuterNodes;
+
+ constexpr unsigned short nDim = 3;
+ unsigned short iDim, nTmp;
+
+ int NextNode, **OuterNodesNeighbour, CurrentNode, StartIndex, count;
+ const unsigned long *OuterNodes, *ptr;
+
+ /* --- Store central node as element first point --- */
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ element[0][iDim] = coord[centralNode * nDim + iDim];
+
+ nOuterNodes = nNeighbor[centralNode];
+
+ OuterNodes = &map[ startIndex[centralNode] ];
+
+ /* --- Allocate auxiliary structure, vectors are longer than needed but this avoid further re-allocations due to length variation --- */
+
+ OuterNodesNeighbour = new int*[nOuterNodes];
+ for ( iNode = 0; iNode < nOuterNodes; iNode++ )
+ OuterNodesNeighbour[ iNode ] = new int[2];
+
+ /* --- Finds which and how many nodes belong to the specified marker, initialize some variables --- */
+
+ for ( iNode = 0; iNode < nOuterNodes; iNode++ ){
+ OuterNodesNeighbour[ iNode ][0] = -1;
+ OuterNodesNeighbour[ iNode ][1] = -1;
+ }
+
+ /* --- For each outer node, the program finds the two neighbouring outer nodes --- */
+
+ StartIndex = 0;
+ for( iNode = 0; iNode < nOuterNodes; iNode++ ){
+
+ count = 0;
+ iPoint = OuterNodes[ iNode ];
+ ptr = &map[ startIndex[iPoint] ];
+ nTmp = nNeighbor[iPoint];
+
+ for ( jNode = 0; jNode < nTmp; jNode++ ){
+ jPoint = ptr[jNode];
+ for( kNode = 0; kNode < nOuterNodes; kNode++ ){
+ if ( jPoint == OuterNodes[ kNode ] && jPoint != centralNode){
+ OuterNodesNeighbour[iNode][count] = (int)kNode;
+ count++;
+ break;
+ }
+ }
+ }
+
+ // If the central node belongs to two different markers, ie at corners, makes this outer node the starting point for reconstructing the element
+ if( count == 1 )
+ StartIndex = (int)iNode;
+ }
+
+ /* --- Build element, starts from one outer node and loops along the external edges until the element is reconstructed --- */
+
+ CurrentNode = StartIndex;
+ NextNode = OuterNodesNeighbour[ CurrentNode ][0];
+ iElementNode = 1;
+
+ while( NextNode != -1 ){
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ element[ iElementNode ][iDim] = ( element[0][iDim] + coord[ OuterNodes[ CurrentNode ] * nDim + iDim ])/2;
+
+ iElementNode++;
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ element[ iElementNode ][iDim] = ( element[0][iDim] + coord[ OuterNodes[ CurrentNode ] * nDim + iDim] +
+ coord[ OuterNodes[ NextNode ] * nDim + iDim] )/3;
+ iElementNode++;
+
+ if( OuterNodesNeighbour[ NextNode ][0] == CurrentNode){
+ CurrentNode = NextNode;
+ NextNode = OuterNodesNeighbour[ NextNode ][1];
+ }
+ else{
+ CurrentNode = NextNode;
+ NextNode = OuterNodesNeighbour[ NextNode ][0];
+ }
+
+ if (CurrentNode == StartIndex)
+ break;
+ }
+
+ if( CurrentNode == StartIndex ){ // This is a closed element, so add again element 1 to the end of the structure, useful later
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ element[ iElementNode ][iDim] = element[1][iDim];
+ iElementNode++;
+ }
+ else{
+ for (iDim = 0; iDim < nDim; iDim++)
+ element[ iElementNode ][iDim] = ( element[0][iDim] + coord[ OuterNodes[ CurrentNode ] * nDim + iDim] )/2;
+ iElementNode++;
+ }
+
+ for ( iNode = 0; iNode < nOuterNodes; iNode++ )
+ delete [] OuterNodesNeighbour[ iNode ];
+ delete [] OuterNodesNeighbour;
+
+ return (int)iElementNode;
+
+}
+
+su2double CSlidingMesh::ComputeLineIntersectionLength(unsigned short nDim, const su2double* A1, const su2double* A2,
+ const su2double* B1, const su2double* B2, const su2double* Direction) {
+
+ /*--- Given 2 segments, each defined by 2 points, it projects them along a given direction
+ * and it computes the length of the segment resulting from their intersection ---*/
+ /*--- The algorithm works for both 2D and 3D problems ---*/
+
+ unsigned short iDim;
+
+ su2double dotA2, dotB1, dotB2;
+
+ dotA2 = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dotA2 += ( A2[iDim] - A1[iDim] ) * Direction[iDim];
+
+ if( dotA2 >= 0 ){
+ dotB1 = 0;
+ dotB2 = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ dotB1 += ( B1[iDim] - A1[iDim] ) * Direction[iDim];
+ dotB2 += ( B2[iDim] - A1[iDim] ) * Direction[iDim];
+ }
+ }
+ else{
+ dotA2 *= -1;
+
+ dotB1 = 0;
+ dotB2 = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ dotB1 -= ( B1[iDim] - A1[iDim] ) * Direction[iDim];
+ dotB2 -= ( B2[iDim] - A1[iDim] ) * Direction[iDim];
+ }
+ }
+
+ if( dotB1 >= 0 && dotB1 <= dotA2 ){
+ if ( dotB2 < 0 )
+ return fabs( dotB1 );
+ if ( dotB2 > dotA2 )
+ return fabs( dotA2 - dotB1 );
+
+ return fabs( dotB1 - dotB2 );
+ }
+
+ if( dotB2 >= 0 && dotB2 <= dotA2 ){
+ if ( dotB1 < 0 )
+ return fabs(dotB2);
+ if ( dotB1 > dotA2 )
+ return fabs( dotA2 - dotB2 );
+ }
+
+ if( ( dotB1 <= 0 && dotA2 <= dotB2 ) || ( dotB2 <= 0 && dotA2 <= dotB1 ) )
+ return fabs( dotA2 );
+
+ return 0.0;
+}
+
+su2double CSlidingMesh::Compute_Triangle_Intersection(const su2double* A1, const su2double* A2, const su2double* A3,
+ const su2double* B1, const su2double* B2, const su2double* B3,
+ const su2double* Direction) {
+
+ /* --- This routine is ONLY for 3D grids --- */
+ /* --- Projects triangle points onto a plane, specified by its normal "Direction", and calls the ComputeIntersectionArea routine --- */
+
+ unsigned short iDim;
+ constexpr unsigned short nDim = 3;
+
+ su2double I[3], J[3], K[3];
+ su2double a1[3], a2[3], a3[3];
+ su2double b1[3], b2[3], b3[3];
+ su2double m1, m2;
+
+ /* --- Reference frame is determined by: x = A1A2 y = x ^ ( -Direction ) --- */
+
+ for(iDim = 0; iDim < 3; iDim++){
+ a1[iDim] = 0;
+ a2[iDim] = 0;
+ a3[iDim] = 0;
+
+ b1[iDim] = 0;
+ b2[iDim] = 0;
+ b3[iDim] = 0;
+ }
+
+ m1 = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ K[iDim] = Direction[iDim];
+
+ m1 += K[iDim] * K[iDim];
+ }
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ K[iDim] /= sqrt(m1);
+
+ m2 = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ m2 += (A2[iDim] - A1[iDim]) * K[iDim];
+
+ m1 = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ I[iDim] = (A2[iDim] - A1[iDim]) - m2 * K[iDim];
+ m1 += I[iDim] * I[iDim];
+ }
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ I[iDim] /= sqrt(m1);
+
+ // Cross product to find Y
+ J[0] = K[1]*I[2] - K[2]*I[1];
+ J[1] = -(K[0]*I[2] - K[2]*I[0]);
+ J[2] = K[0]*I[1] - K[1]*I[0];
+
+ /* --- Project all points on the plane specified by Direction and change their reference frame taking A1 as origin --- */
+
+ for(iDim = 0; iDim < nDim; iDim++){
+ a2[0] += (A2[iDim] - A1[iDim]) * I[iDim];
+ a2[1] += (A2[iDim] - A1[iDim]) * J[iDim];
+ a2[2] += (A2[iDim] - A1[iDim]) * K[iDim];
+
+ a3[0] += (A3[iDim] - A1[iDim]) * I[iDim];
+ a3[1] += (A3[iDim] - A1[iDim]) * J[iDim];
+ a3[2] += (A3[iDim] - A1[iDim]) * K[iDim];
+
+ b1[0] += (B1[iDim] - A1[iDim]) * I[iDim];
+ b1[1] += (B1[iDim] - A1[iDim]) * J[iDim];
+ b1[2] += (B1[iDim] - A1[iDim]) * K[iDim];
+
+ b2[0] += (B2[iDim] - A1[iDim]) * I[iDim];
+ b2[1] += (B2[iDim] - A1[iDim]) * J[iDim];
+ b2[2] += (B2[iDim] - A1[iDim]) * K[iDim];
+
+ b3[0] += (B3[iDim] - A1[iDim]) * I[iDim];
+ b3[1] += (B3[iDim] - A1[iDim]) * J[iDim];
+ b3[2] += (B3[iDim] - A1[iDim]) * K[iDim];
+ }
+
+ /*--- Compute intersection area ---*/
+
+ return ComputeIntersectionArea( a1, a2, a3, b1, b2, b3 );
+}
+
+su2double CSlidingMesh::ComputeIntersectionArea(const su2double* P1, const su2double* P2, const su2double* P3,
+ const su2double* Q1, const su2double* Q2, const su2double* Q3) {
+
+ /* --- This routines computes the area of the polygonal element generated by the superimposition of 2 planar triangle --- */
+ /* --- The 2 triangle must lie on the same plane --- */
+
+ unsigned short iDim, nPoints = 0, i, j, k;
+ unsigned short min_theta_index;
+
+ su2double points[16][2], IntersectionPoint[2], theta[6];
+ su2double TriangleP[4][2], TriangleQ[4][2];
+ su2double Area, det, dot1, dot2, dtmp, min_theta;
+
+ constexpr unsigned short nDim = 2;
+
+ for(iDim = 0; iDim < nDim; iDim++){
+ TriangleP[0][iDim] = 0;
+ TriangleP[1][iDim] = P2[iDim] - P1[iDim];
+ TriangleP[2][iDim] = P3[iDim] - P1[iDim];
+ TriangleP[3][iDim] = 0;
+
+ TriangleQ[0][iDim] = Q1[iDim] - P1[iDim];
+ TriangleQ[1][iDim] = Q2[iDim] - P1[iDim];
+ TriangleQ[2][iDim] = Q3[iDim] - P1[iDim];
+ TriangleQ[3][iDim] = Q1[iDim] - P1[iDim];
+ }
+
+
+ for( j = 0; j < 3; j++){
+ if( CheckPointInsideTriangle(TriangleP[j], TriangleQ[0], TriangleQ[1], TriangleQ[2]) ){
+
+ // Then P1 is also inside triangle Q, so store it
+ for(iDim = 0; iDim < nDim; iDim++)
+ points[nPoints][iDim] = TriangleP[j][iDim];
+
+ nPoints++;
+ }
+ }
+
+ for( j = 0; j < 3; j++){
+ if( CheckPointInsideTriangle(TriangleQ[j], TriangleP[0], TriangleP[1], TriangleP[2]) ){
+
+ // Then Q1 is also inside triangle P, so store it
+ for(iDim = 0; iDim < nDim; iDim++)
+ points[nPoints][iDim] = TriangleQ[j][iDim];
+
+ nPoints++;
+ }
+ }
+
+
+ // Compute all edge intersections
+
+ for( j = 0; j < 3; j++){
+ for( i = 0; i < 3; i++){
+
+ det = (TriangleP[j][0] - TriangleP[j+1][0]) * (TriangleQ[i][1] - TriangleQ[i+1][1]) -
+ (TriangleP[j][1] - TriangleP[j+1][1]) * (TriangleQ[i][0] - TriangleQ[i+1][0]);
+
+ if ( det != 0.0 ){
+ ComputeLineIntersectionPoint( TriangleP[j], TriangleP[j+1], TriangleQ[i], TriangleQ[i+1], IntersectionPoint );
+
+ dot1 = 0;
+ dot2 = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ dot1 += ( TriangleP[j][iDim] - IntersectionPoint[iDim] ) * ( TriangleP[j+1][iDim] - IntersectionPoint[iDim] );
+ dot2 += ( TriangleQ[i][iDim] - IntersectionPoint[iDim] ) * ( TriangleQ[i+1][iDim] - IntersectionPoint[iDim] );
+ }
+
+ if( dot1 <= 0 && dot2 <= 0 ){ // It found one intersection
+
+ // Store temporarily the intersection point
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ points[nPoints][iDim] = IntersectionPoint[iDim];
+
+ nPoints++;
+ }
+ }
+ }
+ }
+
+ // Remove double points, if any
+
+ for( i = 0; i < nPoints; i++){
+ for( j = i+1; j < nPoints; j++){
+ if(points[j][0] == points[i][0] && points[j][1] == points[i][1]){
+ for( k = j; k < nPoints-1; k++){
+ points[k][0] = points[k+1][0];
+ points[k][1] = points[k+1][1];
+ }
+ nPoints--;
+ j--;
+ }
+ }
+ }
+
+ // Re-order nodes
+
+ for( i = 1; i < nPoints; i++){ // Change again reference frame
+ for(iDim = 0; iDim < nDim; iDim++)
+ points[i][iDim] -= points[0][iDim];
+
+ // Compute polar azimuth for each node but the first
+ theta[i] = atan2(points[i][1], points[i][0]);
+ }
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ points[0][iDim] = 0;
+
+ for( i = 1; i < nPoints; i++){
+
+ min_theta = theta[i];
+ min_theta_index = 0;
+
+ for( j = i + 1; j < nPoints; j++){
+
+ if( theta[j] < min_theta ){
+ min_theta = theta[j];
+ min_theta_index = j;
+ }
+ }
+
+ if( min_theta_index != 0 ){
+ dtmp = theta[i];
+ theta[i] = theta[min_theta_index];
+ theta[min_theta_index] = dtmp;
+
+ dtmp = points[i][0];
+ points[i][0] = points[min_theta_index][0];
+ points[min_theta_index][0] = dtmp;
+
+ dtmp = points[i][1];
+ points[i][1] = points[min_theta_index][1];
+ points[min_theta_index][1] = dtmp;
+ }
+ }
+
+ // compute area using cross product rule, points position are referred to the
+ // 2-dimensional, local, reference frame centered in points[0]
+
+ Area = 0;
+
+ if (nPoints > 2){
+ for( i = 1; i < nPoints-1; i++ ){
+
+ // Ax*By
+ Area += ( points[i][0] - points[0][0] ) * ( points[i+1][1] - points[0][1] );
+
+ // Ay*Bx
+ Area -= ( points[i][1] - points[0][1] ) * ( points[i+1][0] - points[0][0] );
+ }
+ }
+
+ return fabs(Area)/2;
+}
+
+void CSlidingMesh::ComputeLineIntersectionPoint(const su2double* A1, const su2double* A2, const su2double* B1,
+ const su2double* B2, su2double* IntersectionPoint ){
+
+ /* --- Uses determinant rule to compute the intersection point between 2 straight segments --- */
+ /* This works only for lines on a 2D plane, A1, A2 and B1, B2 are respectively the head and the tail points of each segment,
+ * since they're on a 2D plane they are defined by a 2-elements array containing their coordinates */
+
+ su2double det;
+
+ det = (A1[0] - A2[0]) * (B1[1] - B2[1]) - (A1[1] - A2[1]) * (B1[0] - B2[0]);
+
+ if ( det != 0.0 ){ // else there is no intersection point
+ IntersectionPoint[0] = ( ( A1[0]*A2[1] - A1[1]*A2[0] ) * ( B1[0] - B2[0] ) - ( B1[0]*B2[1] - B1[1]*B2[0] ) * ( A1[0] - A2[0] ) ) / det;
+ IntersectionPoint[1] = ( ( A1[0]*A2[1] - A1[1]*A2[0] ) * ( B1[1] - B2[1] ) - ( B1[0]*B2[1] - B1[1]*B2[0] ) * ( A1[1] - A2[1] ) ) / det;
+ }
+}
+
+bool CSlidingMesh::CheckPointInsideTriangle(const su2double* Point, const su2double* T1, const su2double* T2, const su2double* T3) {
+
+ /* --- Check whether a point "Point" lies inside or outside a triangle defined by 3 points "T1", "T2", "T3" --- */
+ /* For each edge it checks on which side the point lies:
+ * - Computes the unit vector pointing at the internal side of the edge
+ * - Comutes the vector that connects the point to a point along the edge
+ * - If the dot product is positive it means that the point is on the internal side of the edge
+ * - If the check is positive for all the 3 edges, then the point lies within the triangle
+ */
+
+ unsigned short iDim, check = 0;
+
+ su2double vect1[2], vect2[2], r[2];
+ su2double dot;
+
+ constexpr unsigned short nDim = 2;
+
+ /* --- Check first edge --- */
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ vect1[iDim] = T3[iDim] - T1[iDim]; // vec 1 is aligned to the edge
+ vect2[iDim] = T2[iDim] - T1[iDim]; // vect 2 is the vector connecting one edge point to the third triangle vertex
+
+ r[iDim] = Point[iDim] - T1[iDim]; // Connects point to vertex T1
+
+ dot += vect2[iDim] * vect2[iDim];
+ }
+ dot = sqrt(dot);
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect2[iDim] /= dot;
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dot += vect1[iDim] * vect2[iDim];
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect1[iDim] = T3[iDim] - (T1[iDim] + dot * vect2[iDim]); // Computes the inward unit vector
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++) // Checs that the point lies on the internal plane
+ dot += vect1[iDim] * r[iDim];
+
+ if (dot >= 0)
+ check++;
+
+ /* --- Check second edge --- */
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ vect1[iDim] = T1[iDim] - T2[iDim];
+ vect2[iDim] = T3[iDim] - T2[iDim];
+
+ r[iDim] = Point[iDim] - T2[iDim];
+
+ dot += vect2[iDim] * vect2[iDim];
+ }
+ dot = sqrt(dot);
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect2[iDim] /= dot;
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dot += vect1[iDim] * vect2[iDim];
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect1[iDim] = T1[iDim] - (T2[iDim] + dot * vect2[iDim]);
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dot += vect1[iDim] * r[iDim];
+
+ if (dot >= 0)
+ check++;
+
+ /* --- Check third edge --- */
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++){
+ vect1[iDim] = T2[iDim] - T3[iDim];
+ vect2[iDim] = T1[iDim] - T3[iDim];
+
+ r[iDim] = Point[iDim] - T3[iDim];
+
+ dot += vect2[iDim] * vect2[iDim];
+ }
+ dot = sqrt(dot);
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect2[iDim] /= dot;
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dot += vect1[iDim] * vect2[iDim];
+
+ for(iDim = 0; iDim < nDim; iDim++)
+ vect1[iDim] = T2[iDim] - (T3[iDim] + dot * vect2[iDim]);
+
+ dot = 0;
+ for(iDim = 0; iDim < nDim; iDim++)
+ dot += vect1[iDim] * r[iDim];
+
+ if (dot >= 0)
+ check++;
+
+ return (check == 3);
+}
diff --git a/Common/src/interface_interpolation/meson.build b/Common/src/interface_interpolation/meson.build
new file mode 100644
index 000000000000..8624b3ad4fa8
--- /dev/null
+++ b/Common/src/interface_interpolation/meson.build
@@ -0,0 +1,7 @@
+common_src += files(['CInterpolatorFactory.cpp',
+ 'CInterpolator.cpp',
+ 'CMirror.cpp',
+ 'CSlidingMesh.cpp',
+ 'CIsoparametric.cpp',
+ 'CNearestNeighbor.cpp',
+ 'CRadialBasisFunction.cpp'])
diff --git a/Common/src/interpolation_structure.cpp b/Common/src/interpolation_structure.cpp
deleted file mode 100644
index 2cf20d8ec7e5..000000000000
--- a/Common/src/interpolation_structure.cpp
+++ /dev/null
@@ -1,3849 +0,0 @@
-/*!
- * \file interpolation_structure.cpp
- * \brief Main subroutines used by SU2_FSI
- * \author H. Kline
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-#include "../include/interpolation_structure.hpp"
-
-#if defined(HAVE_MKL)
-#include "mkl.h"
-#ifndef HAVE_LAPACK
-#define HAVE_LAPACK
-#endif
-#elif defined(HAVE_LAPACK)
-/*--- Lapack / Blas routines used in RBF interpolation. ---*/
-extern "C" void dsptrf_(char*, int*, passivedouble*, int*, int*);
-extern "C" void dsptri_(char*, int*, passivedouble*, int*, passivedouble*, int*);
-extern "C" void dsymm_(char*, char*, int*, int*, passivedouble*, passivedouble*, int*,
- passivedouble*, int*, passivedouble*, passivedouble*, int*);
-#endif
-
-CInterpolator::CInterpolator(void) {
-
- size = SU2_MPI::GetSize();
- rank = SU2_MPI::GetRank();
-
- nZone = 0;
- Geometry = NULL;
-
- donor_geometry = NULL;
- target_geometry = NULL;
-
- donorZone = 0;
- targetZone = 0;
-
- Buffer_Receive_nVertex_Donor = NULL;
- Buffer_Receive_nFace_Donor = NULL;
- Buffer_Receive_nFaceNodes_Donor = NULL;
- Buffer_Send_nVertex_Donor = NULL;
- Buffer_Send_nFace_Donor = NULL;
- Buffer_Send_nFaceNodes_Donor = NULL;
- Buffer_Receive_GlobalPoint = NULL;
- Buffer_Send_GlobalPoint = NULL;
- Buffer_Send_FaceIndex = NULL;
- Buffer_Receive_FaceIndex = NULL;
- Buffer_Send_FaceNodes = NULL;
- Buffer_Receive_FaceNodes = NULL;
- Buffer_Send_FaceProc = NULL;
- Buffer_Receive_FaceProc = NULL;
-
- Buffer_Send_Coord = NULL;
- Buffer_Send_Normal = NULL;
- Buffer_Receive_Coord = NULL;
- Buffer_Receive_Normal = NULL;
-
- Receive_GlobalPoint = NULL;
- Buffer_Receive_nLinkedNodes = NULL;
- Buffer_Receive_LinkedNodes = NULL;
- Buffer_Receive_StartLinkedNodes = NULL;
- Buffer_Receive_Proc = NULL;
-
-}
-
-CInterpolator::~CInterpolator(void) {
-
- //if (Buffer_Receive_nVertex_Donor!= NULL) delete[] Buffer_Receive_nVertex_Donor;
-}
-
-
-CInterpolator::CInterpolator(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) {
-
- size = SU2_MPI::GetSize();
- rank = SU2_MPI::GetRank();
-
- /* Store pointers*/
- Geometry = geometry_container;
-
- donorZone = iZone;
- targetZone = jZone;
-
- donor_geometry = geometry_container[donorZone][INST_0][MESH_0];
- target_geometry = geometry_container[targetZone][INST_0][MESH_0];
-
- /*--- Initialize transfer coefficients between the zones ---*/
- /* Since this is a virtual function, call it in the child class constructor */
- //Set_TransferCoeff(targetZone,donorZone,config);
- /*--- Initialize transfer coefficients between the zones ---*/
- //Set_TransferCoeff(Zones,config);
-
- //Buffer_Receive_nVertex_Donor = NULL;
-
-}
-
-inline void CInterpolator::Set_TransferCoeff(CConfig **config) { }
-
-void CInterpolator::Determine_ArraySize(bool faces, int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim) {
- unsigned long nLocalVertex_Donor = 0, nLocalFaceNodes_Donor=0, nLocalFace_Donor=0;
- unsigned long iVertex, iPointDonor = 0;
- /* Only needed if face data is also collected */
- unsigned long inode;
- unsigned long donor_elem, jElem, jPoint;
- unsigned short iDonor;
- unsigned int nFaces=0, iFace, nNodes=0;
- bool face_on_marker = true;
-
- for (iVertex = 0; iVertex < nVertexDonor; iVertex++) {
- iPointDonor = donor_geometry->vertex[markDonor][iVertex]->GetNode();
- if (donor_geometry->node[iPointDonor]->GetDomain()) {
- nLocalVertex_Donor++;
- if (faces) {
- /*--- On Donor geometry also communicate face info ---*/
- if (nDim==3) {
- for (jElem=0; jElemnode[iPointDonor]->GetnElem(); jElem++) {
- donor_elem = donor_geometry->node[iPointDonor]->GetElem(jElem);
- nFaces = donor_geometry->elem[donor_elem]->GetnFaces();
- for (iFace=0; iFaceelem[donor_elem]->GetnNodesFace(iFace);
- for (iDonor=0; iDonorelem[donor_elem]->GetFaces(iFace, iDonor);
- jPoint = donor_geometry->elem[donor_elem]->GetNode(inode);
- face_on_marker = (face_on_marker && (donor_geometry->node[jPoint]->GetVertex(markDonor) !=-1));
- }
- if (face_on_marker ) {
- nLocalFace_Donor++;
- nLocalFaceNodes_Donor+=nNodes;
- }
- }
- }
- }
- else {
- /*--- in 2D we use the edges ---*/
- nNodes=2;
- nFaces = donor_geometry->node[iPointDonor]->GetnPoint();
- for (iFace=0; iFacenode[iPointDonor]->GetEdge(iFace);
- jPoint = donor_geometry->edge[inode]->GetNode(iDonor);
- face_on_marker = (face_on_marker && (donor_geometry->node[jPoint]->GetVertex(markDonor) !=-1));
- }
- if (face_on_marker ) {
- nLocalFace_Donor++;
- nLocalFaceNodes_Donor+=nNodes;
- }
- }
- }
- }
- }
- }
-
- Buffer_Send_nVertex_Donor[0] = nLocalVertex_Donor;
- if (faces) {
- Buffer_Send_nFace_Donor[0] = nLocalFace_Donor;
- Buffer_Send_nFaceNodes_Donor[0] = nLocalFaceNodes_Donor;
- }
-
- /*--- Send Interface vertex information --*/
-#ifdef HAVE_MPI
- SU2_MPI::Allreduce(&nLocalVertex_Donor, &MaxLocalVertex_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_nVertex_Donor, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- if (faces) {
- SU2_MPI::Allreduce(&nLocalFace_Donor, &nGlobalFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&nLocalFace_Donor, &MaxFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&nLocalFaceNodes_Donor, &nGlobalFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&nLocalFaceNodes_Donor, &MaxFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_nFace_Donor, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- MaxFace_Donor++;
- }
-#else
- MaxLocalVertex_Donor = nLocalVertex_Donor;
- Buffer_Receive_nVertex_Donor[0] = Buffer_Send_nVertex_Donor[0];
- if (faces) {
- nGlobalFace_Donor = nLocalFace_Donor;
- nGlobalFaceNodes_Donor = nLocalFaceNodes_Donor;
- MaxFaceNodes_Donor = nLocalFaceNodes_Donor;
- MaxFace_Donor = nLocalFace_Donor+1;
- Buffer_Receive_nFace_Donor[0] = Buffer_Send_nFace_Donor[0];
- Buffer_Receive_nFaceNodes_Donor[0] = Buffer_Send_nFaceNodes_Donor[0];
- }
-#endif
-
-}
-
-void CInterpolator::Collect_VertexInfo(bool faces, int markDonor, int markTarget, unsigned long nVertexDonor, unsigned short nDim)
-{
- unsigned long iVertex, iPointDonor = 0, iVertexDonor, nBuffer_Coord, nBuffer_Point, nLocalVertex_Donor;
- unsigned short iDim;
-
- /* Only needed if face data is also collected */
- su2double *Normal;
-
- for (iVertex = 0; iVertex < MaxLocalVertex_Donor; iVertex++) {
- Buffer_Send_GlobalPoint[iVertex] = -1;
- for (iDim = 0; iDim < nDim; iDim++) {
- Buffer_Send_Coord[iVertex*nDim+iDim] = 0.0;
- if (faces)
- Buffer_Send_Normal[iVertex*nDim+iDim] = 0.0;
- }
- }
-
- /*--- Copy coordinates and point to the auxiliar vector --*/
- nLocalVertex_Donor = 0;
-
- for (iVertexDonor = 0; iVertexDonor < nVertexDonor; iVertexDonor++) {
- iPointDonor = donor_geometry->vertex[markDonor][iVertexDonor]->GetNode();
- if (donor_geometry->node[iPointDonor]->GetDomain()) {
- Buffer_Send_GlobalPoint[nLocalVertex_Donor] = donor_geometry->node[iPointDonor]->GetGlobalIndex();
- for (iDim = 0; iDim < nDim; iDim++)
- Buffer_Send_Coord[nLocalVertex_Donor*nDim+iDim] = donor_geometry->node[iPointDonor]->GetCoord(iDim);
-
- if (faces) {
- Normal = donor_geometry->vertex[markDonor][iVertexDonor]->GetNormal();
- for (iDim = 0; iDim < nDim; iDim++)
- Buffer_Send_Normal[nLocalVertex_Donor*nDim+iDim] = Normal[iDim];
- }
- nLocalVertex_Donor++;
- }
- }
- nBuffer_Coord = MaxLocalVertex_Donor*nDim;
- nBuffer_Point = MaxLocalVertex_Donor;
-
-#ifdef HAVE_MPI
- SU2_MPI::Allgather(Buffer_Send_Coord, nBuffer_Coord, MPI_DOUBLE, Buffer_Receive_Coord, nBuffer_Coord, MPI_DOUBLE, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_GlobalPoint, nBuffer_Point, MPI_LONG, Buffer_Receive_GlobalPoint, nBuffer_Point, MPI_LONG, MPI_COMM_WORLD);
- if (faces) {
- SU2_MPI::Allgather(Buffer_Send_Normal, nBuffer_Coord, MPI_DOUBLE, Buffer_Receive_Normal, nBuffer_Coord, MPI_DOUBLE, MPI_COMM_WORLD);
- }
-#else
- for (iVertex = 0; iVertex < nBuffer_Coord; iVertex++)
- Buffer_Receive_Coord[iVertex] = Buffer_Send_Coord[iVertex];
-
- for (iVertex = 0; iVertex < nBuffer_Point; iVertex++)
- Buffer_Receive_GlobalPoint[iVertex] = Buffer_Send_GlobalPoint[iVertex];
-
- if (faces) {
- for (iVertex = 0; iVertex < nBuffer_Coord; iVertex++)
- Buffer_Receive_Normal[iVertex] = Buffer_Send_Normal[iVertex];
- }
-#endif
-}
-
-int CInterpolator::Find_InterfaceMarker(CConfig *config, unsigned short val_marker_interface) {
-
- unsigned short nMarker = config->GetnMarker_All();
- unsigned short iMarker;
-
- for (iMarker = 0; iMarker < nMarker; iMarker++) {
-
- /*--- If the tag GetMarker_All_ZoneInterface(iMarker) equals the index we are looping at ---*/
- if (config->GetMarker_All_ZoneInterface(iMarker) == val_marker_interface ) {
-
- /*--- We have identified the identifier for the interface marker ---*/
- return iMarker;
- }
- }
-
- return -1;
-}
-
-
-void CInterpolator::ReconstructBoundary(unsigned long val_zone, int val_marker){
-
- CGeometry *geom = Geometry[val_zone][INST_0][MESH_0];
-
- unsigned long iVertex, jVertex, kVertex;
-
- unsigned long count, iTmp, *uptr, dPoint, EdgeIndex, jEdge, nEdges, nNodes, nVertex, iDim, nDim, iPoint;
-
- unsigned long nGlobalLinkedNodes, nLocalVertex, nLocalLinkedNodes;
-
- nDim = geom->GetnDim();
-
- if( val_marker != -1 )
- nVertex = geom->GetnVertex( val_marker );
- else
- nVertex = 0;
-
-
- su2double *Buffer_Send_Coord = new su2double [ nVertex * nDim ];
- unsigned long *Buffer_Send_GlobalPoint = new unsigned long [ nVertex ];
-
- unsigned long *Buffer_Send_nLinkedNodes = new unsigned long [ nVertex ];
- unsigned long *Buffer_Send_StartLinkedNodes = new unsigned long [ nVertex ];
- unsigned long **Aux_Send_Map = new unsigned long*[ nVertex ];
-
-#ifdef HAVE_MPI
- int nProcessor = size, iRank;
- unsigned long iTmp2, tmp_index, tmp_index_2;
-#endif
-
- /*--- Copy coordinates and point to the auxiliar vector ---*/
-
- nGlobalVertex = 0;
- nLocalVertex = 0;
- nLocalLinkedNodes = 0;
-
- for (iVertex = 0; iVertex < nVertex; iVertex++) {
-
- Buffer_Send_nLinkedNodes[iVertex] = 0;
- Aux_Send_Map[iVertex] = NULL;
-
- iPoint = geom->vertex[val_marker][iVertex]->GetNode();
-
- if (geom->node[iPoint]->GetDomain()) {
- Buffer_Send_GlobalPoint[nLocalVertex] = geom->node[iPoint]->GetGlobalIndex();
-
- for (iDim = 0; iDim < nDim; iDim++)
- Buffer_Send_Coord[nLocalVertex*nDim+iDim] = geom->node[iPoint]->GetCoord(iDim);
-
- nNodes = 0;
- nEdges = geom->node[iPoint]->GetnPoint();
-
- for (jEdge = 0; jEdge < nEdges; jEdge++){
- EdgeIndex = geom->node[iPoint]->GetEdge(jEdge);
-
- if( iPoint == geom->edge[EdgeIndex]->GetNode(0) )
- dPoint = geom->edge[EdgeIndex]->GetNode(1);
- else
- dPoint = geom->edge[EdgeIndex]->GetNode(0);
-
- if ( geom->node[dPoint]->GetVertex(val_marker) != -1 )
- nNodes++;
- }
-
- Buffer_Send_StartLinkedNodes[nLocalVertex] = nLocalLinkedNodes;
- Buffer_Send_nLinkedNodes[nLocalVertex] = nNodes;
-
- nLocalLinkedNodes += nNodes;
-
- Aux_Send_Map[nLocalVertex] = new unsigned long[ nNodes ];
- nNodes = 0;
-
- for (jEdge = 0; jEdge < nEdges; jEdge++){
- EdgeIndex = geom->node[iPoint]->GetEdge(jEdge);
-
- if( iPoint == geom->edge[EdgeIndex]->GetNode(0) )
- dPoint = geom->edge[EdgeIndex]->GetNode(1);
- else
- dPoint = geom->edge[EdgeIndex]->GetNode(0);
-
- if ( geom->node[dPoint]->GetVertex(val_marker) != -1 ){
- Aux_Send_Map[nLocalVertex][nNodes] = geom->node[dPoint]->GetGlobalIndex();
- nNodes++;
- }
- }
- nLocalVertex++;
- }
- }
-
- unsigned long *Buffer_Send_LinkedNodes = new unsigned long [ nLocalLinkedNodes ];
-
- nLocalLinkedNodes = 0;
-
- for (iVertex = 0; iVertex < nLocalVertex; iVertex++){
- for (jEdge = 0; jEdge < Buffer_Send_nLinkedNodes[iVertex]; jEdge++){
- Buffer_Send_LinkedNodes[nLocalLinkedNodes] = Aux_Send_Map[iVertex][jEdge];
- nLocalLinkedNodes++;
- }
- }
-
- for (iVertex = 0; iVertex < nVertex; iVertex++){
- if( Aux_Send_Map[iVertex] != NULL )
- delete [] Aux_Send_Map[iVertex];
- }
- delete [] Aux_Send_Map; Aux_Send_Map = NULL;
-
- /*--- Reconstruct boundary by gathering data from all ranks ---*/
-
-#ifdef HAVE_MPI
- SU2_MPI::Allreduce( &nLocalVertex, &nGlobalVertex, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&nLocalLinkedNodes, &nGlobalLinkedNodes, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
-#else
- nGlobalVertex = nLocalVertex;
- nGlobalLinkedNodes = nLocalLinkedNodes;
-#endif
-
- Buffer_Receive_Coord = new su2double [ nGlobalVertex * nDim ];
- Buffer_Receive_GlobalPoint = new long[ nGlobalVertex ];
- Buffer_Receive_Proc = new unsigned long[ nGlobalVertex ];
-
- Buffer_Receive_nLinkedNodes = new unsigned long[ nGlobalVertex ];
- Buffer_Receive_LinkedNodes = new unsigned long[ nGlobalLinkedNodes ];
- Buffer_Receive_StartLinkedNodes = new unsigned long[ nGlobalVertex ];
-
-#ifdef HAVE_MPI
- if (rank == MASTER_NODE){
-
- for (iVertex = 0; iVertex < nDim*nLocalVertex; iVertex++)
- Buffer_Receive_Coord[iVertex] = Buffer_Send_Coord[iVertex];
-
- for (iVertex = 0; iVertex < nLocalVertex; iVertex++){
- Buffer_Receive_GlobalPoint[iVertex] = Buffer_Send_GlobalPoint[iVertex];
- Buffer_Receive_Proc[iVertex] = MASTER_NODE;
- Buffer_Receive_nLinkedNodes[iVertex] = Buffer_Send_nLinkedNodes[iVertex];
- Buffer_Receive_StartLinkedNodes[iVertex] = Buffer_Send_StartLinkedNodes[iVertex];
- }
-
- for (iVertex = 0; iVertex < nLocalLinkedNodes; iVertex++)
- Buffer_Receive_LinkedNodes[iVertex] = Buffer_Send_LinkedNodes[iVertex];
-
- tmp_index = nLocalVertex;
- tmp_index_2 = nLocalLinkedNodes;
-
- for(iRank = 1; iRank < nProcessor; iRank++){
-
- SU2_MPI::Recv( &iTmp2, 1, MPI_UNSIGNED_LONG, iRank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
- SU2_MPI::Recv(&Buffer_Receive_LinkedNodes[tmp_index_2], iTmp2, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-
- SU2_MPI::Recv( &iTmp, 1, MPI_UNSIGNED_LONG, iRank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
- SU2_MPI::Recv(&Buffer_Receive_Coord[tmp_index*nDim], nDim*iTmp, MPI_DOUBLE, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-
- SU2_MPI::Recv( &Buffer_Receive_GlobalPoint[tmp_index], iTmp, MPI_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
- SU2_MPI::Recv( &Buffer_Receive_nLinkedNodes[tmp_index], iTmp, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
- SU2_MPI::Recv(&Buffer_Receive_StartLinkedNodes[tmp_index], iTmp, MPI_UNSIGNED_LONG, iRank, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-
- for (iVertex = 0; iVertex < iTmp; iVertex++){
- Buffer_Receive_Proc[ tmp_index + iVertex ] = iRank;
- Buffer_Receive_StartLinkedNodes[ tmp_index + iVertex ] += tmp_index_2;
- }
-
- tmp_index += iTmp;
- tmp_index_2 += iTmp2;
- }
- }
- else{
- SU2_MPI::Send( &nLocalLinkedNodes, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
- SU2_MPI::Send(Buffer_Send_LinkedNodes, nLocalLinkedNodes, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
-
- SU2_MPI::Send( &nLocalVertex, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
- SU2_MPI::Send(Buffer_Send_Coord, nDim * nLocalVertex, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
-
- SU2_MPI::Send( Buffer_Send_GlobalPoint, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
- SU2_MPI::Send( Buffer_Send_nLinkedNodes, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
- SU2_MPI::Send(Buffer_Send_StartLinkedNodes, nLocalVertex, MPI_UNSIGNED_LONG, 0, 1, MPI_COMM_WORLD);
- }
-#else
- for (iVertex = 0; iVertex < nDim * nGlobalVertex; iVertex++)
- Buffer_Receive_Coord[iVertex] = Buffer_Send_Coord[iVertex];
-
- for (iVertex = 0; iVertex < nGlobalVertex; iVertex++){
- Buffer_Receive_GlobalPoint[iVertex] = Buffer_Send_GlobalPoint[iVertex];
- Buffer_Receive_Proc[iVertex] = MASTER_NODE;
- Buffer_Receive_nLinkedNodes[iVertex] = Buffer_Send_nLinkedNodes[iVertex];
- Buffer_Receive_StartLinkedNodes[iVertex] = Buffer_Send_StartLinkedNodes[iVertex];
- }
-
- for (iVertex = 0; iVertex < nGlobalLinkedNodes; iVertex++)
- Buffer_Receive_LinkedNodes[iVertex] = Buffer_Send_LinkedNodes[iVertex];
-#endif
-
- if (rank == MASTER_NODE){
- for (iVertex = 0; iVertex < nGlobalVertex; iVertex++){
- count = 0;
- uptr = &Buffer_Receive_LinkedNodes[ Buffer_Receive_StartLinkedNodes[iVertex] ];
-
- for (jVertex = 0; jVertex < Buffer_Receive_nLinkedNodes[iVertex]; jVertex++){
- iTmp = uptr[ jVertex ];
- for (kVertex = 0; kVertex < nGlobalVertex; kVertex++){
- if( Buffer_Receive_GlobalPoint[kVertex] == long(iTmp) ){
- uptr[ jVertex ] = kVertex;
- count++;
- break;
- }
- }
-
- if( count != (jVertex+1) ){
- for (kVertex = jVertex; kVertex < Buffer_Receive_nLinkedNodes[iVertex]-1; kVertex++){
- uptr[ kVertex ] = uptr[ kVertex + 1];
- }
- Buffer_Receive_nLinkedNodes[iVertex]--;
- jVertex--;
- }
- }
- }
- }
-
-#ifdef HAVE_MPI
- SU2_MPI::Bcast( Buffer_Receive_Coord, nGlobalVertex * nDim, MPI_DOUBLE, 0, MPI_COMM_WORLD);
- SU2_MPI::Bcast(Buffer_Receive_GlobalPoint, nGlobalVertex, MPI_LONG, 0, MPI_COMM_WORLD);
- SU2_MPI::Bcast( Buffer_Receive_Proc, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD );
-
- SU2_MPI::Bcast( Buffer_Receive_nLinkedNodes, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
- SU2_MPI::Bcast(Buffer_Receive_StartLinkedNodes, nGlobalVertex, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
- SU2_MPI::Bcast( Buffer_Receive_LinkedNodes, nGlobalLinkedNodes, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
-#endif
-
- if( Buffer_Send_Coord != NULL) {delete [] Buffer_Send_Coord; Buffer_Send_Coord = NULL;}
- if( Buffer_Send_GlobalPoint != NULL) {delete [] Buffer_Send_GlobalPoint; Buffer_Send_GlobalPoint = NULL;}
- if( Buffer_Send_LinkedNodes != NULL) {delete [] Buffer_Send_LinkedNodes; Buffer_Send_LinkedNodes = NULL;}
- if( Buffer_Send_nLinkedNodes != NULL) {delete [] Buffer_Send_nLinkedNodes; Buffer_Send_nLinkedNodes = NULL;}
- if( Buffer_Send_StartLinkedNodes != NULL) {delete [] Buffer_Send_StartLinkedNodes; Buffer_Send_StartLinkedNodes = NULL;}
-}
-
-bool CInterpolator::CheckInterfaceBoundary(int markDonor, int markTarget){
-
- int Donor_check, Target_check;
-
- #ifdef HAVE_MPI
-
- int *Buffer_Recv_mark = NULL;
- int iRank, nProcessor = size;
-
- if (rank == MASTER_NODE)
- Buffer_Recv_mark = new int[nProcessor];
-
- Donor_check = -1;
- Target_check = -1;
-
- /*--- We gather a vector in MASTER_NODE to determine whether the boundary is not on the processor because of the partition or because the zone does not include it ---*/
-
- SU2_MPI::Gather(&markDonor , 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE)
- for (iRank = 0; iRank < nProcessor; iRank++)
- if( Buffer_Recv_mark[iRank] != -1 ){
- Donor_check = Buffer_Recv_mark[iRank];
- break;
- }
-
- SU2_MPI::Bcast(&Donor_check , 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
-
- SU2_MPI::Gather(&markTarget, 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE)
- for (iRank = 0; iRank < nProcessor; iRank++)
- if( Buffer_Recv_mark[iRank] != -1 ){
- Target_check = Buffer_Recv_mark[iRank];
- break;
- }
-
-
- SU2_MPI::Bcast(&Target_check, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE)
- delete [] Buffer_Recv_mark;
-
-#else
- Donor_check = markDonor;
- Target_check = markTarget;
-#endif
-
- if(Target_check == -1 || Donor_check == -1)
- return false;
- else
- return true;
-}
-
-su2double CInterpolator::PointsDistance(su2double *point_i, su2double *point_j){
-
- /*--- Compute distance between 2 points ---*/
-
- unsigned short iDim, nDim = donor_geometry->GetnDim();
- su2double m;
-
- m = 0 ;
- for(iDim = 0; iDim < nDim; iDim++)
- m += (point_j[iDim] - point_i[iDim])*(point_j[iDim] - point_i[iDim]);
-
- return sqrt(m);
-}
-
-/* Nearest Neighbor Interpolator */
-CNearestNeighbor::CNearestNeighbor(void): CInterpolator() { }
-
-CNearestNeighbor::CNearestNeighbor(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
-
- /*--- Initialize transfer coefficients between the zones ---*/
- Set_TransferCoeff(config);
-}
-
-CNearestNeighbor::~CNearestNeighbor() {}
-
-void CNearestNeighbor::Set_TransferCoeff(CConfig **config) {
-
- int iProcessor, pProcessor, nProcessor = size;
- int markDonor, markTarget;
-
- unsigned short nDim, iMarkerInt, nMarkerInt, iDonor;
-
- unsigned long nVertexDonor, nVertexTarget, Point_Target, jVertex, iVertexTarget;
- unsigned long Global_Point_Donor;
- long pGlobalPoint = 0;
-
- su2double *Coord_i, *Coord_j, dist, mindist, maxdist;
-
- /*--- Initialize variables --- */
-
- nMarkerInt = (int) ( config[donorZone]->GetMarker_n_ZoneInterface() / 2 );
-
- nDim = donor_geometry->GetnDim();
-
- iDonor = 0;
-
- Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
-
-
- /*--- Cycle over nMarkersInt interface to determine communication pattern ---*/
-
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
-
-
- /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
- markDonor = Find_InterfaceMarker(config[donorZone], iMarkerInt);
-
- /*--- On the target side: find the tag of the boundary sharing the interface ---*/
- markTarget = Find_InterfaceMarker(config[targetZone], iMarkerInt);
-
- /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
- if( !CheckInterfaceBoundary(markDonor, markTarget) )
- continue;
-
- if(markDonor != -1)
- nVertexDonor = donor_geometry->GetnVertex( markDonor );
- else
- nVertexDonor = 0;
-
- if(markTarget != -1)
- nVertexTarget = target_geometry->GetnVertex( markTarget );
- else
- nVertexTarget = 0;
-
- Buffer_Send_nVertex_Donor = new unsigned long [ 1 ];
-
- /* Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor */
- Determine_ArraySize(false, markDonor, markTarget, nVertexDonor, nDim);
-
- Buffer_Send_Coord = new su2double [ MaxLocalVertex_Donor * nDim ];
- Buffer_Send_GlobalPoint = new long [ MaxLocalVertex_Donor ];
- Buffer_Receive_Coord = new su2double [ nProcessor * MaxLocalVertex_Donor * nDim ];
- Buffer_Receive_GlobalPoint = new long [ nProcessor * MaxLocalVertex_Donor ];
-
- /*-- Collect coordinates, global points, and normal vectors ---*/
- Collect_VertexInfo( false, markDonor, markTarget, nVertexDonor, nDim );
-
- /*--- Compute the closest point to a Near-Field boundary point ---*/
- maxdist = 0.0;
-
- for (iVertexTarget = 0; iVertexTarget < nVertexTarget; iVertexTarget++) {
-
- Point_Target = target_geometry->vertex[markTarget][iVertexTarget]->GetNode();
-
- if ( target_geometry->node[Point_Target]->GetDomain() ) {
-
- target_geometry->vertex[markTarget][iVertexTarget]->SetnDonorPoints(1);
- target_geometry->vertex[markTarget][iVertexTarget]->Allocate_DonorInfo(); // Possible meme leak?
-
- /*--- Coordinates of the boundary point ---*/
- Coord_i = target_geometry->node[Point_Target]->GetCoord();
-
- mindist = 1E6;
- pProcessor = 0;
-
- /*--- Loop over all the boundaries to find the pair ---*/
-
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- for (jVertex = 0; jVertex < MaxLocalVertex_Donor; jVertex++) {
-
- Global_Point_Donor = iProcessor*MaxLocalVertex_Donor+jVertex;
-
- if (Buffer_Receive_GlobalPoint[Global_Point_Donor] != -1){
-
- Coord_j = &Buffer_Receive_Coord[ Global_Point_Donor*nDim];
-
- dist = PointsDistance(Coord_i, Coord_j);
-
- if (dist < mindist) {
- mindist = dist; pProcessor = iProcessor;
- pGlobalPoint = Buffer_Receive_GlobalPoint[Global_Point_Donor];
- }
-
- if (dist == 0.0) break;
- }
- }
- }
-
- /*--- Store the value of the pair ---*/
- maxdist = max(maxdist, mindist);
- target_geometry->vertex[markTarget][iVertexTarget]->SetInterpDonorPoint(iDonor, pGlobalPoint);
- target_geometry->vertex[markTarget][iVertexTarget]->SetInterpDonorProcessor(iDonor, pProcessor);
- target_geometry->vertex[markTarget][iVertexTarget]->SetDonorCoeff(iDonor, 1.0);
- }
- }
-
- delete[] Buffer_Send_Coord;
- delete[] Buffer_Send_GlobalPoint;
-
- delete[] Buffer_Receive_Coord;
- delete[] Buffer_Receive_GlobalPoint;
-
- delete[] Buffer_Send_nVertex_Donor;
-
- }
-
- delete[] Buffer_Receive_nVertex_Donor;
-}
-
-
-
-CIsoparametric::CIsoparametric(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
-
- /*--- Initialize transfer coefficients between the zones ---*/
- Set_TransferCoeff(config);
-
- /*--- For fluid-structure interaction data interpolated with have nDim dimensions ---*/
- // InitializeData(Zones,nDim);
-}
-
-CIsoparametric::~CIsoparametric() {}
-
-void CIsoparametric::Set_TransferCoeff(CConfig **config) {
- unsigned long iVertex, jVertex;
- unsigned long dPoint, inode, jElem, nElem;
- unsigned short iDim, iDonor=0, iFace;
-
- unsigned short nDim = donor_geometry->GetnDim();
-
- unsigned short nMarkerInt;
- unsigned short iMarkerInt;
-
- int markDonor=0, markTarget=0;
-
- long donor_elem=0, temp_donor=0;
- unsigned int nNodes=0;
- /*--- Restricted to 2-zone for now ---*/
- unsigned int nFaces=1; //For 2D cases, we want to look at edges, not faces, as the 'interface'
- bool face_on_marker=true;
-
- unsigned long nVertexDonor = 0, nVertexTarget= 0;
- unsigned long Point_Target = 0;
-
- unsigned long iVertexDonor, iPointDonor = 0;
- int iProcessor;
-
- unsigned long nLocalFace_Donor = 0, nLocalFaceNodes_Donor=0;
-
- unsigned long faceindex;
-
- su2double dist = 0.0, mindist=1E6, *Coord, *Coord_i;
- su2double myCoeff[10]; // Maximum # of donor points
- su2double *Normal;
- su2double *projected_point = new su2double[nDim];
- su2double tmp, tmp2;
- su2double storeCoeff[10];
- unsigned long storeGlobal[10];
- int storeProc[10];
-
- int nProcessor = size;
- Coord = new su2double[nDim];
- Normal = new su2double[nDim];
-
- nMarkerInt = (config[donorZone]->GetMarker_n_ZoneInterface())/2;
-
- /*--- For the number of markers on the interface... ---*/
- for (iMarkerInt=1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
- /*--- Procedure:
- * -Loop through vertices of the aero grid
- * -Find nearest element and allocate enough space in the aero grid donor point info
- * -set the transfer coefficient values
- */
-
- /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
- markDonor = Find_InterfaceMarker(config[donorZone], iMarkerInt);
-
- /*--- On the target side: find the tag of the boundary sharing the interface ---*/
- markTarget = Find_InterfaceMarker(config[targetZone], iMarkerInt);
-
- /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
- if( !CheckInterfaceBoundary(markDonor, markTarget) )
- continue;
-
- if(markDonor != -1)
- nVertexDonor = donor_geometry->GetnVertex( markDonor );
- else
- nVertexDonor = 0;
-
- if(markTarget != -1)
- nVertexTarget = target_geometry->GetnVertex( markTarget );
- else
- nVertexTarget = 0;
-
- Buffer_Send_nVertex_Donor = new unsigned long [1];
- Buffer_Send_nFace_Donor = new unsigned long [1];
- Buffer_Send_nFaceNodes_Donor = new unsigned long [1];
-
- Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
- Buffer_Receive_nFace_Donor = new unsigned long [nProcessor];
- Buffer_Receive_nFaceNodes_Donor = new unsigned long [nProcessor];
-
- /* Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor */
- Determine_ArraySize(true, markDonor, markTarget, nVertexDonor, nDim);
-
- Buffer_Send_Coord = new su2double [MaxLocalVertex_Donor*nDim];
- Buffer_Send_Normal = new su2double [MaxLocalVertex_Donor*nDim];
- Buffer_Send_GlobalPoint = new long [MaxLocalVertex_Donor];
-
- Buffer_Receive_Coord = new su2double [nProcessor*MaxLocalVertex_Donor*nDim];
- Buffer_Receive_Normal = new su2double [nProcessor*MaxLocalVertex_Donor*nDim];
- Buffer_Receive_GlobalPoint = new long [nProcessor*MaxLocalVertex_Donor];
-
- /*-- Collect coordinates, global points, and normal vectors ---*/
- Collect_VertexInfo(true, markDonor,markTarget,nVertexDonor,nDim);
-
- Buffer_Send_FaceIndex = new unsigned long[MaxFace_Donor];
- Buffer_Send_FaceNodes = new unsigned long[MaxFaceNodes_Donor];
- Buffer_Send_FaceProc = new unsigned long[MaxFaceNodes_Donor];
-
- Buffer_Receive_FaceIndex = new unsigned long[MaxFace_Donor*nProcessor];
- Buffer_Receive_FaceNodes = new unsigned long[MaxFaceNodes_Donor*nProcessor];
- Buffer_Receive_FaceProc = new unsigned long[MaxFaceNodes_Donor*nProcessor];
-
- nLocalFace_Donor=0;
- nLocalFaceNodes_Donor=0;
-
- /*--- Collect Face info ---*/
-
- for (iVertex = 0; iVertex < MaxFace_Donor; iVertex++) {
- Buffer_Send_FaceIndex[iVertex] = 0;
- }
- for (iVertex=0; iVertexvertex[markDonor][iVertexDonor]->GetNode();
-
- if (donor_geometry->node[iPointDonor]->GetDomain()) {
-
- if (nDim==3) nElem = donor_geometry->node[iPointDonor]->GetnElem();
- else nElem =donor_geometry->node[iPointDonor]->GetnPoint();
-
- for (jElem=0; jElem < nElem; jElem++) {
- if (nDim==3) {
- temp_donor = donor_geometry->node[iPointDonor]->GetElem(jElem);
- nFaces = donor_geometry->elem[temp_donor]->GetnFaces();
- for (iFace=0; iFaceelem[temp_donor]->GetnNodesFace(iFace);
- for (iDonor=0; iDonorelem[temp_donor]->GetFaces(iFace, iDonor);
- dPoint = donor_geometry->elem[temp_donor]->GetNode(inode);
- face_on_marker = (face_on_marker && (donor_geometry->node[dPoint]->GetVertex(markDonor) !=-1));
- }
-
- if (face_on_marker ) {
- for (iDonor=0; iDonorelem[temp_donor]->GetFaces(iFace, iDonor);
- dPoint = donor_geometry->elem[temp_donor]->GetNode(inode);
- // Match node on the face to the correct global index
- long jGlobalPoint = donor_geometry->node[dPoint]->GetGlobalIndex();
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- for (jVertex = 0; jVertex < Buffer_Receive_nVertex_Donor[iProcessor]; jVertex++) {
- if (jGlobalPoint == Buffer_Receive_GlobalPoint[MaxLocalVertex_Donor*iProcessor+jVertex]) {
- Buffer_Send_FaceNodes[nLocalFaceNodes_Donor]=MaxLocalVertex_Donor*iProcessor+jVertex;
- Buffer_Send_FaceProc[nLocalFaceNodes_Donor]=iProcessor;
- }
- }
- }
- nLocalFaceNodes_Donor++; // Increment total number of face-nodes / processor
- }
- /* Store the indices */
- Buffer_Send_FaceIndex[nLocalFace_Donor+1] = Buffer_Send_FaceIndex[nLocalFace_Donor]+nNodes;
- nLocalFace_Donor++; // Increment number of faces / processor
- }
- }
- }
- else {
- /*-- Determine whether this face/edge is on the marker --*/
- face_on_marker=true;
- for (iDonor=0; iDonornode[iPointDonor]->GetEdge(jElem);
- dPoint = donor_geometry->edge[inode]->GetNode(iDonor);
- face_on_marker = (face_on_marker && (donor_geometry->node[dPoint]->GetVertex(markDonor) !=-1));
- }
- if (face_on_marker ) {
- for (iDonor=0; iDonornode[iPointDonor]->GetEdge(jElem);
- dPoint = donor_geometry->edge[inode]->GetNode(iDonor);
- // Match node on the face to the correct global index
- long jGlobalPoint = donor_geometry->node[dPoint]->GetGlobalIndex();
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- for (jVertex = 0; jVertex < Buffer_Receive_nVertex_Donor[iProcessor]; jVertex++) {
- if (jGlobalPoint == Buffer_Receive_GlobalPoint[MaxLocalVertex_Donor*iProcessor+jVertex]) {
- Buffer_Send_FaceNodes[nLocalFaceNodes_Donor]=MaxLocalVertex_Donor*iProcessor+jVertex;
- Buffer_Send_FaceProc[nLocalFaceNodes_Donor]=iProcessor;
- }
- }
- }
- nLocalFaceNodes_Donor++; // Increment total number of face-nodes / processor
- }
- /* Store the indices */
- Buffer_Send_FaceIndex[nLocalFace_Donor+1] = Buffer_Send_FaceIndex[nLocalFace_Donor]+nNodes;
- nLocalFace_Donor++; // Increment number of faces / processor
- }
- }
- }
- }
- }
-
- //Buffer_Send_FaceIndex[nLocalFace_Donor+1] = MaxFaceNodes_Donor*rank+nLocalFaceNodes_Donor;
-#ifdef HAVE_MPI
- SU2_MPI::Allgather(Buffer_Send_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, Buffer_Receive_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_FaceProc, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, Buffer_Receive_FaceProc, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG, Buffer_Receive_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
-#else
- for (iFace=0; iFacevertex[markTarget][iVertex]->GetNode();
-
- if (target_geometry->node[Point_Target]->GetDomain()) {
-
- Coord_i = target_geometry->node[Point_Target]->GetCoord();
- /*---Loop over the faces previously communicated/stored ---*/
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
-
- nFaces = (unsigned int)Buffer_Receive_nFace_Donor[iProcessor];
-
- for (iFace = 0; iFace< nFaces; iFace++) {
- /*--- ---*/
-
- nNodes = (unsigned int)Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace+1] -
- (unsigned int)Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace];
-
- su2double *X = new su2double[nNodes*(nDim+1)];
- faceindex = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace]; // first index of this face
- for (iDonor=0; iDonorvertex[markTarget][iVertex]->SetDonorElem(donor_elem); // in 2D is nearest neighbor
- target_geometry->vertex[markTarget][iVertex]->SetnDonorPoints(nNodes);
- for (iDonor=0; iDonorvertex[markTarget][iVertex]->GetnDonorPoints();
- target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo();
-
- for (iDonor=0; iDonorvertex[markTarget][iVertex]->SetInterpDonorPoint(iDonor,storeGlobal[iDonor]);
- //cout <vertex[markTarget][iVertex]->SetDonorCoeff(iDonor,storeCoeff[iDonor]);
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, storeProc[iDonor]);
- }
- }
- }
-
- delete[] Buffer_Send_nVertex_Donor;
- delete[] Buffer_Send_nFace_Donor;
- delete[] Buffer_Send_nFaceNodes_Donor;
-
- delete[] Buffer_Receive_nVertex_Donor;
- delete[] Buffer_Receive_nFace_Donor;
- delete[] Buffer_Receive_nFaceNodes_Donor;
-
- delete[] Buffer_Send_Coord;
- delete[] Buffer_Send_Normal;
- delete[] Buffer_Send_GlobalPoint;
-
- delete[] Buffer_Receive_Coord;
- delete[] Buffer_Receive_Normal;
- delete[] Buffer_Receive_GlobalPoint;
-
- delete[] Buffer_Send_FaceIndex;
- delete[] Buffer_Send_FaceNodes;
- delete[] Buffer_Send_FaceProc;
-
- delete[] Buffer_Receive_FaceIndex;
- delete[] Buffer_Receive_FaceNodes;
- delete[] Buffer_Receive_FaceProc;
- }
- delete [] Coord;
- delete [] Normal;
-
- delete [] projected_point;
-}
-
-void CIsoparametric::Isoparameters(unsigned short nDim, unsigned short nDonor,
- su2double *X, su2double *xj, su2double *isoparams) {
- short iDonor,iDim,k; // indices
- su2double tmp, tmp2;
-
- su2double *x = new su2double[nDim+1];
- su2double *x_tmp = new su2double[nDim+1];
- su2double *Q = new su2double[nDonor*nDonor];
- su2double *R = new su2double[nDonor*nDonor];
- su2double *A = new su2double[(nDim+2)*nDonor];
- su2double *A2 = NULL;
- su2double *x2 = new su2double[nDim+1];
-
- bool *test = new bool[nDim+1];
- bool *testi = new bool[nDim+1];
-
- su2double eps = 1E-10;
-
- short n = nDim+1;
-
- if (nDonor>2) {
- /*--- Create Matrix A: 1st row all 1's, 2nd row x coordinates, 3rd row y coordinates, etc ---*/
- /*--- Right hand side is [1, \vec{x}']'---*/
- for (iDonor=0; iDonoreps && iDonor=0; iDonor--) {
- if (R[iDonor*nDonor+iDonor]>eps)
- isoparams[iDonor]=x_tmp[iDonor]/R[iDonor*nDonor+iDonor];
- else
- isoparams[iDonor]=0;
- for (k=0; k1.0) xi=1.0;
- if (xi<-1.0) xi=-1.0;
- if (eta>1.0) eta=1.0;
- if (eta<-1.0) eta=-1.0;
- isoparams[0]=0.25*(1-xi)*(1-eta);
- isoparams[1]=0.25*(1+xi)*(1-eta);
- isoparams[2]=0.25*(1+xi)*(1+eta);
- isoparams[3]=0.25*(1-xi)*(1+eta);
-
- }
- if (nDonor<4) {
- tmp = 0.0; // value for normalization
- tmp2=0; // check for maximum value, to be used to id nearest neighbor if necessary
- k=0; // index for maximum value
- for (iDonor=0; iDonor< nDonor; iDonor++) {
- if (isoparams[iDonor]>tmp2) {
- k=iDonor;
- tmp2=isoparams[iDonor];
- }
- // [0,1]
- if (isoparams[iDonor]<0) isoparams[iDonor]=0;
- if (isoparams[iDonor]>1) isoparams[iDonor] = 1;
- tmp +=isoparams[iDonor];
- }
- if (tmp>0)
- for (iDonor=0; iDonor< nDonor; iDonor++)
- isoparams[iDonor]=isoparams[iDonor]/tmp;
- else {
- isoparams[k] = 1.0;
- }
- }
-
- delete [] x;
- delete [] x_tmp;
- delete [] Q;
- delete [] R;
- delete [] A;
- if (A2 != NULL) delete [] A2;
- delete [] x2;
-
- delete [] test;
- delete [] testi;
-
-}
-
-
-/* Mirror Interpolator */
-CMirror::CMirror(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
-
- /*--- Initialize transfer coefficients between the zones ---*/
- Set_TransferCoeff(config);
-
-}
-
-CMirror::~CMirror() {}
-
-void CMirror::Set_TransferCoeff(CConfig **config) {
- unsigned long iVertex, jVertex;
- unsigned long iPoint;
- unsigned short iDonor=0, iFace=0, iTarget=0;
-
- unsigned short nMarkerInt;
- unsigned short iMarkerInt;
-
- int markDonor=0, markTarget=0;
-
- unsigned int nNodes=0, iNodes=0;
- unsigned long nVertexDonor = 0, nVertexTarget= 0;
- unsigned long Point_Donor = 0;
- unsigned long pGlobalPoint = 0;
- int iProcessor;
-
- unsigned long nLocalFace_Donor = 0, nLocalFaceNodes_Donor=0;
-
- unsigned long faceindex;
-
- int nProcessor = size;
-
- su2double *Buffer_Send_Coeff, *Buffer_Receive_Coeff;
- su2double coeff;
-
- /*--- Number of markers on the interface ---*/
- nMarkerInt = (config[targetZone]->GetMarker_n_ZoneInterface())/2;
-
- /*--- For the number of markers on the interface... ---*/
- for (iMarkerInt=1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
- /*--- Procedure:
- * -Loop through vertices of the aero grid
- * -Find nearest element and allocate enough space in the aero grid donor point info
- * -set the transfer coefficient values
- */
-
- /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
- markDonor = Find_InterfaceMarker(config[donorZone], iMarkerInt);
-
- /*--- On the target side: find the tag of the boundary sharing the interface ---*/
- markTarget = Find_InterfaceMarker(config[targetZone], iMarkerInt);
-
- /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
- if( !CheckInterfaceBoundary(markDonor, markTarget) )
- continue;
-
- if(markDonor != -1)
- nVertexDonor = donor_geometry->GetnVertex( markDonor );
- else
- nVertexDonor = 0;
-
- if(markTarget != -1)
- nVertexTarget = target_geometry->GetnVertex( markTarget );
- else
- nVertexTarget = 0;
-
- /*-- Collect the number of donor nodes: re-use 'Face' containers --*/
- nLocalFace_Donor=0;
- nLocalFaceNodes_Donor=0;
- for (jVertex = 0; jVertexvertex[markDonor][jVertex]->GetNode(); // Local index of jVertex
-
- if (donor_geometry->node[Point_Donor]->GetDomain()) {
- nNodes = donor_geometry->vertex[markDonor][jVertex]->GetnDonorPoints();
- nLocalFaceNodes_Donor+=nNodes;
- nLocalFace_Donor++;
- }
- }
- Buffer_Send_nFace_Donor= new unsigned long [1];
- Buffer_Send_nFaceNodes_Donor= new unsigned long [1];
-
- Buffer_Receive_nFace_Donor = new unsigned long [nProcessor];
- Buffer_Receive_nFaceNodes_Donor = new unsigned long [nProcessor];
-
- Buffer_Send_nFace_Donor[0] = nLocalFace_Donor;
- Buffer_Send_nFaceNodes_Donor[0] = nLocalFaceNodes_Donor;
-
- /*--- Send Interface vertex information --*/
-#ifdef HAVE_MPI
- SU2_MPI::Allreduce(&nLocalFaceNodes_Donor, &MaxFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&nLocalFace_Donor, &MaxFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_nFace_Donor, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nFace_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nFaceNodes_Donor, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- MaxFace_Donor++;
-#else
- nGlobalFace_Donor = nLocalFace_Donor;
- nGlobalFaceNodes_Donor = nLocalFaceNodes_Donor;
- MaxFaceNodes_Donor = nLocalFaceNodes_Donor;
- MaxFace_Donor = nLocalFace_Donor+1;
- Buffer_Receive_nFace_Donor[0] = Buffer_Send_nFace_Donor[0];
- Buffer_Receive_nFaceNodes_Donor[0] = Buffer_Send_nFaceNodes_Donor[0];
-#endif
-
- /*-- Send donor info --*/
- Buffer_Send_FaceIndex = new unsigned long[MaxFace_Donor];
- Buffer_Send_FaceNodes = new unsigned long[MaxFaceNodes_Donor];
- Buffer_Send_GlobalPoint = new long[MaxFaceNodes_Donor];
- Buffer_Send_Coeff = new su2double[MaxFaceNodes_Donor];
-
- Buffer_Receive_FaceIndex= new unsigned long[MaxFace_Donor*nProcessor];
- Buffer_Receive_FaceNodes= new unsigned long[MaxFaceNodes_Donor*nProcessor];
- Buffer_Receive_GlobalPoint = new long[MaxFaceNodes_Donor*nProcessor];
- Buffer_Receive_Coeff = new su2double[MaxFaceNodes_Donor*nProcessor];
-
- for (iVertex=0; iVertexvertex[markDonor][jVertex]->GetNode(); // Local index of jVertex
- if (donor_geometry->node[Point_Donor]->GetDomain()) {
- nNodes = donor_geometry->vertex[markDonor][jVertex]->GetnDonorPoints();
- for (iDonor=0; iDonornode[Point_Donor]->GetGlobalIndex();
- Buffer_Send_GlobalPoint[nLocalFaceNodes_Donor] =
- donor_geometry->vertex[markDonor][jVertex]->GetInterpDonorPoint(iDonor);
- Buffer_Send_Coeff[nLocalFaceNodes_Donor] =
- donor_geometry->vertex[markDonor][jVertex]->GetDonorCoeff(iDonor);
- nLocalFaceNodes_Donor++;
- }
- Buffer_Send_FaceIndex[nLocalFace_Donor+1] =Buffer_Send_FaceIndex[nLocalFace_Donor]+nNodes;
- nLocalFace_Donor++;
- }
- }
-
-#ifdef HAVE_MPI
- SU2_MPI::Allgather(Buffer_Send_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, Buffer_Receive_FaceNodes, MaxFaceNodes_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_GlobalPoint, MaxFaceNodes_Donor, MPI_LONG,Buffer_Receive_GlobalPoint, MaxFaceNodes_Donor, MPI_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_Coeff, MaxFaceNodes_Donor, MPI_DOUBLE,Buffer_Receive_Coeff, MaxFaceNodes_Donor, MPI_DOUBLE, MPI_COMM_WORLD);
- SU2_MPI::Allgather(Buffer_Send_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG, Buffer_Receive_FaceIndex, MaxFace_Donor, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
-#else
- for (iFace=0; iFacevertex[markTarget][iVertex]->GetNode();
- if (target_geometry->node[iPoint]->GetDomain()) {
- long Global_Point = target_geometry->node[iPoint]->GetGlobalIndex();
- nNodes = 0;
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- for (iFace = 0; iFace < Buffer_Receive_nFace_Donor[iProcessor]; iFace++) {
- faceindex = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace]; // first index of this face
- iNodes = (unsigned int)Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace+1]- (unsigned int)faceindex;
- for (iTarget=0; iTargetvertex[markTarget][iVertex]->SetnDonorPoints(nNodes);
- target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo();
-
- iDonor = 0;
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- for (iFace = 0; iFace < Buffer_Receive_nFace_Donor[iProcessor]; iFace++) {
-
- faceindex = Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace]; // first index of this face
- iNodes = (unsigned int)Buffer_Receive_FaceIndex[iProcessor*MaxFace_Donor+iFace+1]- (unsigned int)faceindex;
- for (iTarget=0; iTargetvertex[markTarget][iVertex]->SetInterpDonorPoint(iDonor,pGlobalPoint);
- target_geometry->vertex[markTarget][iVertex]->SetDonorCoeff(iDonor,coeff);
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, iProcessor);
- iDonor++;
- }
- }
- }
- }
- }
- }
- delete[] Buffer_Send_nFace_Donor;
- delete[] Buffer_Send_nFaceNodes_Donor;
-
- delete[] Buffer_Receive_nFace_Donor;
- delete[] Buffer_Receive_nFaceNodes_Donor;
-
- delete[] Buffer_Send_FaceIndex;
- delete[] Buffer_Send_FaceNodes;
- delete[] Buffer_Send_GlobalPoint;
- delete[] Buffer_Send_Coeff;
-
- delete[] Buffer_Receive_FaceIndex;
- delete[] Buffer_Receive_FaceNodes;
- delete[] Buffer_Receive_GlobalPoint;
- delete[] Buffer_Receive_Coeff;
-
- }
-}
-
-CSlidingMesh::CSlidingMesh(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone){
-
- /*--- Initialize transfer coefficients between the zones ---*/
- Set_TransferCoeff(config);
-
- /*--- For fluid-structure interaction data interpolated with have nDim dimensions ---*/
- // InitializeData(Zones,nDim);
-}
-
-CSlidingMesh::~CSlidingMesh(){}
-
-void CSlidingMesh::Set_TransferCoeff(CConfig **config){
-
- /* --- This routine sets the transfer coefficient for sliding mesh approach --- */
-
- /*
- * The algorithm is based on Rinaldi et al. "Flux-conserving treatment of non-conformal interfaces
- * for finite-volume discritization of conservaation laws" 2015, Comp. Fluids, 120, pp 126-139
- */
-
- /* 0 - Variable declaration - */
-
- /* --- General variables --- */
-
- bool check;
-
- unsigned short iDim, nDim;
-
- unsigned long ii, jj, *uptr;
- unsigned long vPoint;
- unsigned long iEdgeVisited, nEdgeVisited, iNodeVisited;
- unsigned long nAlreadyVisited, nToVisit, StartVisited;
-
- unsigned long *alreadyVisitedDonor, *ToVisit, *tmpVect;
- unsigned long *storeProc, *tmp_storeProc;
-
- su2double dTMP;
- su2double *Coeff_Vect, *tmp_Coeff_Vect;
-
- /* --- Geometrical variables --- */
-
- su2double *Coord_i, *Coord_j, dist, mindist, *Normal;
- su2double Area, Area_old, tmp_Area;
- su2double LineIntersectionLength, *Direction, length;
-
-
- /* --- Markers Variables --- */
-
- unsigned short iMarkerInt, nMarkerInt;
-
- unsigned long iVertex, nVertexTarget;
-
- int markDonor, markTarget;
-
- /* --- Target variables --- */
-
- unsigned long target_iPoint, jVertexTarget;
- unsigned long nEdges_target, nNode_target;
-
- unsigned long *Target_nLinkedNodes, *Target_LinkedNodes, *Target_StartLinkedNodes, *target_segment;
- unsigned long *Target_Proc;
- long *Target_GlobalPoint, *Donor_GlobalPoint;
-
- su2double *TargetPoint_Coord, *target_iMidEdge_point, *target_jMidEdge_point, **target_element;
-
- /* --- Donor variables --- */
-
- unsigned long donor_StartIndex, donor_forward_point, donor_backward_point, donor_iPoint, donor_OldiPoint;
- unsigned long nEdges_donor, nNode_donor, nGlobalVertex_Donor;
-
- unsigned long nDonorPoints, iDonor;
- unsigned long *Donor_Vect, *tmp_Donor_Vect;
- unsigned long *Donor_nLinkedNodes, *Donor_LinkedNodes, *Donor_StartLinkedNodes;
- unsigned long *Donor_Proc;
-
- su2double *donor_iMidEdge_point, *donor_jMidEdge_point;
- su2double **donor_element, *DonorPoint_Coord;
-
- /* 1 - Variable pre-processing - */
-
- nDim = donor_geometry->GetnDim();
-
- /*--- Setting up auxiliary vectors ---*/
-
- Donor_Vect = NULL;
- Coeff_Vect = NULL;
- storeProc = NULL;
-
- tmp_Donor_Vect = NULL;
- tmp_Coeff_Vect = NULL;
- tmp_storeProc = NULL;
-
- Normal = new su2double[nDim];
- Direction = new su2double[nDim];
-
-
- /* 2 - Find boundary tag between touching grids */
-
- /*--- Number of markers on the FSI interface ---*/
- nMarkerInt = (int)( config[ donorZone ]->GetMarker_n_ZoneInterface() ) / 2;
-
- /*--- For the number of markers on the interface... ---*/
- for ( iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++ ){
-
- /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
- markDonor = Find_InterfaceMarker(config[donorZone], iMarkerInt);
-
- /*--- On the target side: find the tag of the boundary sharing the interface ---*/
- markTarget = Find_InterfaceMarker(config[targetZone], iMarkerInt);
-
- /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
- if( !CheckInterfaceBoundary(markDonor, markTarget) )
- continue;
-
- if(markTarget != -1)
- nVertexTarget = target_geometry->GetnVertex( markTarget );
- else
- nVertexTarget = 0;
-
- /*
- 3 -Reconstruct the boundaries from parallel partitioning
- */
-
- /*--- Target boundary ---*/
- ReconstructBoundary(targetZone, markTarget);
-
- nGlobalVertex_Target = nGlobalVertex;
-
- TargetPoint_Coord = Buffer_Receive_Coord;
- Target_GlobalPoint = Buffer_Receive_GlobalPoint;
- Target_nLinkedNodes = Buffer_Receive_nLinkedNodes;
- Target_StartLinkedNodes = Buffer_Receive_StartLinkedNodes;
- Target_LinkedNodes = Buffer_Receive_LinkedNodes;
- Target_Proc = Buffer_Receive_Proc;
-
- /*--- Donor boundary ---*/
- ReconstructBoundary(donorZone, markDonor);
-
- nGlobalVertex_Donor = nGlobalVertex;
-
- DonorPoint_Coord = Buffer_Receive_Coord;
- Donor_GlobalPoint = Buffer_Receive_GlobalPoint;
- Donor_nLinkedNodes = Buffer_Receive_nLinkedNodes;
- Donor_StartLinkedNodes = Buffer_Receive_StartLinkedNodes;
- Donor_LinkedNodes = Buffer_Receive_LinkedNodes;
- Donor_Proc = Buffer_Receive_Proc;
-
- /*--- Starts building the supermesh layer (2D or 3D) ---*/
- /* - For each target node, it first finds the closest donor point
- * - Then it creates the supermesh in the close proximity of the target point:
- * - Starting from the closest donor node, it expands the supermesh by including
- * donor elements neighboring the initial one, until the overall target area is fully covered.
- */
-
- if(nDim == 2){
-
- target_iMidEdge_point = new su2double[nDim];
- target_jMidEdge_point = new su2double[nDim];
-
- donor_iMidEdge_point = new su2double[nDim];
- donor_jMidEdge_point = new su2double[nDim];
-
- /*--- Starts with supermesh reconstruction ---*/
-
- target_segment = new unsigned long[2];
-
- for (iVertex = 0; iVertex < nVertexTarget; iVertex++) {
-
- nDonorPoints = 0;
-
- /*--- Stores coordinates of the target node ---*/
-
- target_iPoint = target_geometry->vertex[markTarget][iVertex]->GetNode();
-
- if (target_geometry->node[target_iPoint]->GetDomain()){
-
- Coord_i = target_geometry->node[target_iPoint]->GetCoord();
-
- /*--- Brute force to find the closest donor_node ---*/
-
- mindist = 1E6;
- donor_StartIndex = 0;
-
- for (donor_iPoint = 0; donor_iPoint < nGlobalVertex_Donor; donor_iPoint++) {
-
- Coord_j = &DonorPoint_Coord[ donor_iPoint * nDim ];
-
- dist = PointsDistance(Coord_i, Coord_j);
-
- if (dist < mindist) {
- mindist = dist;
- donor_StartIndex = donor_iPoint;
- }
-
- if (dist == 0.0){
- donor_StartIndex = donor_iPoint;
- break;
- }
- }
-
- donor_iPoint = donor_StartIndex;
- donor_OldiPoint = donor_iPoint;
-
- /*--- Contruct information regarding the target cell ---*/
-
- long dPoint = target_geometry->node[target_iPoint]->GetGlobalIndex();
- for (jVertexTarget = 0; jVertexTarget < nGlobalVertex_Target; jVertexTarget++)
- if( dPoint == Target_GlobalPoint[jVertexTarget] )
- break;
-
- if ( Target_nLinkedNodes[jVertexTarget] == 1 ){
- target_segment[0] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] ];
- target_segment[1] = jVertexTarget;
- }
- else{
- target_segment[0] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] ];
- target_segment[1] = Target_LinkedNodes[ Target_StartLinkedNodes[jVertexTarget] + 1];
- }
-
- dTMP = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- target_iMidEdge_point[iDim] = ( TargetPoint_Coord[ nDim * target_segment[0] + iDim ] + target_geometry->node[ target_iPoint ]->GetCoord(iDim) ) / 2;
- target_jMidEdge_point[iDim] = ( TargetPoint_Coord[ nDim * target_segment[1] + iDim ] + target_geometry->node[ target_iPoint ]->GetCoord(iDim) ) / 2;
-
- Direction[iDim] = target_jMidEdge_point[iDim] - target_iMidEdge_point[iDim];
- dTMP += Direction[iDim] * Direction[iDim];
- }
-
- dTMP = sqrt(dTMP);
- for(iDim = 0; iDim < nDim; iDim++)
- Direction[iDim] /= dTMP;
-
- length = PointsDistance(target_iMidEdge_point, target_jMidEdge_point);
-
- check = false;
-
- /*--- Proceeds along the forward direction (depending on which connected boundary node is found first) ---*/
-
- while( !check ){
-
- /*--- Proceeds until the value of the intersection area is null ---*/
-
- if ( Donor_nLinkedNodes[donor_iPoint] == 1 ){
- donor_forward_point = Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
- donor_backward_point = donor_iPoint;
- }
- else{
- uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
-
- if( donor_OldiPoint != uptr[0] ){
- donor_forward_point = uptr[0];
- donor_backward_point = uptr[1];
- }
- else{
- donor_forward_point = uptr[1];
- donor_backward_point = uptr[0];
- }
- }
-
- if(donor_iPoint >= nGlobalVertex_Donor){
- check = true;
- continue;
- }
-
- for(iDim = 0; iDim < nDim; iDim++){
- donor_iMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_forward_point * nDim + iDim] + DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
- donor_jMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_backward_point * nDim + iDim] + DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
- }
-
- LineIntersectionLength = ComputeLineIntersectionLength(target_iMidEdge_point, target_jMidEdge_point, donor_iMidEdge_point, donor_jMidEdge_point, Direction);
-
- if ( LineIntersectionLength == 0.0 ){
- check = true;
- continue;
- }
-
- /*--- In case the element intersects the target cell, update the auxiliary communication data structure ---*/
-
- tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
- tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
- tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
-
- for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
- tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
- tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
- tmp_storeProc[iDonor] = storeProc[iDonor];
- }
-
- tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
- tmp_Coeff_Vect[ nDonorPoints ] = LineIntersectionLength / length;
- tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
-
- if (Donor_Vect != NULL) delete [] Donor_Vect;
- if (Coeff_Vect != NULL) delete [] Coeff_Vect;
- if (storeProc != NULL) delete [] storeProc;
-
- Donor_Vect = tmp_Donor_Vect;
- Coeff_Vect = tmp_Coeff_Vect;
- storeProc = tmp_storeProc;
-
- donor_OldiPoint = donor_iPoint;
- donor_iPoint = donor_forward_point;
-
- nDonorPoints++;
- }
-
- if ( Donor_nLinkedNodes[donor_StartIndex] == 2 ){
- check = false;
-
- uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_StartIndex] ];
-
- donor_iPoint = uptr[1];
- donor_OldiPoint = donor_StartIndex;
- }
- else
- check = true;
-
- /*--- Proceeds along the backward direction (depending on which connected boundary node is found first) ---*/
-
- while( !check ){
-
- /*--- Proceeds until the value of the intersection length is null ---*/
- if ( Donor_nLinkedNodes[donor_iPoint] == 1 ){
- donor_forward_point = donor_OldiPoint;
- donor_backward_point = donor_iPoint;
- }
- else{
- uptr = &Donor_LinkedNodes[ Donor_StartLinkedNodes[donor_iPoint] ];
-
- if( donor_OldiPoint != uptr[0] ){
- donor_forward_point = uptr[0];
- donor_backward_point = uptr[1];
- }
- else{
- donor_forward_point = uptr[1];
- donor_backward_point = uptr[0];
- }
- }
-
- if(donor_iPoint >= nGlobalVertex_Donor){
- check = true;
- continue;
- }
-
- for(iDim = 0; iDim < nDim; iDim++){
- donor_iMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_forward_point * nDim + iDim] + DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
- donor_jMidEdge_point[iDim] = ( DonorPoint_Coord[ donor_backward_point * nDim + iDim] + DonorPoint_Coord[ donor_iPoint * nDim + iDim] ) / 2;
- }
-
- LineIntersectionLength = ComputeLineIntersectionLength(target_iMidEdge_point, target_jMidEdge_point, donor_iMidEdge_point, donor_jMidEdge_point, Direction);
-
- if ( LineIntersectionLength == 0.0 ){
- check = true;
- continue;
- }
-
- /*--- In case the element intersects the target cell, update the auxiliary communication data structure ---*/
-
- tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
- tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
- tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
-
- for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
- tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
- tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
- tmp_storeProc[iDonor] = storeProc[iDonor];
- }
-
- tmp_Coeff_Vect[ nDonorPoints ] = LineIntersectionLength / length;
- tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
- tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
-
- if (Donor_Vect != NULL) delete [] Donor_Vect;
- if (Coeff_Vect != NULL) delete [] Coeff_Vect;
- if (storeProc != NULL) delete [] storeProc;
-
- Donor_Vect = tmp_Donor_Vect;
- Coeff_Vect = tmp_Coeff_Vect;
- storeProc = tmp_storeProc;
-
- donor_OldiPoint = donor_iPoint;
- donor_iPoint = donor_forward_point;
-
- nDonorPoints++;
- }
-
- /*--- Set the communication data structure and copy data from the auxiliary vectors ---*/
-
- target_geometry->vertex[markTarget][iVertex]->SetnDonorPoints(nDonorPoints);
-
- target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo();
-
- for ( iDonor = 0; iDonor < nDonorPoints; iDonor++ ){
- target_geometry->vertex[markTarget][iVertex]->SetDonorCoeff( iDonor, Coeff_Vect[iDonor]);
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorPoint( iDonor, Donor_GlobalPoint[ Donor_Vect[iDonor] ]);
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, storeProc[iDonor]);
- }
- }
- }
-
- delete [] target_segment;
-
- delete [] target_iMidEdge_point;
- delete [] target_jMidEdge_point;
-
- delete [] donor_iMidEdge_point;
- delete [] donor_jMidEdge_point;
- }
- else{
- /* --- 3D geometry, creates a superficial super-mesh --- */
-
- for (iVertex = 0; iVertex < nVertexTarget; iVertex++) {
-
- nDonorPoints = 0;
-
- /*--- Stores coordinates of the target node ---*/
-
- target_iPoint = target_geometry->vertex[markTarget][iVertex]->GetNode();
-
- if (target_geometry->node[target_iPoint]->GetDomain()){
-
- Coord_i = target_geometry->node[target_iPoint]->GetCoord();
-
- target_geometry->vertex[markTarget][iVertex]->GetNormal(Normal);
-
- /*--- The value of Area computed here includes also portion of boundary belonging to different marker ---*/
- Area = 0.0;
- for (iDim = 0; iDim < nDim; iDim++)
- Area += Normal[iDim]*Normal[iDim];
- Area = sqrt(Area);
-
- for (iDim = 0; iDim < nDim; iDim++)
- Normal[iDim] /= Area;
-
- for (iDim = 0; iDim < nDim; iDim++)
- Coord_i[iDim] = target_geometry->node[target_iPoint]->GetCoord(iDim);
-
- long dPoint = target_geometry->node[target_iPoint]->GetGlobalIndex();
- for (target_iPoint = 0; target_iPoint < nGlobalVertex_Target; target_iPoint++){
- if( dPoint == Target_GlobalPoint[target_iPoint] )
- break;
- }
-
- /*--- Build local surface dual mesh for target element ---*/
-
- nEdges_target = Target_nLinkedNodes[target_iPoint];
-
- nNode_target = 2*(nEdges_target + 1);
-
- target_element = new su2double*[nNode_target];
- for (ii = 0; ii < nNode_target; ii++)
- target_element[ii] = new su2double[nDim];
-
- nNode_target = Build_3D_surface_element(Target_LinkedNodes, Target_StartLinkedNodes, Target_nLinkedNodes, TargetPoint_Coord, target_iPoint, target_element);
-
- /*--- Brute force to find the closest donor_node ---*/
-
- mindist = 1E6;
- donor_StartIndex = 0;
-
- for (donor_iPoint = 0; donor_iPoint < nGlobalVertex_Donor; donor_iPoint++) {
-
- Coord_j = &DonorPoint_Coord[ donor_iPoint * nDim ];
-
- dist = PointsDistance(Coord_i, Coord_j);
-
- if (dist < mindist) {
- mindist = dist;
- donor_StartIndex = donor_iPoint;
- }
-
- if (dist == 0.0){
- donor_StartIndex = donor_iPoint;
- break;
- }
- }
-
- donor_iPoint = donor_StartIndex;
-
- nEdges_donor = Donor_nLinkedNodes[donor_iPoint];
-
- donor_element = new su2double*[ 2*nEdges_donor + 2 ];
- for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
- donor_element[ii] = new su2double[nDim];
-
- nNode_donor = Build_3D_surface_element(Donor_LinkedNodes, Donor_StartLinkedNodes, Donor_nLinkedNodes, DonorPoint_Coord, donor_iPoint, donor_element);
-
- Area = 0;
- for (ii = 1; ii < nNode_target-1; ii++){
- for (jj = 1; jj < nNode_donor-1; jj++){
- Area += Compute_Triangle_Intersection(target_element[0], target_element[ii], target_element[ii+1], donor_element[0], donor_element[jj], donor_element[jj+1], Normal);
- //cout << Compute_Triangle_Intersection(target_element[0], target_element[ii], target_element[ii+1], donor_element[0], donor_element[jj], donor_element[jj+1], Normal) << endl;
- }
- }
-
- for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
- delete [] donor_element[ii];
- delete [] donor_element;
-
- nDonorPoints = 1;
-
- /*--- In case the element intersect the target cell update the auxiliary communication data structure ---*/
-
- Coeff_Vect = new su2double[ nDonorPoints ];
- Donor_Vect = new unsigned long[ nDonorPoints ];
- storeProc = new unsigned long[ nDonorPoints ];
-
- Coeff_Vect[0] = Area;
- Donor_Vect[0] = donor_iPoint;
- storeProc[0] = Donor_Proc[donor_iPoint];
-
- alreadyVisitedDonor = new unsigned long[1];
-
- alreadyVisitedDonor[0] = donor_iPoint;
- nAlreadyVisited = 1;
- StartVisited = 0;
-
- Area_old = -1;
-
- while( Area > Area_old ){
-
- /*
- * - Starting from the closest donor_point, it expands the supermesh by a countour search pattern.
- * - The closest donor element becomes the core, at each iteration a new layer of elements around the core is taken into account
- */
-
- Area_old = Area;
-
- ToVisit = NULL;
- nToVisit = 0;
-
- for( iNodeVisited = StartVisited; iNodeVisited < nAlreadyVisited; iNodeVisited++ ){
-
- vPoint = alreadyVisitedDonor[ iNodeVisited ];
-
- nEdgeVisited = Donor_nLinkedNodes[vPoint];
-
- for (iEdgeVisited = 0; iEdgeVisited < nEdgeVisited; iEdgeVisited++){
-
- donor_iPoint = Donor_LinkedNodes[ Donor_StartLinkedNodes[vPoint] + iEdgeVisited];
-
- /*--- Check if the node to visit is already listed in the data structure to avoid double visits ---*/
-
- check = 0;
-
- for( jj = 0; jj < nAlreadyVisited; jj++ ){
- if( donor_iPoint == alreadyVisitedDonor[jj] ){
- check = 1;
- break;
- }
- }
-
- if( check == 0 && ToVisit != NULL){
- for( jj = 0; jj < nToVisit; jj++ )
- if( donor_iPoint == ToVisit[jj] ){
- check = 1;
- break;
- }
- }
-
- if( check == 0 ){
- /*--- If the node was not already visited, visit it and list it into data structure ---*/
-
- tmpVect = new unsigned long[ nToVisit + 1 ];
-
- for( jj = 0; jj < nToVisit; jj++ )
- tmpVect[jj] = ToVisit[jj];
- tmpVect[nToVisit] = donor_iPoint;
-
- if( ToVisit != NULL )
- delete [] ToVisit;
-
- ToVisit = tmpVect;
- tmpVect = NULL;
-
- nToVisit++;
-
- /*--- Find the value of the intersection area between the current donor element and the target element --- */
-
- nEdges_donor = Donor_nLinkedNodes[donor_iPoint];
-
- donor_element = new su2double*[ 2*nEdges_donor + 2 ];
- for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
- donor_element[ii] = new su2double[nDim];
-
- nNode_donor = Build_3D_surface_element(Donor_LinkedNodes, Donor_StartLinkedNodes, Donor_nLinkedNodes, DonorPoint_Coord, donor_iPoint, donor_element);
-
- tmp_Area = 0;
- for (ii = 1; ii < nNode_target-1; ii++)
- for (jj = 1; jj < nNode_donor-1; jj++)
- tmp_Area += Compute_Triangle_Intersection(target_element[0], target_element[ii], target_element[ii+1], donor_element[0], donor_element[jj], donor_element[jj+1], Normal);
-
- for (ii = 0; ii < 2*nEdges_donor + 2; ii++)
- delete [] donor_element[ii];
- delete [] donor_element;
-
- /*--- In case the element intersect the target cell update the auxiliary communication data structure ---*/
-
- tmp_Coeff_Vect = new su2double[ nDonorPoints + 1 ];
- tmp_Donor_Vect = new unsigned long[ nDonorPoints + 1 ];
- tmp_storeProc = new unsigned long[ nDonorPoints + 1 ];
-
- for( iDonor = 0; iDonor < nDonorPoints; iDonor++){
- tmp_Donor_Vect[iDonor] = Donor_Vect[iDonor];
- tmp_Coeff_Vect[iDonor] = Coeff_Vect[iDonor];
- tmp_storeProc[iDonor] = storeProc[iDonor];
- }
-
- tmp_Coeff_Vect[ nDonorPoints ] = tmp_Area;
- tmp_Donor_Vect[ nDonorPoints ] = donor_iPoint;
- tmp_storeProc[ nDonorPoints ] = Donor_Proc[donor_iPoint];
-
- if (Donor_Vect != NULL) {delete [] Donor_Vect; }
- if (Coeff_Vect != NULL) {delete [] Coeff_Vect; }
- if (storeProc != NULL) {delete [] storeProc; }
-
- Donor_Vect = tmp_Donor_Vect;
- Coeff_Vect = tmp_Coeff_Vect;
- storeProc = tmp_storeProc;
-
- tmp_Coeff_Vect = NULL;
- tmp_Donor_Vect = NULL;
- tmp_storeProc = NULL;
-
- nDonorPoints++;
-
- Area += tmp_Area;
- }
- }
- }
-
- /*--- Update auxiliary data structure ---*/
-
- StartVisited = nAlreadyVisited;
-
- tmpVect = new unsigned long[ nAlreadyVisited + nToVisit ];
-
- for( jj = 0; jj < nAlreadyVisited; jj++ )
- tmpVect[jj] = alreadyVisitedDonor[jj];
-
- for( jj = 0; jj < nToVisit; jj++ )
- tmpVect[ nAlreadyVisited + jj ] = ToVisit[jj];
-
- if( alreadyVisitedDonor != NULL )
- delete [] alreadyVisitedDonor;
-
- alreadyVisitedDonor = tmpVect;
-
- nAlreadyVisited += nToVisit;
-
- delete [] ToVisit;
- }
-
- delete [] alreadyVisitedDonor;
-
- /*--- Set the communication data structure and copy data from the auxiliary vectors ---*/
-
- target_geometry->vertex[markTarget][iVertex]->SetnDonorPoints(nDonorPoints);
- target_geometry->vertex[markTarget][iVertex]->Allocate_DonorInfo();
-
- for ( iDonor = 0; iDonor < nDonorPoints; iDonor++ ){
- target_geometry->vertex[markTarget][iVertex]->SetDonorCoeff(iDonor, Coeff_Vect[iDonor]/Area);
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorPoint( iDonor, Donor_GlobalPoint[ Donor_Vect[iDonor] ] );
- target_geometry->vertex[markTarget][iVertex]->SetInterpDonorProcessor(iDonor, storeProc[iDonor]);
- //cout <GetnDim();
-
- su2double dotA2, dotB1, dotB2;
-
- dotA2 = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dotA2 += ( A2[iDim] - A1[iDim] ) * Direction[iDim];
-
- if( dotA2 >= 0 ){
- dotB1 = 0;
- dotB2 = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- dotB1 += ( B1[iDim] - A1[iDim] ) * Direction[iDim];
- dotB2 += ( B2[iDim] - A1[iDim] ) * Direction[iDim];
- }
- }
- else{
- dotA2 *= -1;
-
- dotB1 = 0;
- dotB2 = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- dotB1 -= ( B1[iDim] - A1[iDim] ) * Direction[iDim];
- dotB2 -= ( B2[iDim] - A1[iDim] ) * Direction[iDim];
- }
- }
-
- if( dotB1 >= 0 && dotB1 <= dotA2 ){
- if ( dotB2 < 0 )
- return fabs( dotB1 );
- if ( dotB2 > dotA2 )
- return fabs( dotA2 - dotB1 );
-
- return fabs( dotB1 - dotB2 );
- }
-
- if( dotB2 >= 0 && dotB2 <= dotA2 ){
- if ( dotB1 < 0 )
- return fabs(dotB2);
- if ( dotB1 > dotA2 )
- return fabs( dotA2 - dotB2 );
- }
-
- if( ( dotB1 <= 0 && dotA2 <= dotB2 ) || ( dotB2 <= 0 && dotA2 <= dotB1 ) )
- return fabs( dotA2 );
-
- return 0.0;
-}
-
-su2double CSlidingMesh::Compute_Triangle_Intersection(su2double* A1, su2double* A2, su2double* A3, su2double* B1, su2double* B2, su2double* B3, su2double* Direction){
-
- /* --- This routine is ONLY for 3D grids --- */
- /* --- Projects triangle points onto a plane, specified by its normal "Direction", and calls the ComputeIntersectionArea routine --- */
-
- unsigned short iDim;
- unsigned short nDim = 3;
-
- su2double I[3], J[3], K[3];
- su2double a1[3], a2[3], a3[3];
- su2double b1[3], b2[3], b3[3];
- su2double m1, m2;
-
- /* --- Reference frame is determined by: x = A1A2 y = x ^ ( -Direction ) --- */
-
- for(iDim = 0; iDim < 3; iDim++){
- a1[iDim] = 0;
- a2[iDim] = 0;
- a3[iDim] = 0;
-
- b1[iDim] = 0;
- b2[iDim] = 0;
- b3[iDim] = 0;
- }
-
- m1 = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- K[iDim] = Direction[iDim];
-
- m1 += K[iDim] * K[iDim];
- }
-
- for(iDim = 0; iDim < nDim; iDim++)
- K[iDim] /= sqrt(m1);
-
- m2 = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- m2 += (A2[iDim] - A1[iDim]) * K[iDim];
-
- m1 = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- I[iDim] = (A2[iDim] - A1[iDim]) - m2 * K[iDim];
- m1 += I[iDim] * I[iDim];
- }
-
- for(iDim = 0; iDim < nDim; iDim++)
- I[iDim] /= sqrt(m1);
-
- // Cross product to find Y
- J[0] = K[1]*I[2] - K[2]*I[1];
- J[1] = -(K[0]*I[2] - K[2]*I[0]);
- J[2] = K[0]*I[1] - K[1]*I[0];
-
- /* --- Project all points on the plane specified by Direction and change their reference frame taking A1 as origin --- */
-
- for(iDim = 0; iDim < nDim; iDim++){
- a2[0] += (A2[iDim] - A1[iDim]) * I[iDim];
- a2[1] += (A2[iDim] - A1[iDim]) * J[iDim];
- a2[2] += (A2[iDim] - A1[iDim]) * K[iDim];
-
- a3[0] += (A3[iDim] - A1[iDim]) * I[iDim];
- a3[1] += (A3[iDim] - A1[iDim]) * J[iDim];
- a3[2] += (A3[iDim] - A1[iDim]) * K[iDim];
-
- b1[0] += (B1[iDim] - A1[iDim]) * I[iDim];
- b1[1] += (B1[iDim] - A1[iDim]) * J[iDim];
- b1[2] += (B1[iDim] - A1[iDim]) * K[iDim];
-
- b2[0] += (B2[iDim] - A1[iDim]) * I[iDim];
- b2[1] += (B2[iDim] - A1[iDim]) * J[iDim];
- b2[2] += (B2[iDim] - A1[iDim]) * K[iDim];
-
- b3[0] += (B3[iDim] - A1[iDim]) * I[iDim];
- b3[1] += (B3[iDim] - A1[iDim]) * J[iDim];
- b3[2] += (B3[iDim] - A1[iDim]) * K[iDim];
- }
-
- /* --- Compute intersection area --- */
-
- return ComputeIntersectionArea( a1, a2, a3, b1, b2, b3 );
-}
-
-su2double CSlidingMesh::ComputeIntersectionArea( su2double* P1, su2double* P2, su2double* P3, su2double* Q1, su2double* Q2, su2double* Q3 ){
-
- /* --- This routines computes the area of the polygonal element generated by the superimposition of 2 planar triangle --- */
- /* --- The 2 triangle must lie on the same plane --- */
-
- unsigned short iDim, nPoints, i, j, k;
- unsigned short nDim, min_theta_index;
-
- su2double points[16][2], IntersectionPoint[2], theta[6];
- su2double TriangleP[4][2], TriangleQ[4][2];
- su2double Area, det, dot1, dot2, dtmp, min_theta;
-
- nDim = 2;
- nPoints = 0;
-
- for(iDim = 0; iDim < nDim; iDim++){
- TriangleP[0][iDim] = 0;
- TriangleP[1][iDim] = P2[iDim] - P1[iDim];
- TriangleP[2][iDim] = P3[iDim] - P1[iDim];
- TriangleP[3][iDim] = 0;
-
- TriangleQ[0][iDim] = Q1[iDim] - P1[iDim];
- TriangleQ[1][iDim] = Q2[iDim] - P1[iDim];
- TriangleQ[2][iDim] = Q3[iDim] - P1[iDim];
- TriangleQ[3][iDim] = Q1[iDim] - P1[iDim];
- }
-
-
- for( j = 0; j < 3; j++){
- if( CheckPointInsideTriangle(TriangleP[j], TriangleQ[0], TriangleQ[1], TriangleQ[2]) ){
-
- // Then P1 is also inside triangle Q, so store it
- for(iDim = 0; iDim < nDim; iDim++)
- points[nPoints][iDim] = TriangleP[j][iDim];
-
- nPoints++;
- }
- }
-
- for( j = 0; j < 3; j++){
- if( CheckPointInsideTriangle(TriangleQ[j], TriangleP[0], TriangleP[1], TriangleP[2]) ){
-
- // Then Q1 is also inside triangle P, so store it
- for(iDim = 0; iDim < nDim; iDim++)
- points[nPoints][iDim] = TriangleQ[j][iDim];
-
- nPoints++;
- }
- }
-
-
- // Compute all edge intersections
-
- for( j = 0; j < 3; j++){
- for( i = 0; i < 3; i++){
-
- det = (TriangleP[j][0] - TriangleP[j+1][0]) * ( TriangleQ[i][1] - TriangleQ[i+1][1] ) - (TriangleP[j][1] - TriangleP[j+1][1]) * (TriangleQ[i][0] - TriangleQ[i+1][0]);
-
- if ( det != 0.0 ){
- ComputeLineIntersectionPoint( TriangleP[j], TriangleP[j+1], TriangleQ[i], TriangleQ[i+1], IntersectionPoint );
-
- dot1 = 0;
- dot2 = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- dot1 += ( TriangleP[j][iDim] - IntersectionPoint[iDim] ) * ( TriangleP[j+1][iDim] - IntersectionPoint[iDim] );
- dot2 += ( TriangleQ[i][iDim] - IntersectionPoint[iDim] ) * ( TriangleQ[i+1][iDim] - IntersectionPoint[iDim] );
- }
-
- if( dot1 <= 0 && dot2 <= 0 ){ // It found one intersection
-
- // Store temporarily the intersection point
-
- for(iDim = 0; iDim < nDim; iDim++)
- points[nPoints][iDim] = IntersectionPoint[iDim];
-
- nPoints++;
- }
- }
- }
- }
-
- // Remove double points, if any
-
- for( i = 0; i < nPoints; i++){
- for( j = i+1; j < nPoints; j++){
- if(points[j][0] == points[i][0] && points[j][1] == points[i][1]){
- for( k = j; k < nPoints-1; k++){
- points[k][0] = points[k+1][0];
- points[k][1] = points[k+1][1];
- }
- nPoints--;
- j--;
- }
- }
- }
-
- // Re-order nodes
-
- for( i = 1; i < nPoints; i++){ // Change again reference frame
- for(iDim = 0; iDim < nDim; iDim++)
- points[i][iDim] -= points[0][iDim];
-
- // Compute polar azimuth for each node but the first
- theta[i] = atan2(points[i][1], points[i][0]);
- }
-
- for(iDim = 0; iDim < nDim; iDim++)
- points[0][iDim] = 0;
-
- for( i = 1; i < nPoints; i++){
-
- min_theta = theta[i];
- min_theta_index = 0;
-
- for( j = i + 1; j < nPoints; j++){
-
- if( theta[j] < min_theta ){
- min_theta = theta[j];
- min_theta_index = j;
- }
- }
-
- if( min_theta_index != 0 ){
- dtmp = theta[i];
- theta[i] = theta[min_theta_index];
- theta[min_theta_index] = dtmp;
-
- dtmp = points[i][0];
- points[i][0] = points[min_theta_index][0];
- points[min_theta_index][0] = dtmp;
-
- dtmp = points[i][1];
- points[i][1] = points[min_theta_index][1];
- points[min_theta_index][1] = dtmp;
- }
- }
-
- // compute area using cross product rule, points position are referred to the 2-dimensional, local, reference frame centered in points[0]
-
- Area = 0;
-
- if (nPoints > 2){
- for( i = 1; i < nPoints-1; i++ ){
-
- // Ax*By
- Area += ( points[i][0] - points[0][0] ) * ( points[i+1][1] - points[0][1] );
-
- // Ay*Bx
- Area -= ( points[i][1] - points[0][1] ) * ( points[i+1][0] - points[0][0] );
- }
- }
-
- return fabs(Area)/2;
-}
-
-void CSlidingMesh::ComputeLineIntersectionPoint( su2double* A1, su2double* A2, su2double* B1, su2double* B2, su2double* IntersectionPoint ){
-
- /* --- Uses determinant rule to compute the intersection point between 2 straight segments --- */
- /* This works only for lines on a 2D plane, A1, A2 and B1, B2 are respectively the head and the tail points of each segment,
- * since they're on a 2D plane they are defined by a 2-elements array containing their coordinates */
-
- su2double det;
-
- det = (A1[0] - A2[0]) * (B1[1] - B2[1]) - (A1[1] - A2[1]) * (B1[0] - B2[0]);
-
- if ( det != 0.0 ){ // else there is no intersection point
- IntersectionPoint[0] = ( ( A1[0]*A2[1] - A1[1]*A2[0] ) * ( B1[0] - B2[0] ) - ( B1[0]*B2[1] - B1[1]*B2[0] ) * ( A1[0] - A2[0] ) ) / det;
- IntersectionPoint[1] = ( ( A1[0]*A2[1] - A1[1]*A2[0] ) * ( B1[1] - B2[1] ) - ( B1[0]*B2[1] - B1[1]*B2[0] ) * ( A1[1] - A2[1] ) ) / det;
- }
-
- return;
-}
-
-bool CSlidingMesh::CheckPointInsideTriangle(su2double* Point, su2double* T1, su2double* T2, su2double* T3){
-
- /* --- Check whether a point "Point" lies inside or outside a triangle defined by 3 points "T1", "T2", "T3" --- */
- /* For each edge it checks on which side the point lies:
- * - Computes the unit vector pointing at the internal side of the edge
- * - Comutes the vector that connects the point to a point along the edge
- * - If the dot product is positive it means that the point is on the internal side of the edge
- * - If the check is positive for all the 3 edges, then the point lies within the triangle
- */
-
- unsigned short iDim, nDim, check;
-
- su2double vect1[2], vect2[2], r[2];
- su2double dot;
-
- check = 0;
- nDim = 2;
-
- /* --- Check first edge --- */
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- vect1[iDim] = T3[iDim] - T1[iDim]; // vec 1 is aligned to the edge
- vect2[iDim] = T2[iDim] - T1[iDim]; // vect 2 is the vector connecting one edge point to the third triangle vertex
-
- r[iDim] = Point[iDim] - T1[iDim]; // Connects point to vertex T1
-
- dot += vect2[iDim] * vect2[iDim];
- }
- dot = sqrt(dot);
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect2[iDim] /= dot;
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dot += vect1[iDim] * vect2[iDim];
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect1[iDim] = T3[iDim] - (T1[iDim] + dot * vect2[iDim]); // Computes the inward unit vector
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++) // Checs that the point lies on the internal plane
- dot += vect1[iDim] * r[iDim];
-
- if (dot >= 0)
- check++;
-
- /* --- Check second edge --- */
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- vect1[iDim] = T1[iDim] - T2[iDim];
- vect2[iDim] = T3[iDim] - T2[iDim];
-
- r[iDim] = Point[iDim] - T2[iDim];
-
- dot += vect2[iDim] * vect2[iDim];
- }
- dot = sqrt(dot);
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect2[iDim] /= dot;
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dot += vect1[iDim] * vect2[iDim];
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect1[iDim] = T1[iDim] - (T2[iDim] + dot * vect2[iDim]);
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dot += vect1[iDim] * r[iDim];
-
- if (dot >= 0)
- check++;
-
- /* --- Check third edge --- */
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++){
- vect1[iDim] = T2[iDim] - T3[iDim];
- vect2[iDim] = T1[iDim] - T3[iDim];
-
- r[iDim] = Point[iDim] - T3[iDim];
-
- dot += vect2[iDim] * vect2[iDim];
- }
- dot = sqrt(dot);
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect2[iDim] /= dot;
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dot += vect1[iDim] * vect2[iDim];
-
- for(iDim = 0; iDim < nDim; iDim++)
- vect1[iDim] = T2[iDim] - (T3[iDim] + dot * vect2[iDim]);
-
- dot = 0;
- for(iDim = 0; iDim < nDim; iDim++)
- dot += vect1[iDim] * r[iDim];
-
- if (dot >= 0)
- check++;
-
- return (check == 3);
-}
-
-/*--- Radial Basis Function Interpolator ---*/
-CRadialBasisFunction::CRadialBasisFunction(void): CInterpolator() { }
-
-CRadialBasisFunction::CRadialBasisFunction(CGeometry ****geometry_container, CConfig **config, unsigned int iZone, unsigned int jZone) : CInterpolator(geometry_container, config, iZone, jZone) {
-
- /*--- Initialize transfer coefficients between the zones ---*/
- Set_TransferCoeff(config);
-
-}
-
-CRadialBasisFunction::~CRadialBasisFunction() {}
-
-void CRadialBasisFunction::Set_TransferCoeff(CConfig **config) {
-
- int iProcessor, nProcessor = size;
- int nPolynomial = 0;
- int mark_donor, mark_target, target_check, donor_check;
- int *skip_row = NULL, *calc_polynomial_check;
-
- unsigned short iDim, nDim, iMarkerInt, nMarkerInt;
-
- unsigned long iVertexDonor, jVertexDonor, iVertexTarget, iCount, jCount;
- unsigned long nVertexDonor, nVertexTarget, nVertexDonorInDomain;
- unsigned long nGlobalVertexDonor, iGlobalVertexDonor_end, nLocalM;
- unsigned long point_donor, point_target;
- unsigned long *nLocalM_arr;
-
- su2double val_i, val_j;
- su2double interface_coord_tol=1e6*numeric_limits::epsilon();
- su2double *Coord_i, *Coord_j;
- su2double *local_M;
- su2double *P = NULL;
- su2double *C_inv_trunc = NULL, *C_tmp = NULL;
- su2double *target_vec, *coeff_vec;
-
- CSymmetricMatrix *global_M = NULL, *Mp = NULL;
-
-#ifdef HAVE_MPI
- unsigned long iLocalM;
- su2double *global_M_val_arr = NULL, *Buffer_recv_local_M;
- int *Buffer_Recv_mark = new int[nProcessor], iRank;
-#endif
-
- /*--- Initialize variables --- */
-
- nMarkerInt = (int) ( config[donorZone]->GetMarker_n_ZoneInterface() / 2 );
-
- nDim = donor_geometry->GetnDim();
-
-
- Buffer_Receive_nVertex_Donor = new unsigned long [nProcessor];
-
-
- /*--- Cycle over nMarkersInt interface to determine communication pattern ---*/
-
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
-
- /*--- On the donor side: find the tag of the boundary sharing the interface ---*/
- mark_donor = Find_InterfaceMarker(config[donorZone], iMarkerInt);
-
- /*--- On the target side: find the tag of the boundary sharing the interface ---*/
- mark_target = Find_InterfaceMarker(config[targetZone], iMarkerInt);
-
-#ifdef HAVE_MPI
-
- donor_check = -1;
- target_check = -1;
-
- /*--- We gather a vector in MASTER_NODE to determines whether the boundary is not on the processor because of the partition or because the zone does not include it ---*/
-
- SU2_MPI::Gather(&mark_donor , 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE)
- for (iRank = 0; iRank < nProcessor; iRank++)
- if( Buffer_Recv_mark[iRank] != -1 ) {
- donor_check = Buffer_Recv_mark[iRank];
- break;
- }
-
- SU2_MPI::Bcast(&donor_check , 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
-
- SU2_MPI::Gather(&mark_target, 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE)
- for (iRank = 0; iRank < nProcessor; iRank++)
- if( Buffer_Recv_mark[iRank] != -1 ) {
- target_check = Buffer_Recv_mark[iRank];
- break;
- }
-
- SU2_MPI::Bcast(&target_check, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
-#else
- donor_check = mark_donor;
- target_check = mark_target;
-#endif
-
- /*--- Checks if the zone contains the interface, if not continue to the next step ---*/
- if(target_check == -1 || donor_check == -1)
- continue;
-
- if(mark_donor != -1)
- nVertexDonor = donor_geometry->GetnVertex( mark_donor );
- else
- nVertexDonor = 0;
-
- if(mark_target != -1)
- nVertexTarget = target_geometry->GetnVertex( mark_target );
- else
- nVertexTarget = 0;
-
- Buffer_Send_nVertex_Donor = new unsigned long [ 1 ];
-
- /*--- Sets MaxLocalVertex_Donor, Buffer_Receive_nVertex_Donor ---*/
- Determine_ArraySize(false, mark_donor, mark_target, nVertexDonor, nDim);
-
- /*--- Collect information about number of donor vertices in domain.
- Calculate total number of donor vertices across all ranks and
- number of vertices on boundary prior to current rank. ---*/
- nVertexDonorInDomain = Buffer_Send_nVertex_Donor[0];
- iGlobalVertexDonor_end = nGlobalVertexDonor = 0;
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
- {
- nGlobalVertexDonor += Buffer_Receive_nVertex_Donor[iProcessor];
- if (iProcessor<=rank) iGlobalVertexDonor_end += Buffer_Receive_nVertex_Donor[iProcessor];
- }
-
- /*-- Collect coordinates, global points, and normal vectors ---*/
- Buffer_Send_Coord = new su2double [ MaxLocalVertex_Donor * nDim ];
- Buffer_Send_GlobalPoint = new long [ MaxLocalVertex_Donor ];
- Buffer_Receive_Coord = new su2double [ nProcessor * MaxLocalVertex_Donor * nDim ];
- Buffer_Receive_GlobalPoint = new long [ nProcessor * MaxLocalVertex_Donor ];
-
- Collect_VertexInfo( false, mark_donor, mark_target, nVertexDonor, nDim);
-
- /*--- Send information about size of local_M array ---*/
- nLocalM = nVertexDonorInDomain*(nVertexDonorInDomain+1)/2 \
- + nVertexDonorInDomain*(nGlobalVertexDonor-iGlobalVertexDonor_end);
-
- nLocalM_arr = new unsigned long [nProcessor];
-#ifdef HAVE_MPI
- SU2_MPI::Allgather(&nLocalM, 1, MPI_UNSIGNED_LONG, nLocalM_arr, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
-#else
- nLocalM_arr[MASTER_NODE] = nLocalM;
-#endif
-
- /*--- Initialize local M array and calculate values ---*/
- local_M = new su2double [nLocalM];
- Coord_i = new su2double [nDim];
- Coord_j = new su2double [nDim];
- iCount=0;
- for (iVertexDonor=0; iVertexDonorGetKindRadialBasisFunction(),
- config[donorZone]->GetRadialBasisFunctionParameter(),
- PointsDistance(Coord_i, Coord_j));
- }
-
- for (iProcessor=rank+1; iProcessorGetKindRadialBasisFunction(),
- config[donorZone]->GetRadialBasisFunctionParameter(),
- PointsDistance(Coord_i, Coord_j));
- }
- }
- }
-
-#ifdef HAVE_MPI
- if (rank != MASTER_NODE) {
- SU2_MPI::Send(local_M, nLocalM, MPI_DOUBLE, MASTER_NODE, 0, MPI_COMM_WORLD);
- }
-
- /*--- Assemble global_M ---*/
- if (rank == MASTER_NODE) {
- global_M_val_arr = new su2double [nGlobalVertexDonor*(nGlobalVertexDonor+1)/2];
-
- /*--- Copy master node local_M to global_M ---*/
- iCount = 0;
- for (iLocalM=0; iLocalM SINGLE_NODE) {
- for (iProcessor=1; iProcessorInitialize(nGlobalVertexDonor, global_M_val_arr);
- }
-
-#else
- global_M = new CSymmetricMatrix;
- global_M->Initialize((int)nVertexDonorInDomain, local_M);
-#endif
-
- /*--- Invert M matrix ---*/
- if (rank == MASTER_NODE) {
- switch (config[donorZone]->GetKindRadialBasisFunction())
- {
- /*--- Basis functions that make M positive definite ---*/
- case WENDLAND_C2:
- case INV_MULTI_QUADRIC:
- case GAUSSIAN:
- global_M->Invert(true);
- break;
-
- case THIN_PLATE_SPLINE:
- case MULTI_QUADRIC:
- global_M->Invert(false);
- break;
- }
- }
-
- calc_polynomial_check = new int [nDim];
-
- /*--- Calculate C_inv_trunc ---*/
- if (rank == MASTER_NODE) {
-
- if ( config[donorZone]->GetRadialBasisFunctionPolynomialOption() ) {
-
- /*--- Fill P matrix and get minimum and maximum values ---*/
- P = new su2double [nGlobalVertexDonor*(nDim+1)];
- iCount = 0;
- for (iProcessor=MASTER_NODE; iProcessorInitialize(nPolynomial+1);
- for (int m=0; mRead((int)iVertexDonor, (int)jVertexDonor)*P[jVertexDonor*(nPolynomial+1)+n];
- }
- val_i += val_j*P[iVertexDonor*(nPolynomial+1)+m];
- }
- Mp->Write(m, n, val_i);
- }
- }
- Mp->Invert(false);
-
- /*--- Calculate M_p*P*M_inv ---*/
- C_inv_trunc = new su2double [(nGlobalVertexDonor+nPolynomial+1)*nGlobalVertexDonor];
- for (int m=0; mRead((int)jVertexDonor, (int)iVertexDonor);
- }
- val_i += val_j*Mp->Read(m, n);
- }
- /*--- Save in row major order ---*/
- C_inv_trunc[m*nGlobalVertexDonor+iVertexDonor] = val_i;
- }
- }
-
- /*--- Calculate (I - P'*M_p*P*M_inv) ---*/
- C_tmp = new su2double [nGlobalVertexDonor*nGlobalVertexDonor];
- for (iVertexDonor=0; iVertexDonorMatMatMult(true, C_tmp, (int)nGlobalVertexDonor);
-
- /*--- Write to C_inv_trunc matrix ---*/
- for (iVertexDonor=0; iVertexDonorRead((int)iVertexDonor, (int)jVertexDonor);
-
- } // endif GetRadialBasisFunctionPolynomialOption
- } // endif (rank == MASTER_NODE)
-
-#ifdef HAVE_MPI
- SU2_MPI::Bcast(&nPolynomial, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
- SU2_MPI::Bcast(calc_polynomial_check, nDim, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank != MASTER_NODE) {
- C_inv_trunc = new su2double [(nGlobalVertexDonor+nPolynomial+1)*nGlobalVertexDonor];
- }
-
- SU2_MPI::Bcast(C_inv_trunc, (nGlobalVertexDonor+nPolynomial+1)*nGlobalVertexDonor, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
-#endif
-
- /*--- Calculate H matrix ---*/
- if (config[donorZone]->GetRadialBasisFunctionPolynomialOption())
- target_vec = new su2double [nGlobalVertexDonor+nPolynomial+1];
- else
- target_vec = new su2double [nGlobalVertexDonor];
-
- coeff_vec = new su2double [nGlobalVertexDonor];
-
- for (iVertexTarget = 0; iVertexTarget < nVertexTarget; iVertexTarget++) {
-
- point_target = target_geometry->vertex[mark_target][iVertexTarget]->GetNode();
-
- if ( target_geometry->node[point_target]->GetDomain() ) {
- iCount = 0;
- if (config[donorZone]->GetRadialBasisFunctionPolynomialOption()) {
- target_vec[iCount] = 1;
- iCount++;
- }
-
- for (iDim=0; iDimnode[point_target]->GetCoord(iDim);
- if (config[donorZone]->GetRadialBasisFunctionPolynomialOption()) {
- if (calc_polynomial_check[iDim] == 1) {
- target_vec[iCount] = Coord_i[iDim];
- iCount++;
- }
- }
- }
-
- for (iProcessor=0; iProcessorGetKindRadialBasisFunction(),
- config[donorZone]->GetRadialBasisFunctionParameter(),
- PointsDistance(Coord_i, Coord_j));
- }
- }
-
- for (iVertexDonor=0; iVertexDonorvertex[mark_target][iVertexTarget]->SetnDonorPoints(iCount);
- target_geometry->vertex[mark_target][iVertexTarget]->Allocate_DonorInfo();
-
- iCount = 0;
- jCount = 0;
- for (iProcessor=0; iProcessorvertex[mark_target][iVertexTarget]->SetInterpDonorPoint(jCount, point_donor);
- target_geometry->vertex[mark_target][iVertexTarget]->SetInterpDonorProcessor(jCount, iProcessor);
- target_geometry->vertex[mark_target][iVertexTarget]->SetDonorCoeff(jCount, coeff_vec[iCount]);
- jCount++;
- }
- iCount++;
- }
- }
- } // endif
- } // endfor
-
- /*--- Memory management ---*/
- delete [] nLocalM_arr;
- delete [] local_M;
- delete [] Coord_i;
- delete [] Coord_j;
- delete [] calc_polynomial_check;
- delete [] C_inv_trunc;
- delete [] target_vec;
- delete [] coeff_vec;
-
- if ( rank == MASTER_NODE ) {
- delete global_M;
-
- if ( config[donorZone]->GetRadialBasisFunctionPolynomialOption() ) {
- delete [] skip_row;
- delete [] P;
- delete Mp;
- delete [] C_tmp;
- }
- }
-
- delete[] Buffer_Send_Coord;
- delete[] Buffer_Send_GlobalPoint;
-
- delete[] Buffer_Receive_Coord;
- delete[] Buffer_Receive_GlobalPoint;
-
- delete[] Buffer_Send_nVertex_Donor;
-
-#ifdef HAVE_MPI
- if (rank == MASTER_NODE)
- delete [] global_M_val_arr;
-#endif
- } // end loop over markers
-
- delete[] Buffer_Receive_nVertex_Donor;
-
-#ifdef HAVE_MPI
- if (rank == MASTER_NODE)
- delete [] Buffer_Recv_mark;
-#endif
-}
-
-void CRadialBasisFunction::Check_PolynomialTerms(int m, unsigned long n, const int *skip_row, su2double max_diff_tol_in, int *keep_row, int &n_polynomial, su2double *P)
-{
- /*--- This routine keeps the AD information in P but the calculations are done in passivedouble as their purpose
- is to decide which (if any) row of P to remove, and that process is not differentiable anyway. ---*/
-
- int *write_row = NULL;
- unsigned long iCount, jCount, n_rows;
- passivedouble sum, max_diff, max_coeff, *coeff = NULL, max_diff_tol = SU2_TYPE::GetValue(max_diff_tol_in);
- CSymmetricMatrix *PPT;
- su2double *P_tmp = NULL;
-
- n_rows = 0;
- for (int i=0; iInitialize((int)n_rows);
-
- iCount = 0;
- for (int i = 0; i < m; i ++) {
- if (skip_row[i] == 0) {
-
- jCount = 0;
- for (int j = 0; j < m; j ++){
- if (skip_row[j] == 0) {
-
- sum = 0.0;
- for (unsigned long k = 0; k < n; k ++)
- {
- sum += SU2_TYPE::GetValue(P[k*m+i]*P[k*m+j]);
- }
- PPT->Write((int)iCount, (int)jCount, sum);
-
- jCount++;
- }
- }
-
- iCount++;
- }
- }
-
- PPT->Invert(true);
-
- /*--- RHS for the least squares fit (vector of ones times P) ---*/
- coeff = new passivedouble [n_rows];
- iCount = 0;
- for (int i = 0; i < m; i ++) {
- if (skip_row[i] == 0) {
- coeff[iCount] = 0;
- for (unsigned long j = 0; j < n; j += 1)
- {
- coeff[iCount] += SU2_TYPE::GetValue(P[j*m+i]);
- }
- iCount++;
- }
- }
-
- /*--- Multiply the RHS by the inverse thus obtaining the coefficients ---*/
- PPT->MatVecMult(coeff);
-
- /*--- Determine the maximum deviation of the points from the fitted plane ---*/
- max_diff = 0;
- for (unsigned long i = 0; i < n; i ++)
- {
- sum = 0;
- iCount = 0;
- for (int j = 0; j < m; j ++)
- {
- if (skip_row[j] == 0) {
- sum += coeff[iCount]*SU2_TYPE::GetValue(P[i*m+j]);
- iCount++;
- }
- }
- /*--- 1.0 is the arbitrary constant we are assuming when fitting the plane ---*/
- max_diff = max(abs(1.0-sum), max_diff);
- }
-
- for (unsigned long i=0; i max_coeff) iCount = i;
- }
-
- for (unsigned long i=0; i::min()) rbf = 0.0;
- else rbf *= rbf*log(rbf);
- break;
-
- case MULTI_QUADRIC:
- case INV_MULTI_QUADRIC:
- rbf = sqrt(1.0+rbf*rbf);
- if(type == INV_MULTI_QUADRIC) rbf = 1.0/rbf;
- break;
- }
-
- return rbf;
-}
-
-/*--- Symmetric matrix class definitions ---*/
-CSymmetricMatrix::CSymmetricMatrix()
-{
- initialized = false;
- inversed = false;
- decomposed = none;
-
- val_vec = NULL;
- decompose_vec = NULL;
- inv_val_vec = NULL;
- perm_vec = NULL;
-}
-
-CSymmetricMatrix::~CSymmetricMatrix()
-{
- if(val_vec) {delete [] val_vec;}
- if(decompose_vec) {delete [] decompose_vec;}
- if(inv_val_vec) {delete [] inv_val_vec;}
- if(perm_vec) {delete [] perm_vec;}
-}
-
-void CSymmetricMatrix::Initialize(int N)
-{
- int i;
-
- sz = N;
- num_val = sz*(sz+1)/2;
- val_vec = new passivedouble [num_val];
- for (i=0; i abs(pivot) ) {
- pivot = decompose_vec[CalcIdxFull(i, j)];
- pivot_idx = i;
- interchange_row = true;
- }
- }
-
- if ( interchange_row ) {
- for ( k=0; k=sz || j<0 || j>=sz) {
- throw out_of_range("Index to access matrix out of bounds.");
- }
-}
-
-void CSymmetricMatrix::Write(int i, int j, const su2double& val)
-{
- CheckBounds(i,j);
- val_vec[CalcIdx(i, j)] = SU2_TYPE::GetValue(val);
-}
-
-passivedouble CSymmetricMatrix::Read(int i, int j)
-{
- CheckBounds(i,j);
- return val_vec[CalcIdx(i, j)];
-}
-
-passivedouble CSymmetricMatrix::ReadL(int i, int j)
-{
- passivedouble *p = NULL;
-
- CheckBounds(i,j);
-
- if (decompose_vec) { p = decompose_vec; }
- else { p = val_vec; }
-
- switch (decomposed) {
- case cholesky:
- if (i>=j) return p[CalcIdx(i, j)];
- else return 0.0;
-
- case lu:
- if (i>j) return p[CalcIdxFull(i, j)];
- else return passivedouble(i==j);
-
- default:
- throw invalid_argument("Matrix not decomposed yet or results have been deleted.");
- }
-}
-
-passivedouble CSymmetricMatrix::ReadU(int i, int j)
-{
- passivedouble *p = NULL;
-
- CheckBounds(i,j);
-
- if (decompose_vec){ p = decompose_vec; }
- else {p = val_vec;}
-
- switch (decomposed) {
- case cholesky:
- return 0.0;
-
- case lu:
- if (j>=i) return p[CalcIdxFull(j, i)];
- else return 0.0;
-
- default:
- throw invalid_argument("Matrix not decomposed yet or results have been deleted.");
- }
-}
-
-double CSymmetricMatrix::ReadInv(int i, int j)
-{
- passivedouble *p = NULL;
-
- CheckBounds(i,j);
-
- if (inversed) {
- if (inv_val_vec) { p = inv_val_vec; }
- else { p = val_vec; }
-
- return p[CalcIdx(i, j)];
- }
- else {
- throw invalid_argument("Matrix inverse not calculated yet.");
- }
-}
diff --git a/Common/src/linear_algebra/CSysMatrix.cpp b/Common/src/linear_algebra/CSysMatrix.cpp
index 06c153741c99..018c3c84a870 100644
--- a/Common/src/linear_algebra/CSysMatrix.cpp
+++ b/Common/src/linear_algebra/CSysMatrix.cpp
@@ -1383,7 +1383,7 @@ void CSysMatrix::ComputePastixPreconditioner(const CSysVector
void CSysMatrix::BuildPastixPreconditioner(CGeometry *geometry, CConfig *config,
unsigned short kind_fact, bool transposed) {
diff --git a/Common/src/linear_algebra/CSysSolve.cpp b/Common/src/linear_algebra/CSysSolve.cpp
index 43eb712e52a7..8e3118832f3c 100644
--- a/Common/src/linear_algebra/CSysSolve.cpp
+++ b/Common/src/linear_algebra/CSysSolve.cpp
@@ -241,7 +241,8 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector &
/*--- Set the norm to the initial initial residual value ---*/
- norm0 = norm_r;
+ if (tol_type == LinearToleranceType::RELATIVE)
+ norm0 = norm_r;
/*--- Output header information including initial residual ---*/
@@ -400,7 +401,8 @@ unsigned long CSysSolve::FGMRES_LinSolver(const CSysVector::BCGSTAB_LinSolver(const CSysVector::Smoother_LinSolver(const CSysVector::Solve_b(CSysMatrix & Jacobian,
/*--- Enforce a hard limit on total number of iterations ---*/
unsigned long IterLimit = min(RestartIter, MaxIter-IterLinSol);
IterLinSol += FGMRES_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol , IterLimit, Residual, ScreenOutput, config);
- if ( Residual < SolverTol*Norm0 ) break;
+ if ( Residual <= SolverTol*Norm0 ) break;
}
break;
case PASTIX_LDLT : case PASTIX_LU:
diff --git a/Common/src/meson.build b/Common/src/meson.build
index 37eca9d0d903..ca9c048e70d4 100644
--- a/Common/src/meson.build
+++ b/Common/src/meson.build
@@ -14,7 +14,6 @@ common_src =files(['geometry_structure_fem_part.cpp',
'fem_gauss_jacobi_quadrature.cpp',
'wall_model.cpp',
'adt_structure.cpp',
- 'interpolation_structure.cpp',
'mpi_structure.cpp',
'fem_cgns_elements.cpp',
'CMultiGridQueue.cpp'])
@@ -26,6 +25,7 @@ subdir('geometry/elements')
subdir('geometry/dual_grid')
subdir('geometry/primal_grid')
subdir('geometry/meshreader')
+subdir('interface_interpolation')
if get_option('enable-normal')
common = static_library('SU2Common',
diff --git a/Common/src/toolboxes/CSymmetricMatrix.cpp b/Common/src/toolboxes/CSymmetricMatrix.cpp
new file mode 100644
index 000000000000..fc1813479666
--- /dev/null
+++ b/Common/src/toolboxes/CSymmetricMatrix.cpp
@@ -0,0 +1,293 @@
+/*!
+ * \file CSymmetricMatrix.cpp
+ * \brief Implementation of dense symmetric matrix helper class (see hpp).
+ * \author Joel Ho, P. Gomes
+ * \version 7.0.3 "Blackbird"
+ *
+ * SU2 Project Website: https://su2code.github.io
+ *
+ * The SU2 Project is maintained by the SU2 Foundation
+ * (http://su2foundation.org)
+ *
+ * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
+ *
+ * SU2 is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * SU2 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with SU2. If not, see .
+ */
+
+#include "../../include/toolboxes/CSymmetricMatrix.hpp"
+#include "../../include/mpi_structure.hpp"
+
+#if defined(HAVE_MKL)
+#include "mkl.h"
+#ifndef HAVE_LAPACK
+#define HAVE_LAPACK
+#endif
+#elif defined(HAVE_LAPACK)
+/*--- Lapack / Blas routines used in CSymmetricMatrix. ---*/
+extern "C" void dsytrf_(const char*, const int*, passivedouble*, const int*, int*, passivedouble*, const int*, int*);
+extern "C" void dsytri_(const char*, const int*, passivedouble*, const int*, const int*, passivedouble*, int*);
+extern "C" void dpotrf_(const char*, const int*, passivedouble*, const int*, int*);
+extern "C" void dpotri_(const char*, const int*, passivedouble*, const int*, int*);
+extern "C" void dsymm_(const char*, const char*, const int*, const int*, const passivedouble*, const passivedouble*,
+ const int*, const passivedouble*, const int*, const passivedouble*, passivedouble*, const int*);
+#define DSYMM dsymm_
+#endif
+
+void CSymmetricMatrix::Initialize(int N) { mat.resize(N,N); }
+
+void CSymmetricMatrix::CholeskyDecompose()
+{
+#ifndef HAVE_LAPACK
+ int j;
+ for (j = 0; j < Size(); ++j) {
+ passivedouble sum = 0.0;
+ for (int k = 0; k < j; ++k) sum -= pow(Get(j,k), 2);
+ sum += Get(j,j);
+ if (sum < 0.0) break; // not SPD
+ Set(j, j, sqrt(sum));
+
+ for (int i = j+1; i < Size(); ++i) {
+ passivedouble sum = 0.0;
+ for (int k = 0; k < j; ++k) sum -= Get(i,k) * Get(j,k);
+ sum += Get(i,j);
+ Set(i, j, sum / Get(j,j));
+ }
+ }
+ if (j!=Size()) SU2_MPI::Error("LLT factorization failed.", CURRENT_FUNCTION);
+#endif
+}
+
+void CSymmetricMatrix::LUDecompose(su2passivematrix& decomp, vector& perm) const
+{
+#ifndef HAVE_LAPACK
+ const int sz = Size();
+
+ /*--- Copy matrix values to LU matrix, init permutation vec. ---*/
+ decomp.resize(sz,sz);
+ perm.resize(sz);
+
+ for (int i = 0; i < sz; ++i) {
+ perm[i] = i;
+ for (int j = i; j < sz; ++j) decomp(j,i) = decomp(i,j) = Get(i,j);
+ }
+
+ /*--- Decompose LU matrix. ---*/
+ for (int j = 0; j < sz-1; ++j) {
+ /*--- Search for maximum pivot and interchange rows. ---*/
+ passivedouble pivot = decomp(j,j);
+ int pivot_idx = j;
+ for (int i = j+1; i < sz; ++i)
+ if (abs(decomp(i,j)) > abs(pivot)) {
+ pivot = decomp(i,j);
+ pivot_idx = i;
+ }
+
+ if (pivot_idx != j) {
+ swap(perm[j], perm[pivot_idx]);
+ for (int k = 0; k < sz; ++k)
+ swap(decomp(j,k), decomp(pivot_idx,k));
+ }
+
+ /*--- Perform elimination. ---*/
+ for (int k = j+1; k < sz; ++k) decomp(k,j) /= pivot;
+
+ for (int k = j+1; k < sz; ++k)
+ for (int i = j+1; i < sz; ++i)
+ decomp(i,k) -= decomp(j,k)*decomp(i,j);
+ }
+#endif
+}
+
+void CSymmetricMatrix::CalcInv(bool is_spd)
+{
+#ifndef HAVE_LAPACK
+ const int sz = Size();
+
+ /*--- Compute inverse from decomposed matrices. ---*/
+ if (is_spd)
+ {
+ CholeskyDecompose();
+
+ /*--- Initialize inverse matrix. ---*/
+ CSymmetricMatrix inv(sz);
+
+ /*--- Compute L inverse. ---*/
+ /*--- Solve smaller and smaller systems. ---*/
+ for (int j = 0; j < sz; ++j) {
+ /*--- Forward substitution. ---*/
+ inv(j,j) = 1.0 / Get(j,j);
+
+ for (int i = j+1; i < sz; ++i) {
+ passivedouble sum = 0.0;
+ for (int k = j; k < i; ++k) sum -= Get(i,k) * inv(k,j);
+ inv(i,j) = sum / Get(i,i);
+ }
+ } // L inverse in inv
+
+ /*--- Multiply inversed matrices overwrite mat. ---*/
+ for (int j = 0; j < sz; ++j)
+ for (int i = j; i < sz; ++i) {
+ passivedouble sum = 0.0;
+ for (int k = i; k < sz; ++k) sum += inv(k,i) * inv(k,j);
+ Set(i, j, sum);
+ }
+ }
+ else
+ {
+ su2passivematrix decomp;
+ vector perm;
+ LUDecompose(decomp, perm);
+
+ /*--- Alias mat. ---*/
+ auto& inv = mat;
+
+ /*--- Invert L and U matrices in place. ---*/
+ for (int j = 0; j < sz; ++j) {
+ inv(j,j) = 1.0 / decomp(j,j);
+
+ for (int i = j+1; i < sz; ++i) {
+ inv(i,j) = -decomp(i,j);
+ inv(j,i) = -decomp(j,i) * inv(j,j);
+
+ for (int k = j+1; k < i; ++k) {
+ inv(i,j) -= decomp(i,k) * inv(k,j);
+ inv(j,i) -= decomp(k,i) * inv(j,k);
+ }
+ if (j+1 <= i) inv(j,i) /= decomp(i,i);
+ }
+ }
+ // inverses in mat
+
+ /*--- Multiply U_inv by L_inv, overwrite decomp_vec. ---*/
+ for (int i = 0; i < sz; ++i)
+ for (int j = 0; j < sz; ++j) {
+ decomp(i,j) = 0.0;
+ for (int k = max(i,j); k < sz; ++k)
+ decomp(i,j) += inv(i,k) * ((k==j)? 1.0 : inv(k,j));
+ }
+
+ /*--- Permute multiplied matrix to recover A_inv, overwrite mat. ---*/
+ for (int j = 0; j < sz; ++j) {
+ int k = perm[j];
+ for (int i = k; i < sz; ++i) Set(i, k, decomp(i,j));
+ }
+ }
+#endif
+}
+
+void CSymmetricMatrix::CalcInv_sytri()
+{
+#ifdef HAVE_LAPACK
+ const char uplo = 'L';
+ const int sz = Size();
+ int info;
+ vector ipiv(sz);
+
+ /*--- Query the optimum work size. ---*/
+ int query = -1; passivedouble tmp;
+ dsytrf_(&uplo, &sz, mat.data(), &sz, ipiv.data(), &tmp, &query, &info);
+ query = static_cast(tmp);
+ vector work(query);
+
+ /*--- Factorize and invert. ---*/
+ dsytrf_(&uplo, &sz, mat.data(), &sz, ipiv.data(), work.data(), &query, &info);
+ if (info!=0) SU2_MPI::Error("LDLT factorization failed.", CURRENT_FUNCTION);
+ dsytri_(&uplo, &sz, mat.data(), &sz, ipiv.data(), work.data(), &info);
+ if (info!=0) SU2_MPI::Error("Inversion with LDLT factorization failed.", CURRENT_FUNCTION);
+#endif
+}
+
+void CSymmetricMatrix::CalcInv_potri()
+{
+#ifdef HAVE_LAPACK
+ const char uplo = 'L';
+ const int sz = Size();
+ int info;
+
+ dpotrf_(&uplo, &sz, mat.data(), &sz, &info);
+ if (info!=0) SU2_MPI::Error("LLT factorization failed.", CURRENT_FUNCTION);
+ dpotri_(&uplo, &sz, mat.data(), &sz, &info);
+ if (info!=0) SU2_MPI::Error("Inversion with LLT factorization failed.", CURRENT_FUNCTION);
+#endif
+}
+
+void CSymmetricMatrix::Invert(const bool is_spd)
+{
+#ifdef HAVE_LAPACK
+ if(is_spd) CalcInv_potri();
+ else CalcInv_sytri();
+#else
+ CalcInv(is_spd);
+#endif
+}
+
+void CSymmetricMatrix::MatMatMult(const char side,
+ const su2passivematrix& mat_in,
+ su2passivematrix& mat_out) const
+{
+ /*--- Left side: mat_out = this * mat_in. ---*/
+ if (side == 'L' || side == 'l') {
+ const int M = Size(), N = mat_in.cols();
+ assert(M == mat_in.rows());
+
+ mat_out.resize(M,N);
+
+#ifdef HAVE_LAPACK
+ /*--- Right and lower because matrices are in row major order. ---*/
+ const char side = 'R', uplo = 'L';
+ const passivedouble alpha = 1.0, beta = 0.0;
+ DSYMM(&side, &uplo, &N, &M, &alpha, mat.data(), &M,
+ mat_in.data(), &N, &beta, mat_out.data(), &N);
+#else // Naive product
+ for (int i = 0; i < M; ++i)
+ for (int j = 0; j < N; ++j) {
+ mat_out(i,j) = 0.0;
+ for (int k = 0; k < M; ++k)
+ mat_out(i,j) += Get(i,k) * mat_in(k,j);
+ }
+#endif
+ }
+ /*--- Right_side: mat_out = mat_in * this. ---*/
+ else {
+ const int M = mat_in.rows(), N = Size();
+ assert(N == mat_in.cols());
+
+ mat_out.resize(M,N);
+
+#ifdef HAVE_LAPACK
+ /*--- Left and lower because matrices are in row major order. ---*/
+ const char side = 'L', uplo = 'L';
+ const passivedouble alpha = 1.0, beta = 0.0;
+ DSYMM(&side, &uplo, &N, &M, &alpha, mat.data(), &N,
+ mat_in.data(), &N, &beta, mat_out.data(), &N);
+#else // Naive product
+ for (int i = 0; i < M; ++i)
+ for (int j = 0; j < N; ++j) {
+ mat_out(i,j) = 0.0;
+ for (int k = 0; k < N; ++k)
+ mat_out(i,j) += mat_in(i,k) * Get(k,j);
+ }
+#endif
+ }
+}
+
+su2passivematrix CSymmetricMatrix::StealData()
+{
+ /*--- Fill lower triangular part. ---*/
+ for (int i = 1; i < Size(); ++i)
+ for (int j = 0; j < i; ++j)
+ mat(i,j) = mat(j,i);
+
+ return move(mat);
+}
diff --git a/Common/src/toolboxes/meson.build b/Common/src/toolboxes/meson.build
index c753d5142564..123713157639 100644
--- a/Common/src/toolboxes/meson.build
+++ b/Common/src/toolboxes/meson.build
@@ -1,5 +1,6 @@
common_src += files(['CLinearPartitioner.cpp',
'printing_toolbox.cpp',
- 'C1DInterpolation.cpp'])
+ 'C1DInterpolation.cpp',
+ 'CSymmetricMatrix.cpp'])
subdir('MMS')
diff --git a/SU2_CFD/include/SU2_CFD.hpp b/SU2_CFD/include/SU2_CFD.hpp
index 918f7532d9b0..2ebd56836ddb 100644
--- a/SU2_CFD/include/SU2_CFD.hpp
+++ b/SU2_CFD/include/SU2_CFD.hpp
@@ -44,7 +44,6 @@
#include "../../Common/include/geometry/CGeometry.hpp"
#include "../../Common/include/grid_movement_structure.hpp"
#include "../../Common/include/CConfig.hpp"
-#include "../../Common/include/interpolation_structure.hpp"
#include "../include/definition_structure.hpp"
#include "../include/iteration_structure.hpp"
#include "../include/interfaces/CInterface.hpp"
diff --git a/SU2_CFD/include/drivers/CDiscAdjMultizoneDriver.hpp b/SU2_CFD/include/drivers/CDiscAdjMultizoneDriver.hpp
index 4e6126c93c64..1041ad8941a7 100644
--- a/SU2_CFD/include/drivers/CDiscAdjMultizoneDriver.hpp
+++ b/SU2_CFD/include/drivers/CDiscAdjMultizoneDriver.hpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -187,12 +187,6 @@ class CDiscAdjMultizoneDriver : public CMultizoneDriver {
*/
void Update_Cross_Term(unsigned short iZone, unsigned short jZone);
- /*!
- * \brief Saves the current (adjoint) Solution vector to Solution_BGS_k.
- * \param[in] iZone - Zone index.
- */
- void Set_BGSSolution(unsigned short iZone);
-
/*!
* \brief Compute BGS residuals.
* \param[in] iZone - Zone where solver residuals are computed.
diff --git a/SU2_CFD/include/drivers/CDriver.hpp b/SU2_CFD/include/drivers/CDriver.hpp
index d0ee1f4d30ae..c104b344fd40 100644
--- a/SU2_CFD/include/drivers/CDriver.hpp
+++ b/SU2_CFD/include/drivers/CDriver.hpp
@@ -37,11 +37,11 @@
#include "../../../Common/include/geometry/CGeometry.hpp"
#include "../../../Common/include/grid_movement_structure.hpp"
-#include "../../../Common/include/interpolation_structure.hpp"
using namespace std;
class COutputLegacy;
+class CInterpolator;
/*!
* \class CDriver
@@ -204,8 +204,8 @@ class CDriver {
* \brief Definition and allocation of all interface classes.
*/
void Interface_Preprocessing(CConfig **config, CSolver *****solver, CGeometry ****geometry,
- unsigned short **interface_types, CInterface ***&interface,
- CInterpolator ***&interpolation);
+ unsigned short **interface_types, CInterface ***interface,
+ CInterpolator ***interpolation);
/*!
* \brief Definition and allocation of all solver classes.
@@ -1082,269 +1082,3 @@ class CHBDriver : public CFluidDriver {
*/
void ResetConvergence();
};
-
-/*!
- * \class CDiscAdjFSIDriver
- * \brief Overload: Class for driving a discrete adjoint FSI iteration.
- * \author R. Sanchez.
- * \version 7.0.3 "Blackbird"
- */
-class CDiscAdjFSIDriver : public CDriver {
-
- COutputLegacy* output_legacy;
-
- CIteration** direct_iteration;
- unsigned short RecordingState;
- unsigned short CurrentRecording; /*!< \brief Stores the current status of the recording. */
- unsigned short Kind_Objective_Function; /*!< \brief Stores the kind of objective function of the recording. */
-
- su2double *init_res_flow, /*!< \brief Stores the initial residual for the flow. */
- *init_res_struct, /*!< \brief Stores the initial residual for the structure. */
- *residual_flow, /*!< \brief Stores the current residual for the flow. */
- *residual_struct, /*!< \brief Stores the current residual for the structure. */
- *residual_flow_rel,
- *residual_struct_rel;
-
- su2double flow_criteria,
- flow_criteria_rel,
- structure_criteria,
- structure_criteria_rel;
-
-
- enum OF_KIND{
- NO_OBJECTIVE_FUNCTION = 0, /*!< \brief Indicates that there is no objective function. */
- FLOW_OBJECTIVE_FUNCTION = 1, /*!< \brief Indicates that the objective function is only flow-dependent. */
- FEM_OBJECTIVE_FUNCTION = 2 /*!< \brief Indicates that the objective function is only structural-dependent. */
- };
-
-public:
-
- /*!
- * \brief Constructor of the class.
- * \param[in] confFile - Configuration file name.
- * \param[in] val_nZone - Total number of zones.
- * \param[in] val_nDim - Total number of dimensions.
- * \param[in] MPICommunicator - MPI communicator for SU2.
- */
- CDiscAdjFSIDriver(char* confFile,
- unsigned short val_nZone,
- SU2_Comm MPICommunicator);
-
- /*!
- * \brief Destructor of the class.
- */
- ~CDiscAdjFSIDriver(void);
-
- /*!
- * \brief Launch the computation for FSI adjoint (legacy) driver
- */
- inline void StartSolver(){
-
- /*--- Run the solver. ---*/
- if (rank == MASTER_NODE)
- cout << endl <<"------------------------------ Begin Solver -----------------------------" << endl;
- Run();
- }
-
- /*!
- * \brief Run a Discrete Adjoint iteration for the FSI problem.
- * \param[in] iteration_container - Container vector with all the iteration methods.
- * \param[in] output - Pointer to the COutput class.
- * \param[in] integration_container - Container vector with all the integration methods.
- * \param[in] geometry_container - Geometrical definition of the problem.
- * \param[in] solver_container - Container vector with all the solutions.
- * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved).
- * \param[in] config_container - Definition of the particular problem.
- * \param[in] surface_movement - Surface movement classes of the problem.
- * \param[in] grid_movement - Volume grid movement classes of the problem.
- * \param[in] FFDBox - FFD FFDBoxes of the problem.
- */
-
- void Run();
-
- /*!
- * \brief Iterate the direct solver for recording.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
-
- void Iterate_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, unsigned short kind_recording);
-
- /*!
- * \brief Run a direct flow iteration.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- */
- void Fluid_Iteration_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT);
-
- /*!
- * \brief Run a direct structural iteration.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- */
- void Structural_Iteration_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT);
-
- /*!
- * \brief Run a direct mesh deformation.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- */
- void Mesh_Deformation_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT);
-
- /*!
- * \brief Set the recording for a Discrete Adjoint iteration for the FSI problem.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
-
- void SetRecording(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Load the restarts for fluid, structure and mesh.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void Preprocess(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Iterate a certain block for adjoint FSI - may be the whole set of variables or independent and subiterate
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void Iterate_Block(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Initialize the adjoint - set the objective funcition and the output of the adjoint iteration
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void InitializeAdjoint(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Extract the adjoint solution variables
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void ExtractAdjoint(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
-
- /*!
- * \brief Check the convergence of the problem
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- bool CheckConvergence(unsigned long IntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Check the convergence of BGS subiteration process
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- bool BGSConvergence(unsigned long IntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT);
-
-
- /*!
- * \brief Output the convergence history
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void ConvergenceHistory(unsigned long IntIter,
- unsigned long nIntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Load the restarts for fluid, structure and mesh.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void PrintDirect_Residuals(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Restart the variables to the converged solution.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void PrepareRecording(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Register the input variables for adjoint FSI problems: flow conservative, fluid mesh position and structural displacements.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void RegisterInput(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Register the input variables for adjoint FSI problems: flow conservative, fluid mesh position and structural displacements.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void SetDependencies(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Restart the output variables for adjoint FSI problems: flow conservative, fluid mesh position and structural displacements.
- * \param[in] ZONE_FLOW - zone of the fluid solver.
- * \param[in] ZONE_STRUCT - zone of the structural solver.
- * \param[in] kind_recording - kind of recording (flow, structure, mesh, cross terms)
- */
- void RegisterOutput(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording);
-
- /*!
- * \brief Overload, does nothing but avoids dynamic mesh updates in adjoint FSI problems before the iteration
- */
- void DynamicMeshUpdate(unsigned long TimeIter);
-
- /*!
- * \brief Transfer the displacements computed on the structural solver into the fluid solver.
- * \param[in] donorZone - zone in which the displacements will be transferred.
- * \param[in] targetZone - zone which receives the tractions transferred.
- */
- void Transfer_Displacements(unsigned short donorZone, unsigned short targetZone);
-
- /*!
- * \brief Transfer the tractions computed on the fluid solver into the structural solver.
- * \param[in] donorZone - zone from which the tractions will be transferred.
- * \param[in] targetZone - zone which receives the tractions transferred.
- */
- void Transfer_Tractions(unsigned short donorZone, unsigned short targetZone);
-
-};
diff --git a/SU2_CFD/include/interfaces/CInterface.hpp b/SU2_CFD/include/interfaces/CInterface.hpp
index dd593dfc6733..e8b08afe9e95 100644
--- a/SU2_CFD/include/interfaces/CInterface.hpp
+++ b/SU2_CFD/include/interfaces/CInterface.hpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -56,20 +56,20 @@ using namespace std;
class CInterface {
protected:
- int rank, /*!< \brief MPI Rank. */
- size; /*!< \brief MPI Size. */
+ const int rank; /*!< \brief MPI Rank. */
+ const int size; /*!< \brief MPI Size. */
- su2double *Physical_Constants;
- su2double *Donor_Variable;
- su2double *Target_Variable;
- bool valAggregated;
+ su2double *Physical_Constants = nullptr;
+ su2double *Donor_Variable = nullptr;
+ su2double *Target_Variable = nullptr;
+ bool valAggregated = false;
/*--- Mixing Plane interface variable ---*/
- su2double *SpanValueCoeffTarget;
- unsigned short *SpanLevelDonor;
- unsigned short nSpanMaxAllZones;
+ su2double *SpanValueCoeffTarget = nullptr;
+ unsigned short *SpanLevelDonor = nullptr;
+ unsigned short nSpanMaxAllZones = 0;
- unsigned short nVar;
+ unsigned short nVar = 0;
public:
/*!
diff --git a/SU2_CFD/include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp b/SU2_CFD/include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp
deleted file mode 100644
index b603bacfe18a..000000000000
--- a/SU2_CFD/include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*!
- * \file CDiscAdjDisplacementsInterfaceLegacy.hpp
- * \brief Declaration and inlines of the class to transfer structural displacements
- * from a structural zone into a fluid zone in a discrete adjoint simulation.
- * \author Ruben Sanchez
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-
-#pragma once
-
-#include "../CInterface.hpp"
-
-class CDiscAdjDisplacementsInterfaceLegacy : public CInterface {
-
-protected:
-
-public:
-
- /*!
- * \brief Constructor of the class.
- */
- CDiscAdjDisplacementsInterfaceLegacy(void);
-
- /*!
- * \overload
- * \param[in] val_nVar - Number of variables that need to be transferred.
- * \param[in] config - Definition of the particular problem.
- */
- CDiscAdjDisplacementsInterfaceLegacy(unsigned short val_nVar, unsigned short val_nConst, CConfig *config);
-
- /*!
- * \brief Destructor of the class.
- */
- virtual ~CDiscAdjDisplacementsInterfaceLegacy(void);
-
- /*!
- * \brief Retrieve some constants needed for the calculations.
- * \param[in] donor_solution - Solution from the donor mesh.
- * \param[in] target_solution - Solution from the target mesh.
- * \param[in] donor_geometry - Geometry of the donor mesh.
- * \param[in] target_geometry - Geometry of the target mesh.
- * \param[in] donor_config - Definition of the problem at the donor mesh.
- * \param[in] target_config - Definition of the problem at the target mesh.
- */
- void GetPhysical_Constants(CSolver *donor_solution, CSolver *target_solution,
- CGeometry *donor_geometry, CGeometry *target_geometry,
- CConfig *donor_config, CConfig *target_config);
-
- /*!
- * \brief Retrieve the variable that will be sent from donor mesh to target mesh.
- * \param[in] donor_solution - Solution from the donor mesh.
- * \param[in] donor_geometry - Geometry of the donor mesh.
- * \param[in] donor_config - Definition of the problem at the donor mesh.
- * \param[in] Marker_Donor - Index of the donor marker.
- * \param[in] Vertex_Donor - Index of the donor vertex.
- */
- void GetDonor_Variable(CSolver *struct_solution, CGeometry *struct_geometry, CConfig *struct_config,
- unsigned long Marker_Struct, unsigned long Vertex_Struct, unsigned long Point_Struct);
-
- /*!
- * \brief Set the variable that has been received from the target mesh into the target mesh.
- * \param[in] target_solution - Solution from the target mesh.
- * \param[in] target_geometry - Geometry of the target mesh.
- * \param[in] target_config - Definition of the problem at the target mesh.
- * \param[in] Marker_Target - Index of the target marker.
- * \param[in] Vertex_Target - Index of the target vertex.
- * \param[in] Point_Target - Index of the target point.
- */
- void SetTarget_Variable(CSolver *flow_solution, CGeometry *flow_geometry,
- CConfig *flow_config, unsigned long Marker_Flow,
- unsigned long Vertex_Flow, unsigned long Point_Flow);
-
-};
-
diff --git a/SU2_CFD/include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp b/SU2_CFD/include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp
index 8dd8dd5cf216..303ba00f5160 100644
--- a/SU2_CFD/include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp
+++ b/SU2_CFD/include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -31,27 +31,14 @@
#include "CFlowTractionInterface.hpp"
class CDiscAdjFlowTractionInterface : public CFlowTractionInterface {
-
-protected:
-
public:
-
- /*!
- * \brief Constructor of the class.
- */
- CDiscAdjFlowTractionInterface(void);
-
/*!
* \overload
* \param[in] val_nVar - Number of variables that need to be transferred.
* \param[in] config - Definition of the particular problem.
*/
- CDiscAdjFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst, CConfig *config);
-
- /*!
- * \brief Destructor of the class.
- */
- virtual ~CDiscAdjFlowTractionInterface(void);
+ CDiscAdjFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst,
+ CConfig *config, bool integrate_tractions_);
/*!
* \brief Retrieve some constants needed for the calculations.
@@ -64,6 +51,6 @@ class CDiscAdjFlowTractionInterface : public CFlowTractionInterface {
*/
void GetPhysical_Constants(CSolver *donor_solution, CSolver *target_solution,
CGeometry *donor_geometry, CGeometry *target_geometry,
- CConfig *donor_config, CConfig *target_config);
+ CConfig *donor_config, CConfig *target_config) override;
};
diff --git a/SU2_CFD/include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp b/SU2_CFD/include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp
deleted file mode 100644
index eb30c3e11905..000000000000
--- a/SU2_CFD/include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*!
- * \file CDisplacementsInterfaceLegacy.hpp
- * \brief Declaration and inlines of the class to transfer structural displacements
- * from a structural zone into a fluid zone.
- * \author Ruben Sanchez
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-
-#pragma once
-
-#include "../CInterface.hpp"
-
-class CDisplacementsInterfaceLegacy : public CInterface {
-
-protected:
-
-public:
-
- /*!
- * \brief Constructor of the class.
- */
- CDisplacementsInterfaceLegacy(void);
-
- /*!
- * \overload
- * \param[in] val_nVar - Number of variables that need to be transferred.
- * \param[in] config - Definition of the particular problem.
- */
- CDisplacementsInterfaceLegacy(unsigned short val_nVar, unsigned short val_nConst, CConfig *config);
-
- /*!
- * \brief Destructor of the class.
- */
- virtual ~CDisplacementsInterfaceLegacy(void);
-
- /*!
- * \brief Retrieve some constants needed for the calculations.
- * \param[in] donor_solution - Solution from the donor mesh.
- * \param[in] target_solution - Solution from the target mesh.
- * \param[in] donor_geometry - Geometry of the donor mesh.
- * \param[in] target_geometry - Geometry of the target mesh.
- * \param[in] donor_config - Definition of the problem at the donor mesh.
- * \param[in] target_config - Definition of the problem at the target mesh.
- */
- void GetPhysical_Constants(CSolver *donor_solution, CSolver *target_solution,
- CGeometry *donor_geometry, CGeometry *target_geometry,
- CConfig *donor_config, CConfig *target_config);
-
- /*!
- * \brief Retrieve the variable that will be sent from donor mesh to target mesh.
- * \param[in] donor_solution - Solution from the donor mesh.
- * \param[in] donor_geometry - Geometry of the donor mesh.
- * \param[in] donor_config - Definition of the problem at the donor mesh.
- * \param[in] Marker_Donor - Index of the donor marker.
- * \param[in] Vertex_Donor - Index of the donor vertex.
- */
- void GetDonor_Variable(CSolver *struct_solution, CGeometry *struct_geometry, CConfig *struct_config,
- unsigned long Marker_Struct, unsigned long Vertex_Struct, unsigned long Point_Struct);
-
- /*!
- * \brief Set the variable that has been received from the target mesh into the target mesh.
- * \param[in] target_solution - Solution from the target mesh.
- * \param[in] target_geometry - Geometry of the target mesh.
- * \param[in] target_config - Definition of the problem at the target mesh.
- * \param[in] Marker_Target - Index of the target marker.
- * \param[in] Vertex_Target - Index of the target vertex.
- * \param[in] Point_Target - Index of the target point.
- */
- void SetTarget_Variable(CSolver *flow_solution, CGeometry *flow_geometry,
- CConfig *flow_config, unsigned long Marker_Flow,
- unsigned long Vertex_Flow, unsigned long Point_Flow);
-
-};
diff --git a/SU2_CFD/include/interfaces/fsi/CFlowTractionInterface.hpp b/SU2_CFD/include/interfaces/fsi/CFlowTractionInterface.hpp
index fefd56afa569..2e338f5cf875 100644
--- a/SU2_CFD/include/interfaces/fsi/CFlowTractionInterface.hpp
+++ b/SU2_CFD/include/interfaces/fsi/CFlowTractionInterface.hpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -31,10 +31,10 @@
#include "../CInterface.hpp"
class CFlowTractionInterface : public CInterface {
+private:
+ bool integrate_tractions;
protected:
- bool consistent_interpolation;
-
/*!
* \brief Sets the dimensional factor for pressure and the consistent_interpolation flag
* \param[in] flow_config - Definition of the fluid (donor) problem.
@@ -42,23 +42,16 @@ class CFlowTractionInterface : public CInterface {
void Preprocess(CConfig *flow_config);
public:
-
- /*!
- * \brief Constructor of the class.
- */
- CFlowTractionInterface(void);
-
/*!
* \overload
* \param[in] val_nVar - Number of variables that need to be transferred.
+ * \param[in] val_nConst - Number of constants.
* \param[in] config - Definition of the particular problem.
+ * \param[in] integrate_tractions_ - Whether to integrate the fluid tractions
+ * (to transfer forces when using conservative interpolation).
*/
- CFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst, CConfig *config);
-
- /*!
- * \brief Destructor of the class.
- */
- virtual ~CFlowTractionInterface(void);
+ CFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst,
+ CConfig *config, bool integrate_tractions_);
/*!
* \brief Retrieve some constants needed for the calculations.
@@ -71,7 +64,7 @@ class CFlowTractionInterface : public CInterface {
*/
void GetPhysical_Constants(CSolver *donor_solution, CSolver *target_solution,
CGeometry *donor_geometry, CGeometry *target_geometry,
- CConfig *donor_config, CConfig *target_config);
+ CConfig *donor_config, CConfig *target_config) override;
/*!
* \brief Retrieve the variable that will be sent from donor mesh to target mesh.
@@ -82,7 +75,7 @@ class CFlowTractionInterface : public CInterface {
* \param[in] Vertex_Donor - Index of the donor vertex.
*/
void GetDonor_Variable(CSolver *flow_solution, CGeometry *flow_geometry, CConfig *flow_config,
- unsigned long Marker_Flow, unsigned long Vertex_Flow, unsigned long Point_Flow);
+ unsigned long Marker_Flow, unsigned long Vertex_Flow, unsigned long Point_Flow) override;
/*!
* \brief Set the variable that has been received from the target mesh into the target mesh.
@@ -95,6 +88,6 @@ class CFlowTractionInterface : public CInterface {
*/
void SetTarget_Variable(CSolver *fea_solution, CGeometry *fea_geometry,
CConfig *fea_config, unsigned long Marker_Struct,
- unsigned long Vertex_Struct, unsigned long Point_Struct);
+ unsigned long Vertex_Struct, unsigned long Point_Struct) override;
};
diff --git a/SU2_CFD/include/limiters/computeLimiters_impl.hpp b/SU2_CFD/include/limiters/computeLimiters_impl.hpp
index 9b4cd2fd3888..47c257349989 100644
--- a/SU2_CFD/include/limiters/computeLimiters_impl.hpp
+++ b/SU2_CFD/include/limiters/computeLimiters_impl.hpp
@@ -98,15 +98,13 @@ void computeLimiters_impl(CSolver* solver,
omp_get_max_threads(), OMP_MAX_CHUNK);
#endif
-#ifdef CODI_REVERSE_TYPE
bool tapeActive = false;
if (config.GetDiscrete_Adjoint() && config.GetFrozen_Limiter_Disc()) {
/*--- If limiters are frozen do not record the computation ---*/
- tapeActive = AD::globalTape.isActive();
+ tapeActive = AD::TapeActive();
AD::StopRecording();
}
-#endif
CLimiterDetails limiterDetails;
@@ -248,8 +246,6 @@ void computeLimiters_impl(CSolver* solver,
}
SU2_OMP_BARRIER
-#ifdef CODI_REVERSE_TYPE
if (tapeActive) AD::StartRecording();
-#endif
}
diff --git a/SU2_CFD/include/output/COutputLegacy.hpp b/SU2_CFD/include/output/COutputLegacy.hpp
index 3a3ce66c44b4..bd347d8578a9 100644
--- a/SU2_CFD/include/output/COutputLegacy.hpp
+++ b/SU2_CFD/include/output/COutputLegacy.hpp
@@ -321,17 +321,6 @@ class COutputLegacy {
*/
void SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output);
- /*!
- * \brief Create and write the file with the FSI convergence history.
- * \param[in] config - Definition of the particular problem.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] solver_container - Solver for all physical problems.
- * \param[in] iExtIter - Current external (time) iteration.
- * \param[in] val_iZone - Current zone number in the grid file.
- */
- void SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container, CConfig **config, CIntegration ****integration,
- unsigned long iExtIter, unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header);
-
/*!
* \brief Create and write the file with the FSI convergence history.
* \param[in] iIter - Current iteration.
diff --git a/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp b/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp
index 1c2593c75ab2..4e0919a696bc 100644
--- a/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp
+++ b/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp
@@ -161,22 +161,6 @@ class CDiscAdjFEASolver final : public CSolver {
*/
void ExtractAdjoint_Solution(CGeometry *geometry, CConfig *config) override;
- /*!
- * \brief Sets the adjoint values of the structural variables due to cross term contributions
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- void ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *config) override;
-
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- void ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config) override;
-
/*!
* \brief Register the objective function as output.
* \param[in] geometry - The geometrical definition of the problem.
@@ -386,11 +370,4 @@ class CDiscAdjFEASolver final : public CSolver {
int val_iter,
bool val_update_geo) override;
- /*!
- * \brief Compute the multizone residual.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config) override;
-
};
diff --git a/SU2_CFD/include/solvers/CDiscAdjMeshSolver.hpp b/SU2_CFD/include/solvers/CDiscAdjMeshSolver.hpp
index 3a3b2ce6a72d..f128389ea832 100644
--- a/SU2_CFD/include/solvers/CDiscAdjMeshSolver.hpp
+++ b/SU2_CFD/include/solvers/CDiscAdjMeshSolver.hpp
@@ -102,12 +102,6 @@ class CDiscAdjMeshSolver final : public CSolver {
*/
void SetSensitivity(CGeometry *geometry, CSolver **solver, CConfig *config) override;
- /*!
- * \brief Set the value of the max residual and RMS residual.
- * \param[in] val_iterlinsolver - Number of linear iterations.
- */
- void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config) override;
-
/*!
* \brief Prepare the solver for a new recording.
* \param[in] kind_recording - Kind of AD recording.
diff --git a/SU2_CFD/include/solvers/CDiscAdjSolver.hpp b/SU2_CFD/include/solvers/CDiscAdjSolver.hpp
index a27d1acb9c0c..f654c2637356 100644
--- a/SU2_CFD/include/solvers/CDiscAdjSolver.hpp
+++ b/SU2_CFD/include/solvers/CDiscAdjSolver.hpp
@@ -140,30 +140,6 @@ class CDiscAdjSolver final : public CSolver {
*/
void ExtractAdjoint_Geometry(CGeometry *geometry, CConfig *config) override;
- /*!
- * \brief Sets the adjoint values of the flow variables due to cross term contributions
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- void ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *config) override;
-
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- void ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config) override;
-
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- void ExtractAdjoint_CrossTerm_Geometry_Flow(CGeometry *geometry, CConfig *config) override;
-
/*!
* \brief Register the objective function as output.
* \param[in] geometry - The geometrical definition of the problem.
@@ -321,11 +297,4 @@ class CDiscAdjSolver final : public CSolver {
int val_iter,
bool val_update_geo) override;
- /*!
- * \brief Compute the multizone residual.
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- */
- void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config) override;
-
};
diff --git a/SU2_CFD/include/solvers/CFEASolver.hpp b/SU2_CFD/include/solvers/CFEASolver.hpp
index fd413735ae75..02b6f463ae4f 100644
--- a/SU2_CFD/include/solvers/CFEASolver.hpp
+++ b/SU2_CFD/include/solvers/CFEASolver.hpp
@@ -46,7 +46,7 @@ class CFEASolver : public CSolver {
su2double Total_CFEA; /*!< \brief Total FEA coefficient for all the boundaries. */
- unsigned short *iElem_iDe; /*!< \brief For DE cases, ID of the region considered for each iElem. */
+ unsigned short *iElem_iDe = nullptr; /*!< \brief For DE cases, ID of the region considered for each iElem. */
su2double a_dt[9]; /*!< \brief Integration constants. */
@@ -87,9 +87,13 @@ class CFEASolver : public CSolver {
bool element_based; /*!< \brief Bool to determine if an element-based file is used. */
bool topol_filter_applied; /*!< \brief True if density filtering has been performed. */
+ bool initial_calc = true; /*!< \brief Becomes false after first call to Preprocessing. */
unsigned long nElement; /*!< \brief Number of elements. */
+ /*--- Extra vertices for row/column elimination, see Set_VertexEliminationSchedule. ---*/
+ vector ExtraVerticesToEliminate;
+
/*!
* \brief The highest level in the variable hierarchy this solver can safely use,
* CVariable is the common denominator between the FEA and Mesh deformation variables.
@@ -146,6 +150,15 @@ class CFEASolver : public CSolver {
*/
void Set_Prestretch(CGeometry *geometry, CConfig *config);
+ /*!
+ * \brief Mitigation for an issue with Dirichlet boundary conditions and MPI,
+ * some ranks do not get enough of the markers to cover their halo points.
+ * This breaks the symmetry of the global matrix as columns are not fully eliminated.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] markers - List of essential BC markers.
+ */
+ void Set_VertexEliminationSchedule(CGeometry *geometry, const vector& markers);
+
/*!
* \brief Compute constants for time integration.
* \param[in] config - Definition of the particular problem.
@@ -179,8 +192,8 @@ class CFEASolver : public CSolver {
CSysMatrix MassMatrix; /*!< \brief Sparse structure for storing the mass matrix. */
- CElement*** element_container; /*!< \brief Vector which the define the finite element structure for each problem. */
- CProperty** element_properties; /*!< \brief Vector which stores the properties of each element */
+ CElement*** element_container = nullptr; /*!< \brief Vector which the define the finite element structure for each problem. */
+ CProperty** element_properties = nullptr; /*!< \brief Vector which stores the properties of each element */
/*!
* \brief Constructor of the class.
@@ -454,7 +467,7 @@ class CFEASolver : public CSolver {
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
*/
- void Integrate_FSI_Loads(CGeometry *geometry, CConfig *config);
+ void Integrate_FSI_Loads(CGeometry *geometry, const CConfig *config);
/*!
* \brief Update the solution using an implicit solver.
diff --git a/SU2_CFD/include/solvers/CMeshSolver.hpp b/SU2_CFD/include/solvers/CMeshSolver.hpp
index b4d2196792ba..3dcd474c7e5a 100644
--- a/SU2_CFD/include/solvers/CMeshSolver.hpp
+++ b/SU2_CFD/include/solvers/CMeshSolver.hpp
@@ -172,45 +172,37 @@ class CMeshSolver final : public CFEASolver {
* \return
*/
inline su2double GetMaximum_Volume() const override {return MaxVolume_Curr;}
-
+
/*!
* \brief Pitching definition for deforming mesh
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
+ * \param[in] iter - Current time iteration number
*/
- void Surface_Pitching(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
+ void Surface_Pitching(CGeometry *geometry, CConfig *config, unsigned long iter);
/*!
* \brief Rotating definition for deforming mesh
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
* \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
*/
- void Surface_Rotating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
+ void Surface_Rotating(CGeometry *geometry, CConfig *config, unsigned long iter);
/*!
* \brief Plunging definition for deforming mesh
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
* \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
*/
- void Surface_Plunging(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
+ void Surface_Plunging(CGeometry *geometry, CConfig *config, unsigned long iter);
/*!
* \brief Translating definition for deforming mesh
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
* \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
*/
- void Surface_Translating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone);
+ void Surface_Translating(CGeometry *geometry, CConfig *config, unsigned long iter);
};
diff --git a/SU2_CFD/include/solvers/CSolver.hpp b/SU2_CFD/include/solvers/CSolver.hpp
index 414e5959f723..d2bf6e363e6a 100644
--- a/SU2_CFD/include/solvers/CSolver.hpp
+++ b/SU2_CFD/include/solvers/CSolver.hpp
@@ -272,18 +272,13 @@ class CSolver {
* \brief Set the value of the max residual and RMS residual.
* \param[in] val_iterlinsolver - Number of linear iterations.
*/
- virtual void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config);
+ void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config);
/*!
* \brief Move the mesh in time
*/
inline virtual void SetDualTime_Mesh(void){ }
- /*!
- * \brief Store the BGS solution in the previous subiteration in the corresponding vector.
- */
- void UpdateSolution_BGS(CGeometry *geometry, CConfig *config);
-
/*!
* \brief Set the solver nondimensionalization.
* \param[in] config - Definition of the particular problem.
@@ -3907,30 +3902,6 @@ class CSolver {
*/
inline virtual void ExtractAdjoint_Geometry(CGeometry *geometry, CConfig *config) {}
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- inline virtual void ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *config) {}
-
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- inline virtual void ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config) {}
-
- /*!
- * \brief A virtual member.
- * \param[in] geometry - The geometrical definition of the problem.
- * \param[in] solver_container - The solver container holding all solutions.
- * \param[in] config - The particular config.
- */
- inline virtual void ExtractAdjoint_CrossTerm_Geometry_Flow(CGeometry *geometry, CConfig *config) {}
-
/*!
* \brief A virtual member
* \param[in] geometry - The geometrical definition of the problem.
@@ -4577,42 +4548,6 @@ class CSolver {
CNumerics **numerics,
CConfig *config) { }
- /*!
- * \brief Pitching definition for deforming mesh
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
- */
- inline virtual void Surface_Pitching(CGeometry *geometry, CConfig *config, unsigned long iter, unsigned short iZone) { }
-
- /*!
- * \brief Rotating definition for deforming mesh
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
- */
- inline virtual void Surface_Rotating(CGeometry *geometry, CConfig *config, unsigned long iter, unsigned short iZone) { }
-
- /*!
- * \brief Plunging definition for deforming mesh
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
- */
- inline virtual void Surface_Plunging(CGeometry *geometry, CConfig *config, unsigned long iter, unsigned short iZone) { }
-
- /*!
- * \brief Translating definition for deforming mesh
- * \param[in] geometry - Geometrical definition of the problem.
- * \param[in] config - Definition of the particular problem.
- * \param[in] iter - Current time iteration number
- * \param[in] iZone - Current zone
- */
- inline virtual void Surface_Translating(CGeometry *geometry, CConfig *config, unsigned long iter, unsigned short iZone) { }
-
/*!
* \brief A virtual member.
* \param[in] geometry - Geometrical definition.
diff --git a/SU2_CFD/include/variables/CDiscAdjFEAVariable.hpp b/SU2_CFD/include/variables/CDiscAdjFEAVariable.hpp
index 583607455fa8..5e0f9fa8aef1 100644
--- a/SU2_CFD/include/variables/CDiscAdjFEAVariable.hpp
+++ b/SU2_CFD/include/variables/CDiscAdjFEAVariable.hpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -60,11 +60,6 @@ class CDiscAdjFEAVariable : public CVariable {
MatrixType Solution_Direct_Vel;
MatrixType Solution_Direct_Accel;
- MatrixType Cross_Term_Derivative;
- MatrixType Geometry_CrossTerm_Derivative;
-
- MatrixType Solution_BGS;
-
/*!
* \brief Constructor of the class.
* \param[in] disp - Pointer to the adjoint value (initialization value).
@@ -240,44 +235,4 @@ class CDiscAdjFEAVariable : public CVariable {
*/
void Set_OldSolution_Vel() final;
- /*!
- * \brief Set the contribution of crossed terms into the derivative.
- */
- inline void SetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar, su2double der) final {
- Cross_Term_Derivative(iPoint,iVar) = der;
- }
-
- /*!
- * \brief Get the contribution of crossed terms into the derivative.
- */
- inline su2double GetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar) const final { return Cross_Term_Derivative(iPoint,iVar); }
-
- /*!
- * \brief A virtual member. Get the geometry solution.
- * \param[in] iVar - Index of the variable.
- * \return Value of the solution for the index iVar.
- */
- inline su2double GetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iVar) const final {
- return Geometry_CrossTerm_Derivative(iPoint,iVar);
- }
-
- /*!
- * \brief A virtual member. Set the value of the mesh solution (adjoint).
- * \param[in] der - cross term derivative.
- */
- inline void SetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iVar, su2double der) final {
- Geometry_CrossTerm_Derivative(iPoint,iVar) = der;
- }
-
- /*!
- * \brief Set the value of the adjoint solution in the current BGS subiteration.
- */
- inline void Set_BGSSolution(unsigned long iPoint, unsigned long iDim, su2double val_solution) final { Solution_BGS(iPoint,iDim) = val_solution; }
-
- /*!
- * \brief Get the value of the adjoint solution in the previous BGS subiteration.
- * \param[out] val_solution - adjoint solution in the previous BGS subiteration.
- */
- inline su2double Get_BGSSolution(unsigned long iPoint, unsigned long iDim) const final { return Solution_BGS(iPoint,iDim); }
-
};
diff --git a/SU2_CFD/include/variables/CDiscAdjMeshBoundVariable.hpp b/SU2_CFD/include/variables/CDiscAdjMeshBoundVariable.hpp
index 47b38adfac67..4eaeb801f413 100644
--- a/SU2_CFD/include/variables/CDiscAdjMeshBoundVariable.hpp
+++ b/SU2_CFD/include/variables/CDiscAdjMeshBoundVariable.hpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -37,8 +37,6 @@ class CDiscAdjMeshBoundVariable final : public CVariable {
MatrixType Bound_Disp_Sens; /*!< \brief Store the reference coordinates of the mesh. */
MatrixType Bound_Disp_Direct; /*!< \brief Store the reference boundary displacements of the mesh. */
- MatrixType Solution_BGS_k; /*!< \brief BGS solution to compute overall convergence. */
-
CVertexMap VertexMap; /*!< \brief Object that controls accesses to the variables of this class. */
public:
@@ -115,11 +113,24 @@ class CDiscAdjMeshBoundVariable final : public CVariable {
VertexMap.SetIsVertex(iPoint,isVertex);
}
+ /*!
+ * \brief Get the value of the BGS solution.
+ */
+ inline su2double Get_BGSSolution(unsigned long iPoint, unsigned long iDim) const override {
+ if (!VertexMap.GetVertexIndex(iPoint)) return 0.0;
+ return Bound_Disp_Sens(iPoint,iDim);
+ }
+
/*!
* \brief Set the value of the solution in the previous BGS subiteration.
*/
void Set_BGSSolution_k() override;
+ /*!
+ * \brief Restore the previous BGS subiteration to solution.
+ */
+ void Restore_BGSSolution_k() override;
+
/*!
* \brief Get the value of the solution in the previous BGS subiteration.
* \param[out] val_solution - solution in the previous BGS subiteration.
@@ -129,4 +140,13 @@ class CDiscAdjMeshBoundVariable final : public CVariable {
return Solution_BGS_k(iPoint,iDim);
}
+ /*!
+ * \brief Get the value of the solution in the previous BGS subiteration.
+ * \param[out] val_solution - solution in the previous BGS subiteration.
+ */
+ inline void Set_BGSSolution_k(unsigned long iPoint, unsigned long iDim, su2double val) override {
+ if (!VertexMap.GetVertexIndex(iPoint)) return;
+ Solution_BGS_k(iPoint,iDim) = val;
+ }
+
};
diff --git a/SU2_CFD/include/variables/CDiscAdjVariable.hpp b/SU2_CFD/include/variables/CDiscAdjVariable.hpp
index 643d2fc551af..b0526199f38e 100644
--- a/SU2_CFD/include/variables/CDiscAdjVariable.hpp
+++ b/SU2_CFD/include/variables/CDiscAdjVariable.hpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -42,15 +42,10 @@ class CDiscAdjVariable final : public CVariable {
MatrixType DualTime_Derivative;
MatrixType DualTime_Derivative_n;
- MatrixType Cross_Term_Derivative;
- MatrixType Geometry_CrossTerm_Derivative;
- MatrixType Geometry_CrossTerm_Derivative_Flow;
-
MatrixType Solution_Geometry;
MatrixType Solution_Geometry_Old;
MatrixType Geometry_Direct;
- MatrixType Solution_BGS;
MatrixType Solution_Geometry_BGS_k;
public:
@@ -143,40 +138,6 @@ class CDiscAdjVariable final : public CVariable {
Solution_Geometry(iPoint,iVar) = val_solution_geometry;
}
- /*!
- * \brief A virtual member. Get the geometry solution.
- * \param[in] iVar - Index of the variable.
- * \return Value of the solution for the index iVar.
- */
- inline su2double GetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iVar) const override {
- return Geometry_CrossTerm_Derivative(iPoint,iVar);
- }
-
- /*!
- * \brief A virtual member. Set the value of the mesh solution (adjoint).
- * \param[in] der - cross term derivative.
- */
- inline void SetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iDim, su2double der) override {
- Geometry_CrossTerm_Derivative(iPoint,iDim) = der;
- }
-
- /*!
- * \brief Get the mesh cross term derivative from the flow solution.
- * \param[in] iVar - Index of the variable.
- * \return Value of the solution for the index iVar.
- */
- inline su2double GetGeometry_CrossTerm_Derivative_Flow(unsigned long iPoint, unsigned long iVar) const override {
- return Geometry_CrossTerm_Derivative_Flow(iPoint,iVar);
- }
-
- /*!
- * \brief Set the value of the mesh cross term derivative from the flow solution (adjoint).
- * \param[in] der - cross term derivative.
- */
- inline void SetGeometry_CrossTerm_Derivative_Flow(unsigned long iPoint, unsigned long iDim, su2double der) override {
- Geometry_CrossTerm_Derivative_Flow(iPoint,iDim) = der;
- }
-
/*!
* \brief Set the value of the mesh solution (adjoint).
*/
@@ -190,31 +151,4 @@ class CDiscAdjVariable final : public CVariable {
return Solution_Geometry_Old(iPoint,iDim);
}
- /*!
- * \brief Set the value of the adjoint solution in the current BGS subiteration.
- */
- inline void Set_BGSSolution(unsigned long iPoint, unsigned long iDim, su2double val_solution) override {
- Solution_BGS(iPoint,iDim) = val_solution;
- }
-
- /*!
- * \brief Get the value of the adjoint solution in the previous BGS subiteration.
- * \param[out] val_solution - adjoint solution in the previous BGS subiteration.
- */
- inline su2double Get_BGSSolution(unsigned long iPoint, unsigned long iDim) const override { return Solution_BGS(iPoint,iDim);}
-
- /*!
- * \brief Set the contribution of crossed terms into the derivative.
- */
- inline void SetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar, su2double der) override {
- Cross_Term_Derivative(iPoint,iVar) = der;
- }
-
- /*!
- * \brief Get the contribution of crossed terms into the derivative.
- */
- inline su2double GetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar) const override {
- return Cross_Term_Derivative(iPoint,iVar);
- }
-
};
diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp
index 87970a27c61e..5f4850025498 100644
--- a/SU2_CFD/include/variables/CVariable.hpp
+++ b/SU2_CFD/include/variables/CVariable.hpp
@@ -129,10 +129,10 @@ class CVariable {
unsigned long nSecondaryVar = 0; /*!< \brief Number of secondary variables. */
unsigned long nSecondaryVarGrad = 0; /*!< \brief Number of secondaries for which a gradient is computed. */
+ /*--- Only allow default construction by derived classes. ---*/
+ CVariable() = default;
public:
-
- /*--- Disable default construction copy and assignment. ---*/
- CVariable() = delete;
+ /*--- Disable copy and assignment. ---*/
CVariable(const CVariable&) = delete;
CVariable(CVariable&&) = delete;
CVariable& operator= (const CVariable&) = delete;
@@ -2098,32 +2098,6 @@ class CVariable {
*/
inline virtual void SetSolution_Geometry(unsigned long iPoint, unsigned long iVar, su2double solution_geometry) {}
- /*!
- * \brief A virtual member. Get the geometry solution.
- * \param[in] iVar - Index of the variable.
- * \return Value of the solution for the index iVar.
- */
- inline virtual su2double GetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iVar) const { return 0.0; }
-
- /*!
- * \brief A virtual member. Set the value of the mesh solution (adjoint).
- * \param[in] solution - Solution of the problem (acceleration).
- */
- inline virtual void SetGeometry_CrossTerm_Derivative(unsigned long iPoint, unsigned long iDim, su2double der) {}
-
- /*!
- * \brief A virtual member. Get the geometry solution.
- * \param[in] iVar - Index of the variable.
- * \return Value of the solution for the index iVar.
- */
- inline virtual su2double GetGeometry_CrossTerm_Derivative_Flow(unsigned long iPoint, unsigned long iVar) const { return 0.0;}
-
- /*!
- * \brief A virtual member. Set the value of the mesh solution (adjoint).
- * \param[in] solution - Solution of the problem (acceleration).
- */
- inline virtual void SetGeometry_CrossTerm_Derivative_Flow(unsigned long iPoint, unsigned long iDim, su2double der) {}
-
/*!
* \brief A virtual member. Set the value of the old geometry solution (adjoint).
*/
@@ -2136,9 +2110,13 @@ class CVariable {
inline virtual su2double Get_OldSolution_Geometry(unsigned long iPoint, unsigned long iDim) const { return 0.0; }
/*!
- * \brief A virtual member. Set the value of the old geometry solution (adjoint).
+ * \brief Get BGS solution to compute the BGS residual (difference between BGS and BGS_k).
+ * \note This is virtual because for some classes the result of a BGS iteration is not "Solution".
+ * If this method is overriden, the BGSSolution_k ones proabably have to be too.
*/
- inline virtual void Set_BGSSolution(unsigned long iPoint, unsigned long iDim, su2double solution) {}
+ inline virtual su2double Get_BGSSolution(unsigned long iPoint, unsigned long iVar) const {
+ return Solution(iPoint, iVar);
+ }
/*!
* \brief Set the value of the solution in the previous BGS subiteration.
@@ -2148,12 +2126,12 @@ class CVariable {
/*!
* \brief Restore the previous BGS subiteration to solution.
*/
- void Restore_BGSSolution_k();
+ virtual void Restore_BGSSolution_k();
/*!
* \brief Set the value of the solution in the previous BGS subiteration.
*/
- inline void Set_BGSSolution_k(unsigned long iPoint, unsigned long iVar, su2double val_var) {
+ inline virtual void Set_BGSSolution_k(unsigned long iPoint, unsigned long iVar, su2double val_var) {
Solution_BGS_k(iPoint,iVar) = val_var;
}
@@ -2165,23 +2143,6 @@ class CVariable {
return Solution_BGS_k(iPoint,iVar);
}
- /*!
- * \brief A virtual member. Get the value of the old geometry solution (adjoint).
- * \param[out] val_solution - old adjoint solution for coordinate iDim
- */
- inline virtual su2double Get_BGSSolution(unsigned long iPoint, unsigned long iDim) const {return 0.0;}
-
- /*!
- * \brief A virtual member. Set the contribution of crossed terms into the derivative.
- */
- inline virtual void SetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar, su2double der) {}
-
- /*!
- * \brief A virtual member. Get the contribution of crossed terms into the derivative.
- * \return The contribution of crossed terms into the derivative.
- */
- inline virtual su2double GetCross_Term_Derivative(unsigned long iPoint, unsigned long iVar) const { return 0.0; }
-
/*!
* \brief A virtual member. Set the direct velocity solution for the adjoint solver.
* \param[in] solution_direct - Value of the direct velocity solution.
diff --git a/SU2_CFD/obj/Makefile.am b/SU2_CFD/obj/Makefile.am
index 57221ace52f3..6bf3d7c713b3 100644
--- a/SU2_CFD/obj/Makefile.am
+++ b/SU2_CFD/obj/Makefile.am
@@ -126,7 +126,6 @@ libSU2Core_sources = ../src/definition_structure.cpp \
../src/output/CMultizoneOutput.cpp \
../src/output/COutputFactory.cpp \
../src/output/output_structure_legacy.cpp \
- ../src/output/COutputFactory.cpp \
../src/python_wrapper_structure.cpp \
../src/solvers/CAdjEulerSolver.cpp \
../src/solvers/CAdjNSSolver.cpp \
@@ -164,8 +163,6 @@ libSU2Core_sources = ../src/definition_structure.cpp \
../src/interfaces/fsi/CDisplacementsInterface.cpp \
../src/interfaces/fsi/CFlowTractionInterface.cpp \
../src/interfaces/fsi/CDiscAdjFlowTractionInterface.cpp \
- ../src/interfaces/fsi/CDisplacementsInterfaceLegacy.cpp \
- ../src/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.cpp \
../src/transport_model.cpp \
../src/variables/CFEABoundVariable.cpp \
../src/variables/CRadVariable.cpp \
diff --git a/SU2_CFD/src/SU2_CFD.cpp b/SU2_CFD/src/SU2_CFD.cpp
index 5b6875fd6d4b..9f25160e8fb2 100644
--- a/SU2_CFD/src/SU2_CFD.cpp
+++ b/SU2_CFD/src/SU2_CFD.cpp
@@ -25,7 +25,6 @@
* License along with SU2. If not, see .
*/
-
#include "../include/SU2_CFD.hpp"
/* LIBXSMM include files, if supported. */
@@ -101,7 +100,6 @@ int main(int argc, char *argv[]) {
CConfig* config = new CConfig(config_file_name, SU2_CFD);
unsigned short nZone = config->GetnZone();
- bool fsi = config->GetFSI_Simulation();
bool turbo = config->GetBoolTurbomachinery();
/*--- First, given the basic information about the number of zones and the
@@ -132,7 +130,7 @@ int main(int argc, char *argv[]) {
}
}
- else if (multizone && !turbo && !fsi) {
+ else if (multizone && !turbo) {
/*--- Generic multizone problems. ---*/
if (disc_adj) {
@@ -148,18 +146,6 @@ int main(int argc, char *argv[]) {
/*--- Harmonic balance problem: instantiate the Harmonic Balance driver class. ---*/
driver = new CHBDriver(config_file_name, nZone, MPICommunicator);
- }
- else if (fsi && disc_adj) {
-
- /*--- Discrete adjoint FSI problem with the legacy driver. ---*/
- if (config->GetTime_Domain())
- SU2_MPI::Error("There is no discrete adjoint implementation for dynamic FSI. ", CURRENT_FUNCTION);
-
- if (nZone != 2)
- SU2_MPI::Error("The legacy discrete adjoint FSI driver only works for two-zone problems. ", CURRENT_FUNCTION);
-
- driver = new CDiscAdjFSIDriver(config_file_name, nZone, MPICommunicator);
-
}
else if (turbo) {
diff --git a/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp b/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp
index f1c5395de08b..b5be9b5a904d 100644
--- a/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp
+++ b/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -288,7 +288,7 @@ void CDiscAdjMultizoneDriver::Run() {
for (unsigned short jZone = 0; jZone < nZone; jZone++) {
- if (jZone != iZone && interface_container[jZone][iZone] != NULL) {
+ if (jZone != iZone && interface_container[jZone][iZone] != nullptr) {
/*--- Extracting adjoints for solvers in jZone w.r.t. to the output of all solvers in iZone,
* that is, for the cases iZone != jZone we are evaluating cross derivatives between zones. ---*/
@@ -303,14 +303,10 @@ void CDiscAdjMultizoneDriver::Run() {
}
}
- /*--- Save Solution to Solution_BGS and compute residual from Solution_BGS and Solution_BGS_k. ---*/
+ /*--- Compute residual from Solution and Solution_BGS_k and update the latter. ---*/
SetResidual_BGS(iZone);
- /*--- Save Solution to Solution_BGS_k for a next outer iteration.
- * (Solution might be overwritten when entering another zone because of cross derivatives.) ---*/
-
- Set_BGSSolution(iZone);
}
/*--- Set the multizone output. ---*/
@@ -424,11 +420,8 @@ void CDiscAdjMultizoneDriver::SetRecording(unsigned short kind_recording, Kind_T
for(iZone = 0; iZone < nZone; iZone++) {
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != NULL) {
- if (solver->GetAdjoint()) {
- solver->SetRecording(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->SetRecording(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
}
}
@@ -792,12 +785,12 @@ void CDiscAdjMultizoneDriver::SetAdj_ObjFunction() {
unsigned long IterAvg_Obj = config_container[ZONE_0]->GetIter_Avg_Objective();
su2double seeding = 1.0;
- CWindowingTools windowEvaluator = CWindowingTools();
-
if (time_stepping){
if (TimeIter < IterAvg_Obj){
// Default behavior (in case no specific window is chosen) is to use Square-Windowing, i.e. the numerator equals 1.0
- seeding = windowEvaluator.GetWndWeight(config_container[ZONE_0]->GetKindWindow(),TimeIter, IterAvg_Obj-1)/ (static_cast(IterAvg_Obj));
+ auto windowEvaluator = CWindowingTools();
+ su2double weight = windowEvaluator.GetWndWeight(config_container[ZONE_0]->GetKindWindow(), TimeIter, IterAvg_Obj-1);
+ seeding = weight / IterAvg_Obj;
}
else{
seeding = 0.0;
@@ -844,7 +837,7 @@ void CDiscAdjMultizoneDriver::InitializeCrossTerms() {
for(unsigned short iZone = 0; iZone < nZone; iZone++) {
for (unsigned short jZone = 0; jZone < nZone; jZone++) {
- if (iZone != jZone || interface_container[jZone][iZone] != NULL) {
+ if (iZone != jZone || interface_container[jZone][iZone] != nullptr) {
/*--- If jZone contributes to iZone in the primal problem, then
* iZone contributes to jZone in the adjoint problem. ---*/
@@ -853,12 +846,10 @@ void CDiscAdjMultizoneDriver::InitializeCrossTerms() {
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
CSolver* solver = solver_container[jZone][INST_0][MESH_0][iSol];
- if (solver != NULL) {
- if (solver->GetAdjoint()) {
- unsigned long nPoint = geometry_container[jZone][INST_0][MESH_0]->GetnPoint();
- unsigned short nVar = solver->GetnVar();
- Cross_Terms[iZone][jZone][iSol].resize(nPoint,nVar) = 0.0;
- }
+ if (solver && solver->GetAdjoint()) {
+ unsigned long nPoint = geometry_container[jZone][INST_0][MESH_0]->GetnPoint();
+ unsigned short nVar = solver->GetnVar();
+ Cross_Terms[iZone][jZone][iSol].resize(nPoint,nVar) = 0.0;
}
}
}
@@ -878,7 +869,7 @@ void CDiscAdjMultizoneDriver::HandleDataTransfer() {
/*--- Transfer from all the remaining zones ---*/
for (unsigned short jZone = 0; jZone < nZone; jZone++){
/*--- The target zone is iZone ---*/
- if (jZone != iZone && interface_container[iZone][jZone] != NULL) {
+ if (jZone != iZone && interface_container[iZone][jZone] != nullptr) {
DeformMesh = DeformMesh || Transfer_Data(jZone, iZone);
}
}
@@ -893,11 +884,8 @@ void CDiscAdjMultizoneDriver::Add_Solution_To_External(unsigned short iZone) {
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->Add_Solution_To_External();
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->Add_Solution_To_External();
}
}
@@ -905,11 +893,8 @@ void CDiscAdjMultizoneDriver::Add_External_To_Solution(unsigned short iZone) {
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->Add_External_To_Solution();
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->Add_External_To_Solution();
}
}
@@ -917,23 +902,8 @@ void CDiscAdjMultizoneDriver::Update_Cross_Term(unsigned short iZone, unsigned s
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[jZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->Update_Cross_Term(config_container[jZone], Cross_Terms[iZone][jZone][iSol]);
- }
- }
- }
-}
-
-void CDiscAdjMultizoneDriver::Set_BGSSolution(unsigned short iZone) {
-
- for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
- auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->UpdateSolution_BGS(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->Update_Cross_Term(config_container[jZone], Cross_Terms[iZone][jZone][iSol]);
}
}
@@ -941,11 +911,8 @@ void CDiscAdjMultizoneDriver::Set_Solution_To_BGSSolution_k(unsigned short iZone
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->GetNodes()->Restore_BGSSolution_k();
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->GetNodes()->Restore_BGSSolution_k();
}
}
@@ -953,11 +920,8 @@ void CDiscAdjMultizoneDriver::Set_BGSSolution_k_To_Solution(unsigned short iZone
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->GetNodes()->Set_BGSSolution_k();
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->GetNodes()->Set_BGSSolution_k();
}
}
@@ -965,11 +929,7 @@ void CDiscAdjMultizoneDriver::SetResidual_BGS(unsigned short iZone) {
for (unsigned short iSol=0; iSol < MAX_SOLS; iSol++) {
auto solver = solver_container[iZone][INST_0][MESH_0][iSol];
- if (solver != nullptr) {
- if (solver->GetAdjoint()) {
- solver->ComputeResidual_Multizone(geometry_container[iZone][INST_0][MESH_0],
- config_container[iZone]);
- }
- }
+ if (solver && solver->GetAdjoint())
+ solver->ComputeResidual_Multizone(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
}
}
diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp
index 31bccb6c4764..0261c5f6774c 100644
--- a/SU2_CFD/src/drivers/CDriver.cpp
+++ b/SU2_CFD/src/drivers/CDriver.cpp
@@ -38,6 +38,9 @@
#include "../../include/output/COutputFactory.hpp"
#include "../../include/output/COutputLegacy.hpp"
+#include "../../../Common/include/interface_interpolation/CInterpolator.hpp"
+#include "../../../Common/include/interface_interpolation/CInterpolatorFactory.hpp"
+
#include "../../include/interfaces/cfd/CConservativeVarsInterface.hpp"
#include "../../include/interfaces/cfd/CMixingPlaneInterface.hpp"
#include "../../include/interfaces/cfd/CSlidingInterface.hpp"
@@ -45,8 +48,6 @@
#include "../../include/interfaces/fsi/CDisplacementsInterface.hpp"
#include "../../include/interfaces/fsi/CFlowTractionInterface.hpp"
#include "../../include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp"
-#include "../../include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp"
-#include "../../include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp"
#include "../../include/numerics/template.hpp"
#include "../../include/numerics/transition.hpp"
@@ -83,10 +84,9 @@
#endif
#include
-CDriver::CDriver(char* confFile,
- unsigned short val_nZone,
- SU2_Comm MPICommunicator, bool dummy_geo):config_file_name(confFile), StartTime(0.0), StopTime(0.0), UsedTime(0.0),
- TimeIter(0), nZone(val_nZone), StopCalc(false), fsi(false), fem_solver(false), dry_run(dummy_geo) {
+CDriver::CDriver(char* confFile, unsigned short val_nZone, SU2_Comm MPICommunicator, bool dummy_geo) :
+ config_file_name(confFile), StartTime(0.0), StopTime(0.0), UsedTime(0.0),
+ TimeIter(0), nZone(val_nZone), StopCalc(false), fsi(false), fem_solver(false), dry_run(dummy_geo) {
/*--- Initialize Medipack (must also be here so it is initialized from python) ---*/
#ifdef HAVE_MPI
@@ -95,8 +95,6 @@ CDriver::CDriver(char* confFile,
#endif
#endif
- unsigned short jZone;
-
SU2_MPI::SetComm(MPICommunicator);
rank = SU2_MPI::GetRank();
@@ -144,13 +142,8 @@ CDriver::CDriver(char* confFile,
/*--- Allocate transfer and interpolation container --- */
- interface_container[iZone] = new CInterface*[nZone];
- interpolator_container[iZone] = new CInterpolator*[nZone];
-
- for (jZone = 0; jZone < nZone; jZone++){
- interface_container[iZone][jZone] = NULL;
- interpolator_container[iZone][jZone] = NULL;
- }
+ interface_container[iZone] = new CInterface*[nZone] ();
+ interpolator_container[iZone] = new CInterpolator*[nZone] ();
for (iInst = 0; iInst < nInst[iZone]; iInst++){
@@ -207,7 +200,7 @@ CDriver::CDriver(char* confFile,
/*--- Dynamic mesh processing. ---*/
DynamicMesh_Preprocessing(config_container[iZone], geometry_container[iZone][iInst], solver_container[iZone][iInst],
- iteration_container[iZone][iInst], grid_movement[iZone][iInst], surface_movement[iZone]);
+ iteration_container[iZone][iInst], grid_movement[iZone][iInst], surface_movement[iZone]);
/*--- Static mesh processing. ---*/
StaticMesh_Preprocessing(config_container[iZone], geometry_container[iZone][iInst], surface_movement[iZone]);
@@ -249,15 +242,6 @@ CDriver::CDriver(char* confFile,
PythonInterface_Preprocessing(config_container, geometry_container, solver_container);
- /*--- Open the FSI convergence history file ---*/
-
-// if (fsi){
-// if (rank == MASTER_NODE) cout << endl <<"Opening FSI history file." << endl;
-// unsigned short ZONE_FLOW = 0, ZONE_STRUCT = 1;
-// output_container->SpecialOutput_FSI(&FSIHist_file, geometry_container, solver_container,
-// config_container, integration_container, 0,
-// ZONE_FLOW, ZONE_STRUCT, true);
-// }
/*--- Preprocessing time is reported now, but not included in the next compute portion. ---*/
@@ -2467,8 +2451,7 @@ void CDriver::DynamicMesh_Preprocessing(CConfig *config, CGeometry **geometry, C
flows on dynamic meshes, including rigid mesh transformations, dynamically
deforming meshes, and preprocessing of harmonic balance. ---*/
- if (!fem_solver && (config->GetGrid_Movement() ||
- (config->GetDirectDiff() == D_DESIGN)) && !config->GetSurface_Movement(FLUID_STRUCTURE_STATIC)) {
+ if (!fem_solver && (config->GetGrid_Movement() || (config->GetDirectDiff() == D_DESIGN))) {
if (rank == MASTER_NODE)
cout << "Setting dynamic mesh structure for zone "<< iZone + 1<<"." << endl;
grid_movement = new CVolumetricMovement(geometry[MESH_0], config);
@@ -2509,350 +2492,127 @@ void CDriver::DynamicMesh_Preprocessing(CConfig *config, CGeometry **geometry, C
geometry[MESH_0]->ComputeWall_Distance(config);
}
-
- if (config->GetSurface_Movement(FLUID_STRUCTURE_STATIC)){
- if (rank == MASTER_NODE)
- cout << "Setting moving mesh structure for FSI problems." << endl;
- /*--- Instantiate the container for the grid movement structure ---*/
- grid_movement = new CElasticityMovement(geometry[MESH_0], config);
- }
-
}
void CDriver::Interface_Preprocessing(CConfig **config, CSolver***** solver, CGeometry**** geometry,
- unsigned short** interface_types, CInterface ***&interface,
- CInterpolator ***&interpolation) {
-
- unsigned short donorZone, targetZone;
- unsigned short nVar, nVarTransfer;
-
- unsigned short nMarkerTarget, iMarkerTarget, nMarkerDonor, iMarkerDonor;
-
- /*--- Initialize some useful booleans ---*/
- bool fluid_donor, structural_donor, heat_donor;
- bool fluid_target, structural_target, heat_target;
-
- bool discrete_adjoint = config[ZONE_0]->GetDiscrete_Adjoint();
-
- int markDonor, markTarget, Donor_check, Target_check, iMarkerInt, nMarkerInt;
+ unsigned short** interface_types, CInterface ***interface,
+ CInterpolator ***interpolation) {
-#ifdef HAVE_MPI
- int *Buffer_Recv_mark = NULL, iRank, nProcessor = size;
-
- if (rank == MASTER_NODE)
- Buffer_Recv_mark = new int[nProcessor];
-#endif
+ /*--- Setup interpolation and transfer for all possible donor/target pairs. ---*/
- /*--- Coupling between zones ---*/
- // There's a limit here, the interface boundary must connect only 2 zones
+ for (auto target = 0u; target < nZone; target++) {
- /*--- Loops over all target and donor zones to find which ones are connected through
- *--- an interface boundary (fsi or sliding mesh) ---*/
- for (targetZone = 0; targetZone < nZone; targetZone++) {
+ for (auto donor = 0u; donor < nZone; donor++) {
- for (donorZone = 0; donorZone < nZone; donorZone++) {
-
- interface_types[donorZone][targetZone] = NO_TRANSFER;
+ /*--- Aliases to make code less verbose. ---*/
+ auto& interface_type = interface_types[donor][target];
- if ( donorZone == targetZone ) {
- interface_types[donorZone][targetZone] = ZONES_ARE_EQUAL;
- // We're processing the same zone, so skip the following
+ if (donor == target) {
+ interface_type = ZONES_ARE_EQUAL;
continue;
}
+ interface_type = NO_TRANSFER;
- nMarkerInt = (int) ( config[donorZone]->GetMarker_n_ZoneInterface() / 2 );
+ /*--- If there is a common interface setup the interpolation and transfer. ---*/
- /*--- Loops on Interface markers to find if the 2 zones are sharing the boundary and to
- *--- determine donor and target marker tag ---*/
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
+ if (!CInterpolator::CheckZonesInterface(config[donor], config[target])) {
+ interface_type = NO_COMMON_INTERFACE;
+ }
+ else {
+ /*--- Begin the creation of the communication pattern among zones. ---*/
- markDonor = -1;
- markTarget = -1;
+ if (rank == MASTER_NODE) cout << "From zone " << donor << " to zone " << target << ":" << endl;
- /*--- On the donor side ---*/
- nMarkerDonor = config[donorZone]->GetnMarker_All();
+ /*--- Setup the interpolation. ---*/
- for (iMarkerDonor = 0; iMarkerDonor < nMarkerDonor; iMarkerDonor++) {
+ interpolation[donor][target] = CInterpolatorFactory::createInterpolator(geometry, config, donor, target);
- /*--- If the tag GetMarker_All_ZoneInterface(iMarker) equals the index we are looping at ---*/
- if ( config[donorZone]->GetMarker_All_ZoneInterface(iMarkerDonor) == iMarkerInt ) {
- /*--- We have identified the identifier for the interface marker ---*/
- markDonor = iMarkerDonor;
+ /*--- The type of variables transferred depends on the donor/target physics. ---*/
- break;
- }
- }
+ const bool heat_target = config[target]->GetHeatProblem();
+ const bool fluid_target = config[target]->GetFluidProblem();
+ const bool structural_target = config[target]->GetStructuralProblem();
- /*--- On the target side ---*/
- nMarkerTarget = config[targetZone]->GetnMarker_All();
+ const bool heat_donor = config[donor]->GetHeatProblem();
+ const bool fluid_donor = config[donor]->GetFluidProblem();
+ const bool structural_donor = config[donor]->GetStructuralProblem();
- for (iMarkerTarget = 0; iMarkerTarget < nMarkerTarget; iMarkerTarget++) {
+ /*--- Initialize the appropriate transfer strategy. ---*/
- /*--- If the tag GetMarker_All_ZoneInterface(iMarker) equals the index we are looping at ---*/
- if ( config[targetZone]->GetMarker_All_ZoneInterface(iMarkerTarget) == iMarkerInt ) {
- /*--- We have identified the identifier for the interface marker ---*/
- markTarget = iMarkerTarget;
+ if (rank == MASTER_NODE) cout << " Transferring ";
- break;
+ if (fluid_donor && structural_target) {
+ interface_type = FLOW_TRACTION;
+ auto nConst = 2;
+ bool conservative = config[target]->GetConservativeInterpolation();
+ if(!config[ZONE_0]->GetDiscrete_Adjoint()) {
+ interface[donor][target] = new CFlowTractionInterface(nDim, nConst, config[donor], conservative);
+ } else {
+ interface[donor][target] = new CDiscAdjFlowTractionInterface(nDim, nConst, config[donor], conservative);
}
+ if (rank == MASTER_NODE) cout << "fluid " << (conservative? "forces." : "tractions.") << endl;
}
-
-#ifdef HAVE_MPI
-
- Donor_check = -1;
- Target_check = -1;
-
- /*--- We gather a vector in MASTER_NODE that determines if the boundary is not on the processor because
- * of the partition or because the zone does not include it ---*/
-
- SU2_MPI::Gather(&markDonor , 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE) {
- for (iRank = 0; iRank < nProcessor; iRank++) {
- if( Buffer_Recv_mark[iRank] != -1 ) {
- Donor_check = Buffer_Recv_mark[iRank];
- break;
+ else if (structural_donor && fluid_target) {
+ if (solver_container[target][INST_0][MESH_0][MESH_SOL] == nullptr) {
+ SU2_MPI::Error("Mesh deformation was not correctly specified for the fluid zone.\n"
+ "Use DEFORM_MESH=YES, and setup MARKER_DEFORM_MESH=(...)", CURRENT_FUNCTION);
}
+ interface_type = BOUNDARY_DISPLACEMENTS;
+ interface[donor][target] = new CDisplacementsInterface(nDim, 0, config[donor]);
+ if (rank == MASTER_NODE) cout << "boundary displacements from the structural solver." << endl;
}
- }
-
- SU2_MPI::Bcast(&Donor_check , 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- SU2_MPI::Gather(&markTarget, 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE){
- for (iRank = 0; iRank < nProcessor; iRank++){
- if( Buffer_Recv_mark[iRank] != -1 ){
- Target_check = Buffer_Recv_mark[iRank];
- break;
- }
+ else if (fluid_donor && fluid_target) {
+ interface_type = SLIDING_INTERFACE;
+ auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnPrimVar();
+ interface[donor][target] = new CSlidingInterface(nVar, 0, config[donor]);
+ if (rank == MASTER_NODE) cout << "sliding interface." << endl;
}
- }
-
- SU2_MPI::Bcast(&Target_check, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
-#else
- Donor_check = markDonor;
- Target_check = markTarget;
-#endif
-
- /* --- Check ifzones are actually sharing the interface boundary, if not skip ---*/
- if(Target_check == -1 || Donor_check == -1) {
- interface_types[donorZone][targetZone] = NO_COMMON_INTERFACE;
- continue;
- }
-
- /*--- Set some boolean to properly allocate data structure later ---*/
- fluid_target = false;
- structural_target = false;
-
- fluid_donor = false;
- structural_donor = false;
-
- heat_donor = false;
- heat_target = false;
-
- switch ( config[targetZone]->GetKind_Solver() ) {
-
- case EULER : case NAVIER_STOKES: case RANS:
- case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS:
- case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS:
- case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
- fluid_target = true;
- break;
-
- case FEM_ELASTICITY: case DISC_ADJ_FEM:
- structural_target = true;
- break;
-
- case HEAT_EQUATION: case DISC_ADJ_HEAT:
- heat_target = true;
- break;
- }
-
- switch ( config[donorZone]->GetKind_Solver() ) {
-
- case EULER : case NAVIER_STOKES: case RANS:
- case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS:
- case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS:
- case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
- fluid_donor = true;
- break;
+ else if (heat_donor || heat_target) {
+ if (heat_donor && heat_target)
+ SU2_MPI::Error("Conjugate heat transfer between solids is not implemented.", CURRENT_FUNCTION);
- case FEM_ELASTICITY: case DISC_ADJ_FEM:
- structural_donor = true;
- break;
-
- case HEAT_EQUATION : case DISC_ADJ_HEAT:
- heat_donor = true;
- break;
- }
-
- /*--- Begin the creation of the communication pattern among zones ---*/
-
- /*--- Retrieve the number of conservative variables (for problems not involving structural analysis ---*/
- if (fluid_donor && fluid_target)
- nVar = solver[donorZone][INST_0][MESH_0][FLOW_SOL]->GetnVar();
- else
- /*--- If at least one of the components is structural ---*/
- nVar = nDim;
-
- if (rank == MASTER_NODE) cout << "From zone " << donorZone << " to zone " << targetZone << ": ";
-
- /*--- Match Zones ---*/
- if (rank == MASTER_NODE) cout << "Setting coupling ";
-
- bool conservative_interp = config[donorZone]->GetConservativeInterpolation();
-
- /*--- Conditions for conservative interpolation are not met, we cannot fallback on the consistent approach
- because CFlowTractionInterface relies on the information in config to be correct. ---*/
- if ( conservative_interp && targetZone == 0 && structural_target )
- SU2_MPI::Error("Conservative interpolation assumes the structural model mesh is evaluated second, "
- "somehow this has not happened.",CURRENT_FUNCTION);
-
- switch (config[donorZone]->GetKindInterpolation()) {
-
- case NEAREST_NEIGHBOR:
- if ( conservative_interp && targetZone > 0 && structural_target ) {
- interpolation[donorZone][targetZone] = new CMirror(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using a mirror approach: matching coefficients "
- "from opposite mesh." << endl;
- }
- else {
- interpolation[donorZone][targetZone] = new CNearestNeighbor(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using a nearest-neighbor approach." << endl;
- }
- break;
-
- case ISOPARAMETRIC:
- if ( conservative_interp && targetZone > 0 && structural_target ) {
- interpolation[donorZone][targetZone] = new CMirror(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using a mirror approach: matching coefficients "
- "from opposite mesh." << endl;
- }
- else {
- interpolation[donorZone][targetZone] = new CIsoparametric(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using an isoparametric approach." << endl;
- }
- break;
+ const auto fluidZone = heat_target? donor : target;
- case WEIGHTED_AVERAGE:
- interpolation[donorZone][targetZone] = new CSlidingMesh(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using an sliding mesh approach." << endl;
-
- break;
+ if (config[fluidZone]->GetEnergy_Equation() || (config[fluidZone]->GetKind_Regime() == COMPRESSIBLE))
+ interface_type = heat_target? CONJUGATE_HEAT_FS : CONJUGATE_HEAT_SF;
+ else if (config[fluidZone]->GetWeakly_Coupled_Heat())
+ interface_type = heat_target? CONJUGATE_HEAT_WEAKLY_FS : CONJUGATE_HEAT_WEAKLY_SF;
+ else
+ interface_type = NO_TRANSFER;
- case RADIAL_BASIS_FUNCTION:
- if ( conservative_interp && targetZone > 0 && structural_target ) {
- interpolation[donorZone][targetZone] = new CMirror(geometry, config, donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using a mirror approach: matching coefficients "
- "from opposite mesh." << endl;
- }
- else {
- interpolation[donorZone][targetZone] = new CRadialBasisFunction(geometry, config,
- donorZone, targetZone);
- if (rank == MASTER_NODE) cout << "using a radial basis function approach." << endl;
+ if (interface_type != NO_TRANSFER) {
+ auto nVar = 4;
+ interface[donor][target] = new CConjugateHeatInterface(nVar, 0, config[donor]);
+ if (rank == MASTER_NODE) cout << "conjugate heat variables." << endl;
}
- break;
- }
-
- /*--- Initialize the appropriate transfer strategy ---*/
- if (rank == MASTER_NODE) cout << "Transferring ";
-
- if (fluid_donor && structural_target) {
- interface_types[donorZone][targetZone] = FLOW_TRACTION;
- nVarTransfer = 2;
- if(!discrete_adjoint) {
- interface[donorZone][targetZone] = new CFlowTractionInterface(nVar, nVarTransfer, config[donorZone]);
- } else {
- interface[donorZone][targetZone] = new CDiscAdjFlowTractionInterface(nVar, nVarTransfer, config[donorZone]);
- }
- if (rank == MASTER_NODE) cout << "flow tractions. " << endl;
- }
- else if (structural_donor && fluid_target) {
- /*--- If we are using the new mesh solver, we transfer the total boundary displacements (not incremental) --*/
- if (solver_container[targetZone][INST_0][MESH_0][MESH_SOL] != NULL) {
- interface_types[donorZone][targetZone] = BOUNDARY_DISPLACEMENTS;
- nVarTransfer = 0;
- interface[donorZone][targetZone] = new CDisplacementsInterface(nVar, nVarTransfer, config[donorZone]);
- if (rank == MASTER_NODE) cout << "boundary displacements from the structural solver. " << endl;
}
- /*--- We keep the legacy method temporarily until FSI-adjoint has been adapted ---*/
- /// TODO: LEGACY CLEANUP remove the "else" part and every class and enum referenced there,
- /// add a check above to make sure MESH_SOL has been instantiated.
else {
- nVarTransfer = 0;
- if(!discrete_adjoint) {
- interface_types[donorZone][targetZone] = STRUCTURAL_DISPLACEMENTS_LEGACY;
- interface[donorZone][targetZone] = new CDisplacementsInterfaceLegacy(nVar, nVarTransfer, config[donorZone]);
- } else {
- interface_types[donorZone][targetZone] = STRUCTURAL_DISPLACEMENTS_DISC_ADJ;
- interface[donorZone][targetZone] = new CDiscAdjDisplacementsInterfaceLegacy(nVar, nVarTransfer, config[donorZone]);
- }
- if (rank == MASTER_NODE) cout << "structural displacements (legacy). " << endl;
+ if (solver[donor][INST_0][MESH_0][FLOW_SOL] == nullptr)
+ SU2_MPI::Error("Could not determine the number of variables for transfer.", CURRENT_FUNCTION);
+
+ auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnVar();
+ interface_type = CONSERVATIVE_VARIABLES;
+ interface[donor][target] = new CConservativeVarsInterface(nVar, 0, config[donor]);
+ if (rank == MASTER_NODE) cout << "generic conservative variables." << endl;
}
}
- else if (fluid_donor && fluid_target) {
- interface_types[donorZone][targetZone] = SLIDING_INTERFACE;
- nVarTransfer = 0;
- nVar = solver[donorZone][INST_0][MESH_0][FLOW_SOL]->GetnPrimVar();
- interface[donorZone][targetZone] = new CSlidingInterface(nVar, nVarTransfer, config[donorZone]);
- if (rank == MASTER_NODE) cout << "sliding interface. " << endl;
- }
- else if (fluid_donor && heat_target) {
- nVarTransfer = 0;
- nVar = 4;
- if(config[donorZone]->GetEnergy_Equation() || (config[donorZone]->GetKind_Regime() == COMPRESSIBLE))
- interface_types[donorZone][targetZone] = CONJUGATE_HEAT_FS;
- else if (config[donorZone]->GetWeakly_Coupled_Heat())
- interface_types[donorZone][targetZone] = CONJUGATE_HEAT_WEAKLY_FS;
- else { }
- interface[donorZone][targetZone] = new CConjugateHeatInterface(nVar, nVarTransfer, config[donorZone]);
- if (rank == MASTER_NODE) cout << "conjugate heat variables. " << endl;
- }
- else if (heat_donor && fluid_target) {
- nVarTransfer = 0;
- nVar = 4;
- if(config[targetZone]->GetEnergy_Equation() || (config[targetZone]->GetKind_Regime() == COMPRESSIBLE))
- interface_types[donorZone][targetZone] = CONJUGATE_HEAT_SF;
- else if (config[targetZone]->GetWeakly_Coupled_Heat())
- interface_types[donorZone][targetZone] = CONJUGATE_HEAT_WEAKLY_SF;
- else { }
- interface[donorZone][targetZone] = new CConjugateHeatInterface(nVar, nVarTransfer, config[donorZone]);
- if (rank == MASTER_NODE) cout << "conjugate heat variables. " << endl;
- }
- else if (heat_donor && heat_target) {
- SU2_MPI::Error("Conjugate heat transfer between solids not implemented yet.", CURRENT_FUNCTION);
- }
- else {
- interface_types[donorZone][targetZone] = CONSERVATIVE_VARIABLES;
- nVarTransfer = 0;
- interface[donorZone][targetZone] = new CConservativeVarsInterface(nVar, nVarTransfer, config[donorZone]);
- if (rank == MASTER_NODE) cout << "generic conservative variables. " << endl;
- }
-
- break;
- }
+ /*--- Mixing plane for turbo machinery applications. ---*/
- if (config[donorZone]->GetBoolMixingPlaneInterface()){
- interface_types[donorZone][targetZone] = MIXING_PLANE;
- nVarTransfer = 0;
- nVar = solver[donorZone][INST_0][MESH_0][FLOW_SOL]->GetnVar();
- interface[donorZone][targetZone] = new CMixingPlaneInterface(nVar, nVarTransfer,
- config[donorZone], config[targetZone]);
- if (rank == MASTER_NODE) cout << "Set mixing-plane interface from donor zone "<< donorZone
- << " to target zone " << targetZone <<"."<GetBoolMixingPlaneInterface()) {
+ interface_type = MIXING_PLANE;
+ auto nVar = solver[donor][INST_0][MESH_0][FLOW_SOL]->GetnVar();
+ interface[donor][target] = new CMixingPlaneInterface(nVar, 0, config[donor], config[target]);
+ if (rank == MASTER_NODE) {
+ cout << "Set mixing-plane interface from donor zone "
+ << donor << " to target zone " << target << "." << endl;
+ }
}
}
}
-#ifdef HAVE_MPI
- if (rank == MASTER_NODE)
- delete [] Buffer_Recv_mark;
-#endif
}
void CDriver::StaticMesh_Preprocessing(CConfig *config, CGeometry** geometry, CSurfaceMovement* surface_movement){
@@ -2908,7 +2668,7 @@ void CDriver::StaticMesh_Preprocessing(CConfig *config, CGeometry** geometry, CS
break;
}
- if ((config->GetnMarker_Moving() > 0) && !config->GetSurface_Movement(FLUID_STRUCTURE_STATIC)) {
+ if (config->GetnMarker_Moving() > 0) {
/*--- Fixed wall velocities: set the grid velocities only one time
before the first iteration flow solver. ---*/
@@ -3122,11 +2882,9 @@ void CDriver::Turbomachinery_Preprocessing(CConfig** config, CGeometry**** geome
}
-
-
-
CDriver::~CDriver(void) {}
+
CFluidDriver::CFluidDriver(char* confFile, unsigned short val_nZone, SU2_Comm MPICommunicator) : CDriver(confFile, val_nZone, MPICommunicator, false) {
Max_Iter = config_container[ZONE_0]->GetnInner_Iter();
}
@@ -3261,7 +3019,7 @@ void CFluidDriver::Run() {
for (iZone = 0; iZone < nZone; iZone++) {
for (jZone = 0; jZone < nZone; jZone++)
if(jZone != iZone && interpolator_container[iZone][jZone] != NULL)
- interpolator_container[iZone][jZone]->Set_TransferCoeff(config_container);
+ interpolator_container[iZone][jZone]->SetTransferCoeff(config_container);
}
}
@@ -4224,1547 +3982,3 @@ void CHBDriver::ComputeHB_Operator() {
delete [] Omega_HB;
}
-
-CDiscAdjFSIDriver::CDiscAdjFSIDriver(char* confFile,
- unsigned short val_nZone,
- SU2_Comm MPICommunicator) : CDriver(confFile,
- val_nZone,
- MPICommunicator,
- false) {
-
- unsigned short iVar;
- unsigned short nVar_Flow = 0, nVar_Struct = 0;
- RecordingState = 0;
- CurrentRecording = 0;
-
- switch (config_container[ZONE_0]->GetKind_ObjFunc()){
- case DRAG_COEFFICIENT:
- case LIFT_COEFFICIENT:
- case SIDEFORCE_COEFFICIENT:
- case EFFICIENCY:
- case MOMENT_X_COEFFICIENT:
- case MOMENT_Y_COEFFICIENT:
- case MOMENT_Z_COEFFICIENT:
- case EQUIVALENT_AREA:
- Kind_Objective_Function = FLOW_OBJECTIVE_FUNCTION;
- break;
- case REFERENCE_GEOMETRY:
- case REFERENCE_NODE:
- case VOLUME_FRACTION:
- case TOPOL_DISCRETENESS:
- case TOPOL_COMPLIANCE:
- Kind_Objective_Function = FEM_OBJECTIVE_FUNCTION;
- break;
- default:
- Kind_Objective_Function = NO_OBJECTIVE_FUNCTION;
- break;
- }
-
- direct_iteration = new CIteration*[nZone];
-
- unsigned short iZone;
- for (iZone = 0; iZone < nZone; iZone++){
- switch (config_container[iZone]->GetKind_Solver()) {
- case DISC_ADJ_INC_RANS: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES:
- case DISC_ADJ_RANS: case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES:
- direct_iteration[iZone] = new CFluidIteration(config_container[iZone]);
- nVar_Flow = solver_container[iZone][INST_0][MESH_0][ADJFLOW_SOL]->GetnVar();
- flow_criteria = -8.0; // Temporarily hard coded until adapted into new structure
- flow_criteria_rel = 3.0;
- break;
- case DISC_ADJ_FEM:
- direct_iteration[iZone] = new CFEAIteration(config_container[iZone]);
- nVar_Struct = solver_container[iZone][INST_0][MESH_0][ADJFEA_SOL]->GetnVar();
- structure_criteria = -8.0;
- structure_criteria_rel = 3.0;
- break;
- }
- }
-
- init_res_flow = new su2double[nVar_Flow];
- init_res_struct = new su2double[nVar_Struct];
-
- residual_flow = new su2double[nVar_Flow];
- residual_struct = new su2double[nVar_Struct];
-
- residual_flow_rel = new su2double[nVar_Flow];
- residual_struct_rel = new su2double[nVar_Struct];
-
- for (iVar = 0; iVar < nVar_Flow; iVar++){
- init_res_flow[iVar] = 0.0;
- residual_flow[iVar] = 0.0;
- residual_flow_rel[iVar] = 0.0;
- }
- for (iVar = 0; iVar < nVar_Struct; iVar++){
- init_res_struct[iVar] = 0.0;
- residual_struct[iVar] = 0.0;
- residual_struct_rel[iVar] = 0.0;
- }
-
-
- bool write_history = true;
-
- /*--- Header of the temporary output file ---*/
- if ((write_history) && (rank == MASTER_NODE)){
- ofstream myfile_res;
- myfile_res.open ("history_adjoint_FSI.csv");
-
- myfile_res << "BGS_Iter\t";
-
- for (iVar = 0; iVar < nVar_Flow; iVar++){
- myfile_res << "ResFlow[" << iVar << "]\t";
- }
-
- for (iVar = 0; iVar < nVar_Struct; iVar++){
- myfile_res << "ResFEA[" << iVar << "]\t";
- }
-
-
- bool de_effects = config_container[ZONE_0]->GetDE_Effects();
- for (iVar = 0; iVar < config_container[ZONE_0]->GetnElasticityMod(); iVar++)
- myfile_res << "Sens_E_" << iVar << "\t";
-
- for (iVar = 0; iVar < config_container[ZONE_0]->GetnPoissonRatio(); iVar++)
- myfile_res << "Sens_Nu_" << iVar << "\t";
-
- if (de_effects){
- for (iVar = 0; iVar < config_container[ZONE_0]->GetnElectric_Field(); iVar++)
- myfile_res << "Sens_EField_" << iVar << "\t";
- }
-
- myfile_res << endl;
-
- myfile_res.close();
- }
-
- // TEST: for implementation of python framework in standalone structural problems
- if ((config_container[ZONE_1]->GetDV_FEA() != NODV_FEA) && (rank == MASTER_NODE)){
-
- /*--- Header of the temporary output file ---*/
- ofstream myfile_res;
-
- switch (config_container[ZONE_1]->GetDV_FEA()) {
- case YOUNG_MODULUS:
- myfile_res.open("grad_young.opt");
- break;
- case POISSON_RATIO:
- myfile_res.open("grad_poisson.opt");
- break;
- case DENSITY_VAL:
- case DEAD_WEIGHT:
- myfile_res.open("grad_density.opt");
- break;
- case ELECTRIC_FIELD:
- myfile_res.open("grad_efield.opt");
- break;
- default:
- myfile_res.open("grad.opt");
- break;
- }
-
- unsigned short iDV;
- unsigned short nDV = solver_container[ZONE_1][INST_0][MESH_0][ADJFEA_SOL]->GetnDVFEA();
-
- myfile_res << "INDEX" << "\t" << "GRAD" << endl;
-
- myfile_res.precision(15);
-
- for (iDV = 0; iDV < nDV; iDV++){
- myfile_res << iDV;
- myfile_res << "\t";
- myfile_res << scientific << solver_container[ZONE_1][INST_0][MESH_0][ADJFEA_SOL]->GetGlobal_Sens_DVFEA(iDV);
- myfile_res << endl;
- }
-
- myfile_res.close();
- }
- output_legacy = new COutputLegacy(config_container[ZONE_0]);
-
- /*--- TODO: This is a workaround until the TestCases.py script incorporates new classes for nested loops. ---*/
-// config_container[ZONE_0]->SetnExtIter(1);
-// config_container[ZONE_1]->SetnExtIter(1);
- ConvHist_file = NULL;
- ConvHist_file = new ofstream*[nZone];
- for (iZone = 0; iZone < nZone; iZone++) {
- ConvHist_file[iZone] = NULL;
- if (rank == MASTER_NODE){
- ConvHist_file[iZone] = new ofstream[nInst[iZone]];
- for (iInst = 0; iInst < nInst[iZone]; iInst++) {
- output_legacy->SetConvHistory_Header(&ConvHist_file[iZone][iInst], config_container[iZone], iZone, iInst);
- config_container[iZone]->SetHistFile(&ConvHist_file[iZone][INST_0]);
- }
- }
- }
-}
-
-CDiscAdjFSIDriver::~CDiscAdjFSIDriver(void) {
-
- delete [] direct_iteration;
- delete [] init_res_flow;
- delete [] init_res_struct;
- delete [] residual_flow;
- delete [] residual_struct;
- delete [] residual_flow_rel;
- delete [] residual_struct_rel;
-
-}
-
-void CDiscAdjFSIDriver::DynamicMeshUpdate(unsigned long ExtIter){
-
-}
-
-void CDiscAdjFSIDriver::Run( ) {
-
- /*--- As of now, we are coding it for just 2 zones. ---*/
- /*--- This will become more general, but we need to modify the configuration for that ---*/
- unsigned short ZONE_FLOW = 0, ZONE_STRUCT = 1;
- unsigned short iZone;
- bool BGS_Converged = false;
-
- unsigned long IntIter = 0; for (iZone = 0; iZone < nZone; iZone++) config_container[iZone]->SetInnerIter(IntIter);
- unsigned long iOuterIter = 0; for (iZone = 0; iZone < nZone; iZone++) config_container[iZone]->SetOuterIter(iOuterIter);
- unsigned long nOuterIter = driver_config->GetnOuter_Iter();
-
- ofstream myfile_struc, myfile_flow, myfile_geo;
-
- Preprocess(ZONE_FLOW, ZONE_STRUCT, ALL_VARIABLES);
-
- for (iOuterIter = 0; iOuterIter < nOuterIter && !BGS_Converged; iOuterIter++){
-
- if (rank == MASTER_NODE){
- cout << endl << " ****** BGS ITERATION ";
- cout << iOuterIter;
- cout << " ******" << endl;
- }
-
- for (iZone = 0; iZone < nZone; iZone++) config_container[iZone]->SetOuterIter(iOuterIter);
-
- /*--- Start with structural terms if OF is based on displacements ---*/
-
- if (Kind_Objective_Function == FEM_OBJECTIVE_FUNCTION)
- Iterate_Block(ZONE_FLOW, ZONE_STRUCT, FEA_DISP_VARS);
-
- /*--- Iterate fluid (including cross term) ---*/
-
- Iterate_Block(ZONE_FLOW, ZONE_STRUCT, FLOW_CONS_VARS);
-
- /*--- Compute mesh (it is a cross term dF / dMv ) ---*/
-
- Iterate_Block(ZONE_FLOW, ZONE_STRUCT, MESH_COORDS);
-
- /*--- Compute mesh cross term (dM / dSv) ---*/
-
- Iterate_Block(ZONE_FLOW, ZONE_STRUCT, FEM_CROSS_TERM_GEOMETRY);
-
- /*--- End with structural terms if OF is based on fluid variables ---*/
-
- if (Kind_Objective_Function == FLOW_OBJECTIVE_FUNCTION)
- Iterate_Block(ZONE_FLOW, ZONE_STRUCT, FEA_DISP_VARS);
-
- /*--- Check convergence of the BGS method ---*/
- BGS_Converged = BGSConvergence(iOuterIter, ZONE_FLOW, ZONE_STRUCT);
-
- }
-
- output_container[ZONE_FLOW]->SetResult_Files(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW], solver_container[ZONE_FLOW][INST_0][MESH_0], 0, true);
-
- output_container[ZONE_STRUCT]->SetResult_Files(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT], solver_container[ZONE_STRUCT][INST_0][MESH_0], 0, true);
-
-}
-
-
-void CDiscAdjFSIDriver::Preprocess(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned long IntIter = 0, iPoint;
- config_container[ZONE_0]->SetInnerIter(IntIter);
- unsigned short ExtIter = config_container[ZONE_FLOW]->GetTimeIter();
-
- bool dual_time_1st = (config_container[ZONE_FLOW]->GetTime_Marching() == DT_STEPPING_1ST);
- bool dual_time_2nd = (config_container[ZONE_FLOW]->GetTime_Marching() == DT_STEPPING_2ND);
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool dual_time = (dual_time_1st || dual_time_2nd);
- unsigned short iMesh;
- int Direct_Iter_Flow;
- bool update_geo = false;
-
- /*----------------------------------------------------------------------------*/
- /*------------------------------ FLOW SOLUTION -------------------------------*/
- /*----------------------------------------------------------------------------*/
-
- /*--- For the unsteady adjoint, load direct solutions from restart files. ---*/
-
- if (config_container[ZONE_FLOW]->GetTime_Marching()) {
-
- Direct_Iter_Flow = SU2_TYPE::Int(config_container[ZONE_FLOW]->GetUnst_AdjointIter()) - SU2_TYPE::Int(ExtIter) - 2;
-
- /*--- For dual-time stepping we want to load the already converged solution at timestep n ---*/
-
- if (dual_time) {
- Direct_Iter_Flow += 1;
- }
-
- if (ExtIter == 0){
-
- if (dual_time_2nd) {
-
- /*--- Load solution at timestep n-2 ---*/
-
- iteration_container[ZONE_FLOW][INST_0]->LoadUnsteady_Solution(geometry_container, solver_container,config_container, ZONE_FLOW, INST_0, Direct_Iter_Flow-2);
-
- /*--- Push solution back to correct array ---*/
-
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n();
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1();
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n();
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1();
- }
- }
- }
- if (dual_time) {
-
- /*--- Load solution at timestep n-1 ---*/
-
- iteration_container[ZONE_FLOW][INST_0]->LoadUnsteady_Solution(geometry_container, solver_container,config_container, ZONE_FLOW, INST_0, Direct_Iter_Flow-1);
-
- /*--- Push solution back to correct array ---*/
-
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n();
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n();
- }
- }
- }
-
- /*--- Load solution timestep n ---*/
-
- iteration_container[ZONE_FLOW][INST_0]->LoadUnsteady_Solution(geometry_container, solver_container,config_container, ZONE_FLOW, INST_0, Direct_Iter_Flow);
-
- }
-
-
- if ((ExtIter > 0) && dual_time){
-
- /*--- Load solution timestep n - 2 ---*/
-
- iteration_container[ZONE_FLOW][INST_0]->LoadUnsteady_Solution(geometry_container, solver_container,config_container, ZONE_FLOW, INST_0, Direct_Iter_Flow - 2);
-
- /*--- Temporarily store the loaded solution in the Solution_Old array ---*/
-
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_OldSolution();
- if (turbulent){
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_OldSolution();
- }
- }
-
- /*--- Set Solution at timestep n to solution at n-1 ---*/
-
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- for(iPoint=0; iPointGetnPoint();iPoint++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->SetSolution(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint));
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->SetSolution(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->GetSolution_time_n(iPoint));
- }
- }
- }
- if (dual_time_1st){
- /*--- Set Solution at timestep n-1 to the previously loaded solution ---*/
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- for(iPoint=0; iPointGetnPoint();iPoint++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
- }
- }
- }
- }
- if (dual_time_2nd){
- /*--- Set Solution at timestep n-1 to solution at n-2 ---*/
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- for(iPoint=0; iPointGetnPoint();iPoint++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->GetSolution_time_n1(iPoint));
- }
- }
- }
- /*--- Set Solution at timestep n-2 to the previously loaded solution ---*/
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- for(iPoint=0; iPointGetnPoint();iPoint++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->GetSolution_Old(iPoint));
- if (turbulent) {
- solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][TURB_SOL]->GetNodes()->GetSolution_Old(iPoint));
- }
- }
- }
- }
- }
- }
- else{
-
- /*--- Load the restart (we need to use the routine in order to get the GEOMETRY, otherwise it's restarted from the base mesh ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->LoadRestart(geometry_container[ZONE_FLOW][INST_0], solver_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW], 0, true);
-
- if (ExtIter == 0 || dual_time) {
-
- for (iMesh=0; iMesh<=config_container[ZONE_FLOW]->GetnMGLevels();iMesh++) {
- for (iPoint = 0; iPoint < geometry_container[ZONE_FLOW][INST_0][iMesh]->GetnPoint(); iPoint++) {
- solver_container[ZONE_FLOW][INST_0][iMesh][ADJFLOW_SOL]->GetNodes()->SetSolution_Direct(iPoint, solver_container[ZONE_FLOW][INST_0][iMesh][FLOW_SOL]->GetNodes()->GetSolution(iPoint));
- }
- }
- if (turbulent && !config_container[ZONE_FLOW]->GetFrozen_Visc_Disc()) {
- for (iPoint = 0; iPoint < geometry_container[ZONE_FLOW][INST_0][MESH_0]->GetnPoint(); iPoint++) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->GetNodes()->SetSolution_Direct(iPoint, solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->GetNodes()->GetSolution(iPoint));
- }
- }
- }
-
- /*--- Store geometry of the converged solution also in the adjoint solver in order to be able to reset it later ---*/
-
- for (iPoint = 0; iPoint < geometry_container[ZONE_FLOW][INST_0][MESH_0]->GetnPoint(); iPoint++){
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetNodes()->SetGeometry_Direct(iPoint, geometry_container[ZONE_FLOW][INST_0][MESH_0]->node[iPoint]->GetCoord());
- }
-
- }
-
- /*----------------------------------------------------------------------------*/
- /*-------------------------- STRUCTURAL SOLUTION -----------------------------*/
- /*----------------------------------------------------------------------------*/
-
- IntIter = 0;
- config_container[ZONE_STRUCT]->SetInnerIter(IntIter);
- ExtIter = config_container[ZONE_STRUCT]->GetTimeIter();
- bool dynamic = (config_container[ZONE_STRUCT]->GetTime_Domain());
-
- int Direct_Iter_FEA;
-
- /*--- For the dynamic adjoint, load direct solutions from restart files. ---*/
-
- if (dynamic) {
-
- Direct_Iter_FEA = SU2_TYPE::Int(config_container[ZONE_STRUCT]->GetUnst_AdjointIter()) - SU2_TYPE::Int(ExtIter) - 1;
-
- /*--- We want to load the already converged solution at timesteps n and n-1 ---*/
-
- /*--- Load solution at timestep n-1 ---*/
-
- iteration_container[ZONE_STRUCT][INST_0]->LoadDynamic_Solution(geometry_container, solver_container,config_container, ZONE_STRUCT, INST_0, Direct_Iter_FEA-1);
-
- /*--- Push solution back to correct array ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->Set_Solution_time_n();
-
- /*--- Push solution back to correct array ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->SetSolution_Accel_time_n();
-
- /*--- Push solution back to correct array ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->SetSolution_Vel_time_n();
-
- /*--- Load solution timestep n ---*/
-
- iteration_container[ZONE_STRUCT][INST_0]->LoadDynamic_Solution(geometry_container, solver_container,config_container, ZONE_STRUCT, INST_0, Direct_Iter_FEA);
-
- /*--- Store FEA solution also in the adjoint solver in order to be able to reset it later ---*/
-
- for (iPoint = 0; iPoint < geometry_container[ZONE_STRUCT][INST_0][MESH_0]->GetnPoint(); iPoint++){
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetNodes()->SetSolution_Direct(iPoint, solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->GetSolution(iPoint));
- }
-
- for (iPoint = 0; iPoint < geometry_container[ZONE_STRUCT][INST_0][MESH_0]->GetnPoint(); iPoint++){
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetNodes()->SetSolution_Accel_Direct(iPoint, solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->GetSolution_Accel(iPoint));
- }
-
- for (iPoint = 0; iPoint < geometry_container[ZONE_STRUCT][INST_0][MESH_0]->GetnPoint(); iPoint++){
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetNodes()->SetSolution_Vel_Direct(iPoint, solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->GetSolution_Vel(iPoint));
- }
-
- }
- else {
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->LoadRestart(geometry_container[ZONE_STRUCT][INST_0], solver_container[ZONE_STRUCT][INST_0], config_container[ZONE_STRUCT], 0, update_geo);
-
- /*--- Store FEA solution also in the adjoint solver in order to be able to reset it later ---*/
-
- for (iPoint = 0; iPoint < geometry_container[ZONE_STRUCT][INST_0][MESH_0]->GetnPoint(); iPoint++){
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetNodes()->SetSolution_Direct(iPoint, solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetNodes()->GetSolution(iPoint));
- }
-
- }
-
- /*----------------------------------------------------------------------------*/
- /*--------------------- ADJOINT SOLVER PREPROCESSING -------------------------*/
- /*----------------------------------------------------------------------------*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->Preprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0], solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW] , MESH_0, 0, RUNTIME_ADJFLOW_SYS, false);
-
- if (turbulent){
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->Preprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0], solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW] , MESH_0, 0, RUNTIME_ADJTURB_SYS, false);
- }
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->Preprocessing(geometry_container[ZONE_STRUCT][INST_0][MESH_0], solver_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT] , MESH_0, 0, RUNTIME_ADJFEA_SYS, false);
-
-
-
-}
-
-void CDiscAdjFSIDriver::PrintDirect_Residuals(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned short ExtIter = config_container[ZONE_FLOW]->GetTimeIter();
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool nonlinear_analysis = (config_container[ZONE_STRUCT]->GetGeometricConditions() == LARGE_DEFORMATIONS); // Nonlinear analysis.
- bool unsteady = config_container[ZONE_FLOW]->GetTime_Marching() != NONE;
- bool dynamic = (config_container[ZONE_STRUCT]->GetTime_Domain());
-
- su2double val_OFunction = 0.0;
- string kind_OFunction;
-
- cout.precision(6);
- cout.setf(ios::scientific, ios::floatfield);
-
- if ((kind_recording == FLOW_CONS_VARS) || (kind_recording == MESH_COORDS)) {
-
- /*--- Print residuals in the first iteration ---*/
-
- if (rank == MASTER_NODE && ((ExtIter == 0) || unsteady )){
- cout << "log10[RMS Density]: "<< log10(solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetRes_RMS(0))
- <<", Drag: " <GetTotal_CD()
- <<", Lift: " << solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL() << "." << endl;
-
- if (turbulent){
- cout << "log10[RMS k]: " << log10(solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->GetRes_RMS(0)) << endl;
- }
- if (Kind_Objective_Function == FLOW_OBJECTIVE_FUNCTION){
- switch (config_container[ZONE_FLOW]->GetKind_ObjFunc()){
- case DRAG_COEFFICIENT:
- kind_OFunction = "(Drag coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD();
- break;
- case LIFT_COEFFICIENT:
- kind_OFunction = "(Lift coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL();
- break;
- case SIDEFORCE_COEFFICIENT:
- kind_OFunction = "(Sideforce coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CSF();
- break;
- case EFFICIENCY:
- kind_OFunction = "(Efficiency): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CEff();
- break;
- case MOMENT_X_COEFFICIENT:
- kind_OFunction = "(Moment X coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMx();
- break;
- case MOMENT_Y_COEFFICIENT:
- kind_OFunction = "(Moment Y coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMy();
- break;
- case MOMENT_Z_COEFFICIENT:
- kind_OFunction = "(Moment Z coefficient): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMz();
- break;
- case EQUIVALENT_AREA:
- kind_OFunction = "(Equivalent area): ";
- val_OFunction = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CEquivArea();
- break;
- default:
- val_OFunction = 0.0; // If the objective function is computed in a different physical problem
- break;
- }
- cout << "Objective function " << kind_OFunction << val_OFunction << endl;
- }
- }
-
- }
-
- if ((kind_recording == FEA_DISP_VARS) || (kind_recording == FLOW_CROSS_TERM) || (kind_recording == GEOMETRY_CROSS_TERM)) {
-
- if (rank == MASTER_NODE && ((ExtIter == 0) || dynamic )){
- if (nonlinear_analysis){
- cout << "UTOL-A: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_FEM(0))
- << ", RTOL-A: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_FEM(1))
- << ", ETOL-A: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_FEM(2)) << "." << endl;
- }
- else{
- if (solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetnVar() == 2){
- cout << "log10[RMS Ux]: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_RMS(0))
- << ", log10[RMS Uy]: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_RMS(1)) << "." << endl;
-
- }
- else{
- cout << "log10[RMS Ux]: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_RMS(0))
- << ", log10[RMS Uy]: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_RMS(1))
- << ", log10[RMS Uz]: " << log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_RMS(2))<< "." << endl;
- }
-
- }
- if (Kind_Objective_Function == FEM_OBJECTIVE_FUNCTION){
- switch (config_container[ZONE_STRUCT]->GetKind_ObjFunc()){
- case REFERENCE_GEOMETRY:
- kind_OFunction = "(Reference Geometry): ";
- val_OFunction = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefGeom();
- break;
- case REFERENCE_NODE:
- kind_OFunction = "(Reference Node): ";
- val_OFunction = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefNode();
- break;
- case VOLUME_FRACTION:
- kind_OFunction = "(Volume Fraction): ";
- val_OFunction = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFVolFrac();
- break;
- case TOPOL_DISCRETENESS:
- kind_OFunction = "(Topology discreteness): ";
- val_OFunction = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFVolFrac();
- break;
- case TOPOL_COMPLIANCE:
- kind_OFunction = "(Topology compliance): ";
- val_OFunction = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFCompliance();
- break;
- default:
- val_OFunction = 0.0; // If the objective function is computed in a different physical problem
- break;
- }
- cout << "Objective function " << kind_OFunction << val_OFunction << endl;
- }
- }
-
- }
-
-}
-
-void CDiscAdjFSIDriver::Iterate_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, unsigned short kind_recording){
-
- if ((kind_recording == FLOW_CONS_VARS) ||
- (kind_recording == MESH_COORDS)) {
-
- Fluid_Iteration_Direct(ZONE_FLOW, ZONE_STRUCT);
-
-
- }
-
- if ((kind_recording == FEA_DISP_VARS) ||
- (kind_recording == FLOW_CROSS_TERM) ||
- (kind_recording == GEOMETRY_CROSS_TERM)) {
-
- Structural_Iteration_Direct(ZONE_FLOW, ZONE_STRUCT);
-
- }
-
-
- if (kind_recording == FEM_CROSS_TERM_GEOMETRY) {
-
- Mesh_Deformation_Direct(ZONE_FLOW, ZONE_STRUCT);
-
- }
-
-
-}
-
-void CDiscAdjFSIDriver::Fluid_Iteration_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT) {
-
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool frozen_visc = config_container[ZONE_FLOW]->GetFrozen_Visc_Disc();
-
- /*-----------------------------------------------------------------*/
- /*------------------- Set Dependency on Geometry ------------------*/
- /*-----------------------------------------------------------------*/
-
- geometry_container[ZONE_FLOW][INST_0][MESH_0]->UpdateGeometry(geometry_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->Preprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0],solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
-
- if (turbulent && !frozen_visc) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->Postprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0], solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], MESH_0);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION_EDDY);
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION_EDDY);
-
- }
-
- /*-----------------------------------------------------------------*/
- /*----------------- Iterate the flow solver -----------------------*/
- /*---- Sets all the cross dependencies for the flow variables -----*/
- /*-----------------------------------------------------------------*/
-
- config_container[ZONE_FLOW]->SetInnerIter(0);
-
- direct_iteration[ZONE_FLOW]->Iterate(output_container[ZONE_FLOW], integration_container, geometry_container,
- solver_container, numerics_container, config_container,
- surface_movement, grid_movement, FFDBox, ZONE_FLOW, INST_0);
-
- /*-----------------------------------------------------------------*/
- /*--------------------- Set MPI Solution --------------------------*/
- /*-----------------------------------------------------------------*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
-
-}
-
-void CDiscAdjFSIDriver::Structural_Iteration_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT) {
-
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool frozen_visc = config_container[ZONE_FLOW]->GetFrozen_Visc_Disc();
-
- /*-----------------------------------------------------------------*/
- /*---------- Set Dependencies on Geometry and Flow ----------------*/
- /*-----------------------------------------------------------------*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
-
- geometry_container[ZONE_FLOW][INST_0][MESH_0]->UpdateGeometry(geometry_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->Preprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0],solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
-
- if (turbulent && !frozen_visc) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->Postprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0], solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], MESH_0);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION_EDDY);
- solver_container[ZONE_FLOW][INST_0][MESH_0][TURB_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION_EDDY);
-
- }
-
- /*-----------------------------------------------------------------*/
- /*-------------------- Transfer Tractions -------------------------*/
- /*-----------------------------------------------------------------*/
-
- Transfer_Tractions(ZONE_FLOW, ZONE_STRUCT);
-
- /*-----------------------------------------------------------------*/
- /*--------------- Iterate the structural solver -------------------*/
- /*-----------------------------------------------------------------*/
-
- direct_iteration[ZONE_STRUCT]->Iterate(output_container[ZONE_STRUCT], integration_container, geometry_container,
- solver_container, numerics_container, config_container,
- surface_movement, grid_movement, FFDBox, ZONE_STRUCT, INST_0);
-
- /*-----------------------------------------------------------------*/
- /*--------------------- Set MPI Solution --------------------------*/
- /*-----------------------------------------------------------------*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
-
-}
-
-void CDiscAdjFSIDriver::Mesh_Deformation_Direct(unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT) {
-
- unsigned long ExtIter = config_container[ZONE_STRUCT]->GetTimeIter();
-
- /*-----------------------------------------------------------------*/
- /*--------------------- Set MPI Solution --------------------------*/
- /*-----------------------------------------------------------------*/
-
- geometry_container[ZONE_FLOW][INST_0][MESH_0]->UpdateGeometry(geometry_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->InitiateComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->CompleteComms(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], SOLUTION);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->Preprocessing(geometry_container[ZONE_FLOW][INST_0][MESH_0],solver_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW], MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
-
- /*-----------------------------------------------------------------*/
- /*------------------- Transfer Displacements ----------------------*/
- /*-----------------------------------------------------------------*/
-
- Transfer_Displacements(ZONE_STRUCT, ZONE_FLOW);
-
- /*-----------------------------------------------------------------*/
- /*------------------- Set the Grid movement -----------------------*/
- /*---- No longer done in the preprocess of the flow iteration -----*/
- /*---- as the flag Grid_Movement is set to false in this case -----*/
- /*-----------------------------------------------------------------*/
-
- direct_iteration[ZONE_FLOW]->SetGrid_Movement(geometry_container[ZONE_FLOW][INST_0],
- surface_movement[ZONE_FLOW], grid_movement[ZONE_FLOW][INST_0],
- solver_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW], 0, ExtIter );
-
- geometry_container[ZONE_FLOW][INST_0][MESH_0]->UpdateGeometry(geometry_container[ZONE_FLOW][INST_0], config_container[ZONE_FLOW]);
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT], SOLUTION_FEA);
-
-}
-
-void CDiscAdjFSIDriver::SetRecording(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned long IntIter = config_container[ZONE_0]->GetInnerIter();
- bool unsteady = (config_container[ZONE_FLOW]->GetTime_Marching() != NONE);
- bool dynamic = (config_container[ZONE_STRUCT]->GetTime_Domain());
-
- string kind_DirectIteration = " ";
- string kind_AdjointIteration = " ";
-
- if (unsteady || dynamic){
- SU2_MPI::Error("DYNAMIC ADJOINT SOLVER NOT IMPLEMENTED FOR FSI APPLICATIONS", CURRENT_FUNCTION);
- }
-
-
- if (rank == MASTER_NODE){
- cout << endl;
- switch (kind_recording){
- case FLOW_CONS_VARS:
- kind_AdjointIteration = "Flow iteration: flow input -> flow output";
- kind_DirectIteration = "flow ";
- break;
- case MESH_COORDS:
- kind_AdjointIteration = "Geometry cross term from flow: geometry input -> flow output";
- kind_DirectIteration = "flow ";
- break;
- case FEA_DISP_VARS:
- kind_AdjointIteration = "Structural iteration: structural input -> structural output";
- kind_DirectIteration = "structural ";
- break;
- case FLOW_CROSS_TERM:
- kind_AdjointIteration = "Flow cross term: flow input -> structural output";
- kind_DirectIteration = "structural ";
- break;
- case GEOMETRY_CROSS_TERM:
- kind_AdjointIteration = "Geometry cross term from structure: geometry input -> structural output";
- kind_DirectIteration = "structural ";
- break;
- case FEM_CROSS_TERM_GEOMETRY:
- kind_AdjointIteration = "Structural cross term from geometry: structural input -> geometry output";
- kind_DirectIteration = "mesh deformation ";
- break;
- }
- cout << kind_AdjointIteration << endl;
- cout << "Direct " << kind_DirectIteration << "iteration to store computational graph." << endl;
- switch (kind_recording){
- case FLOW_CONS_VARS: case MESH_COORDS:
- case FEA_DISP_VARS: case FLOW_CROSS_TERM: case GEOMETRY_CROSS_TERM:
- cout << "Compute residuals to check the convergence of the direct problem." << endl; break;
- case FEM_CROSS_TERM_GEOMETRY:
- cout << "Deform the grid using the converged solution of the direct problem." << endl; break;
- }
- }
-
-
- AD::Reset();
-
- if (CurrentRecording != kind_recording && (CurrentRecording != NONE) ){
-
- /*--- Clear indices ---*/
-
- PrepareRecording(ZONE_FLOW, ZONE_STRUCT, ALL_VARIABLES);
-
- /*--- Clear indices of coupling variables ---*/
-
- SetDependencies(ZONE_FLOW, ZONE_STRUCT, ALL_VARIABLES);
-
- /*--- Run one iteration while tape is passive - this clears all indices ---*/
- Iterate_Direct(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- }
-
- /*--- Prepare for recording ---*/
-
- PrepareRecording(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Start the recording of all operations ---*/
-
- AD::StartRecording();
-
- /*--- Register input variables ---*/
-
- RegisterInput(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Set dependencies for flow, geometry and structural solvers ---*/
-
- SetDependencies(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Run a direct iteration ---*/
- Iterate_Direct(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Register objective function and output variables ---*/
-
- RegisterOutput(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Stop the recording ---*/
- AD::StopRecording();
-
- /*--- Set the recording status ---*/
-
- CurrentRecording = kind_recording;
-
- /* --- Reset the number of the internal iterations---*/
-
- config_container[ZONE_0]->SetInnerIter(IntIter);
-
-
-}
-
-void CDiscAdjFSIDriver::PrepareRecording(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned short iMesh;
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
-
- /*--- Set fluid variables to direct solver values ---*/
- for (iMesh = 0; iMesh <= config_container[ZONE_FLOW]->GetnMGLevels(); iMesh++){
- solver_container[ZONE_FLOW][INST_0][iMesh][ADJFLOW_SOL]->SetRecording(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW]);
- }
- if (turbulent){
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->SetRecording(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW]);
- }
-
- /*--- Set geometry to the converged values ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->SetMesh_Recording(geometry_container[ZONE_FLOW][INST_0], grid_movement[ZONE_FLOW][INST_0], config_container[ZONE_FLOW]);
-
- /*--- Set structural variables to direct solver values ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->SetRecording(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT]);
-
-}
-
-void CDiscAdjFSIDriver::RegisterInput(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- /*--- Register flow variables ---*/
- if (kind_recording == FLOW_CONS_VARS) {
- iteration_container[ZONE_FLOW][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_FLOW, INST_0, kind_recording);
- }
-
- /*--- Register geometry variables ---*/
- if (kind_recording == MESH_COORDS) {
- iteration_container[ZONE_FLOW][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_FLOW, INST_0, kind_recording);
- }
-
- /*--- Register structural variables ---*/
- if (kind_recording == FEM_CROSS_TERM_GEOMETRY) {
- iteration_container[ZONE_STRUCT][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_STRUCT, INST_0, kind_recording);
- }
-
- /*--- Register all variables ---*/
- if (kind_recording == FEA_DISP_VARS) {
- iteration_container[ZONE_STRUCT][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_STRUCT, INST_0, FEA_DISP_VARS);
- iteration_container[ZONE_FLOW][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_FLOW, INST_0, FLOW_CROSS_TERM);
- iteration_container[ZONE_FLOW][INST_0]->RegisterInput(solver_container, geometry_container, config_container, ZONE_FLOW, INST_0, GEOMETRY_CROSS_TERM);
- }
-
-}
-
-void CDiscAdjFSIDriver::SetDependencies(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- /*--- Add dependencies for geometrical and turbulent variables ---*/
-
- iteration_container[ZONE_FLOW][INST_0]->SetDependencies(solver_container, geometry_container, numerics_container, config_container, ZONE_FLOW, INST_0, kind_recording);
-
- /*--- Add dependencies for E, Nu, Rho, and Rho_DL variables ---*/
-
- iteration_container[ZONE_STRUCT][INST_0]->SetDependencies(solver_container, geometry_container, numerics_container, config_container, ZONE_STRUCT, INST_0, kind_recording);
-
-
-}
-
-void CDiscAdjFSIDriver::RegisterOutput(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool frozen_visc = config_container[ZONE_FLOW]->GetFrozen_Visc_Disc();
-
-
- /*--- Register a flow-type objective function and the conservative variables of the flow as output of the iteration. ---*/
- if ((kind_recording == FLOW_CONS_VARS) ||
- (kind_recording == MESH_COORDS)) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->RegisterObj_Func(config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->RegisterOutput(geometry_container[ZONE_FLOW][INST_0][MESH_0],config_container[ZONE_FLOW]);
-
- if (turbulent && !frozen_visc) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->RegisterOutput(geometry_container[ZONE_FLOW][INST_0][MESH_0],config_container[ZONE_FLOW]);
- }
- }
-
-
- /*--- Register a structural-type objective function and the displacements of the structure as output of the iteration. ---*/
- if (kind_recording == FEA_DISP_VARS) {
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->RegisterObj_Func(config_container[ZONE_STRUCT]);
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->RegisterOutput(geometry_container[ZONE_STRUCT][INST_0][MESH_0],config_container[ZONE_STRUCT]);
- }
-
-
- /*--- The FEM_CROSS_TERM_GEOMETRY evaluates the mesh routines, they do not throw any dependency on the objective function. ---*/
- /*--- Register the displacements of the fluid nodes as output of the iteration. ---*/
- if (kind_recording == FEM_CROSS_TERM_GEOMETRY) {
- geometry_container[ZONE_FLOW][INST_0][MESH_0]->RegisterOutput_Coordinates(config_container[ZONE_FLOW]);
- }
-
-}
-
-
-void CDiscAdjFSIDriver::Iterate_Block(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned long IntIter=0, nIntIter = 1;
- bool dual_time_1st = (config_container[ZONE_0]->GetTime_Marching() == DT_STEPPING_1ST);
- bool dual_time_2nd = (config_container[ZONE_0]->GetTime_Marching() == DT_STEPPING_2ND);
- bool dual_time = (dual_time_1st || dual_time_2nd);
- bool dynamic = (config_container[ZONE_STRUCT]->GetTime_Domain());
-
- bool adjoint_convergence = false;
-
- /*--- Record one direct iteration with kind_recording as input ---*/
-
- SetRecording(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Print the residuals of the direct subiteration ---*/
-
- PrintDirect_Residuals(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Run the iteration ---*/
-
- switch (kind_recording){
- case FLOW_CONS_VARS:
- nIntIter = config_container[ZONE_FLOW]->GetnInner_Iter();
- break;
- case FEA_DISP_VARS:
- nIntIter = config_container[ZONE_STRUCT]->GetnInner_Iter();
- break;
- case MESH_COORDS:
- case FEM_CROSS_TERM_GEOMETRY:
- case FLOW_CROSS_TERM:
- case GEOMETRY_CROSS_TERM:
- nIntIter = 1;
- break;
- }
-
- for (unsigned short iZone = 0; iZone < config_container[ZONE_FLOW]->GetnZone(); iZone++)
- config_container[iZone]->SetInnerIter(IntIter);
-
- for(IntIter = 0; IntIter < nIntIter; IntIter++){
-
- /*--- Set the internal iteration ---*/
-
- for (unsigned short iZone = 0; iZone < config_container[ZONE_FLOW]->GetnZone(); iZone++)
- config_container[iZone]->SetInnerIter(IntIter);
-
- /*--- Set the adjoint values of the flow and objective function ---*/
-
- InitializeAdjoint(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Run the adjoint computation ---*/
-
- AD::ComputeAdjoint();
-
- /*--- Extract the adjoints of the input variables and store them for the next iteration ---*/
-
- ExtractAdjoint(ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Clear all adjoints to re-use the stored computational graph in the next iteration ---*/
- AD::ClearAdjoints();
-
- /*--- Check the convergence of the adjoint block ---*/
-
- adjoint_convergence = CheckConvergence(IntIter, ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Write the convergence history (only screen output) ---*/
-
- ConvergenceHistory(IntIter, nIntIter, ZONE_FLOW, ZONE_STRUCT, kind_recording);
-
- /*--- Break the loop if converged ---*/
-
- if (adjoint_convergence) break;
-
-
- }
-
- if (dual_time){
- integration_container[ZONE_FLOW][INST_0][ADJFLOW_SOL]->SetConvergence(false);
- }
- if (dynamic){
- integration_container[ZONE_FLOW][INST_0][ADJFLOW_SOL]->SetConvergence(false);
- }
-
-}
-
-
-void CDiscAdjFSIDriver::InitializeAdjoint(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool frozen_visc = config_container[ZONE_FLOW]->GetFrozen_Visc_Disc();
-
- /*--- Seed a fluid-type objective function and initialize the adjoints of fluid conservative variables. ---*/
- if ((kind_recording == FLOW_CONS_VARS) ||
- (kind_recording == MESH_COORDS)) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->SetAdj_ObjFunc(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->SetAdjoint_Output(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
- if (turbulent && !frozen_visc) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->SetAdjoint_Output(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
- }
- }
-
- /*--- Seed a structural-type objective function and initialize the adjoints of structural displacements. ---*/
- if (kind_recording == FEA_DISP_VARS) {
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->SetAdj_ObjFunc(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->SetAdjoint_Output(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
- }
-
- /*--- Initialize the adjoints of fluid grid nodes. ---*/
- if (kind_recording == FEM_CROSS_TERM_GEOMETRY) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->SetAdjoint_OutputMesh(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
- }
-}
-
-void CDiscAdjFSIDriver::ExtractAdjoint(unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- bool turbulent = (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS) ||
- (config_container[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_INC_RANS);
- bool frozen_visc = config_container[ZONE_FLOW]->GetFrozen_Visc_Disc();
-
- /*--- Extract the adjoint of the fluid conservative variables ---*/
-
- if (kind_recording == FLOW_CONS_VARS) {
-
- /*--- Extract the adjoints of the conservative input variables and store them for the next iteration ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ExtractAdjoint_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ExtractAdjoint_Variables(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- if (turbulent && !frozen_visc) {
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->ExtractAdjoint_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
- }
-
- }
-
- /*--- Extract the adjoint of the mesh coordinates ---*/
-
- if (kind_recording == MESH_COORDS) {
-
- /*--- Extract the adjoints of the flow geometry and store them for the next iteration ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ExtractAdjoint_CrossTerm_Geometry_Flow(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- }
-
- /*--- Extract the adjoint of the structural displacements ---*/
-
- if (kind_recording == FEA_DISP_VARS) {
-
- /*--- Extract the adjoints of the conservative input variables and store them for the next iteration ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->ExtractAdjoint_Solution(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->ExtractAdjoint_Variables(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ExtractAdjoint_CrossTerm(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- if (turbulent && !frozen_visc)
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJTURB_SOL]->ExtractAdjoint_CrossTerm(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ExtractAdjoint_CrossTerm_Geometry(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
- }
-
-
- if (kind_recording == FEM_CROSS_TERM_GEOMETRY) {
-
- /*--- Extract the adjoints of the displacements (input variables) and store them for the next iteration ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->ExtractAdjoint_CrossTerm_Geometry(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
- }
-
-}
-
-
-bool CDiscAdjFSIDriver::CheckConvergence(unsigned long IntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- bool flow_convergence = false,
- struct_convergence = false,
- adjoint_convergence = false;
-
-// su2double residual_1, residual_2;
-
-// if (kind_recording == FLOW_CONS_VARS) {
-
-// /*--- Set the convergence criteria (only residual possible as of now) ---*/
-
-// residual_1 = log10(solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_RMS(0));
-// residual_2 = log10(solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_RMS(1));
-
-// flow_convergence = ((residual_1 < config_container[ZONE_FLOW]->GetMinLogResidual()) &&
-// (residual_2 < config_container[ZONE_FLOW]->GetMinLogResidual()));
-
-// }
-
-// if (kind_recording == FEA_DISP_VARS) {
-
-// /*--- Set the convergence criteria (only residual possible as of now) ---*/
-
-// residual_1 = log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_RMS(0));
-// residual_2 = log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_RMS(1));
-
-// // Temporary, until function is added
-// struct_convergence = ((residual_1 < config_container[ZONE_STRUCT]->GetResidual_FEM_UTOL()) &&
-// (residual_2 < config_container[ZONE_STRUCT]->GetResidual_FEM_UTOL()));
-
-// }
-
- switch (kind_recording){
- case FLOW_CONS_VARS: adjoint_convergence = flow_convergence; break;
- case MESH_COORDS: adjoint_convergence = true; break;
- case FEA_DISP_VARS: adjoint_convergence = struct_convergence; break;
- case FLOW_CROSS_TERM: adjoint_convergence = true; break;
- case FEM_CROSS_TERM_GEOMETRY: adjoint_convergence = true; break;
- case GEOMETRY_CROSS_TERM: adjoint_convergence = true; break;
- default: adjoint_convergence = false; break;
- }
-
- /*--- Apply the same convergence criteria to all the processors ---*/
-
-#ifdef HAVE_MPI
-
- unsigned short *sbuf_conv = NULL, *rbuf_conv = NULL;
- sbuf_conv = new unsigned short[1]; sbuf_conv[0] = 0;
- rbuf_conv = new unsigned short[1]; rbuf_conv[0] = 0;
-
- /*--- Convergence criteria ---*/
-
- sbuf_conv[0] = adjoint_convergence;
- SU2_MPI::Reduce(sbuf_conv, rbuf_conv, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
-
- /*-- Compute global convergence criteria in the master node --*/
-
- sbuf_conv[0] = 0;
- if (rank == MASTER_NODE) {
- if (rbuf_conv[0] == size) sbuf_conv[0] = 1;
- else sbuf_conv[0] = 0;
- }
-
- SU2_MPI::Bcast(sbuf_conv, 1, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (sbuf_conv[0] == 1) { adjoint_convergence = true;}
- else { adjoint_convergence = false;}
-
- delete [] sbuf_conv;
- delete [] rbuf_conv;
-
-#endif
-
- return adjoint_convergence;
-
-}
-
-void CDiscAdjFSIDriver::ConvergenceHistory(unsigned long IntIter,
- unsigned long nIntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT,
- unsigned short kind_recording){
-
- unsigned long BGS_Iter = config_container[ZONE_FLOW]->GetOuterIter();
-
-
- if (rank == MASTER_NODE)
- output_legacy->SetConvHistory_Header(&ConvHist_file[ZONE_0][INST_0], config_container[ZONE_0], ZONE_0, INST_0);
-
- if (kind_recording == FLOW_CONS_VARS) {
-
- if (rank == MASTER_NODE){
- if (IntIter == 0){
- cout << endl;
- cout << " IntIter" << " BGSIter" << " Res[Psi_Rho]" << " Res[Psi_E]" << endl;
- }
-
- if (IntIter % config_container[ZONE_FLOW]->GetWrt_Con_Freq() == 0){
- /*--- Output the flow convergence ---*/
- /*--- This is temporary as it requires several changes in the output structure ---*/
- unsigned short nVar_Flow = solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetnVar();
- cout.width(8); cout << IntIter;
- cout.width(11); cout << BGS_Iter + 1;
- cout.precision(6); cout.setf(ios::fixed, ios::floatfield);
- cout.width(15); cout << log10(solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_RMS(0));
- cout.width(15); cout << log10(solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_RMS(nVar_Flow-1));
- cout << endl;
- }
-
- }
- }
-
- if (kind_recording == FEA_DISP_VARS) {
- /*--- Set the convergence criteria (only residual possible) ---*/
- output_legacy->SetConvHistory_Body(NULL, geometry_container, solver_container, config_container, integration_container, true, 0.0, ZONE_STRUCT, INST_0);
-
- }
-
-
-}
-
-
-bool CDiscAdjFSIDriver::BGSConvergence(unsigned long IntIter,
- unsigned short ZONE_FLOW,
- unsigned short ZONE_STRUCT){
-
- unsigned short nVar_Flow = solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetnVar(),
- nVar_Struct = solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetnVar();
- unsigned short iRes;
-
- bool flow_converged_absolute = false,
- flow_converged_relative = false,
- struct_converged_absolute = false,
- struct_converged_relative = false;
-
- bool Convergence = false;
-
- /*--- Compute the residual for the flow and structural zones ---*/
-
- /*--- Flow ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->ComputeResidual_Multizone(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- /*--- Structure ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->ComputeResidual_Multizone(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
-
-
- /*--- Retrieve residuals ---*/
-
- /*--- Flow residuals ---*/
-
- for (iRes = 0; iRes < nVar_Flow; iRes++){
- residual_flow[iRes] = log10(solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_BGS(iRes));
- if (IntIter == 0) init_res_flow[iRes] = residual_flow[iRes];
- residual_flow_rel[iRes] = fabs(residual_flow[iRes] - init_res_flow[iRes]);
- }
-
- /*--- Structure residuals ---*/
-
- for (iRes = 0; iRes < nVar_Struct; iRes++){
- residual_struct[iRes] = log10(solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_BGS(iRes));
- if (IntIter == 0) init_res_struct[iRes] = residual_struct[iRes];
- residual_struct_rel[iRes] = fabs(residual_struct[iRes] - init_res_struct[iRes]);
- }
-
- /*--- Check convergence ---*/
- flow_converged_absolute = ((residual_flow[0] < flow_criteria) && (residual_flow[nVar_Flow-1] < flow_criteria));
- flow_converged_relative = ((residual_flow_rel[0] > flow_criteria_rel) && (residual_flow_rel[nVar_Flow-1] > flow_criteria_rel));
-
- struct_converged_absolute = ((residual_struct[0] < structure_criteria) && (residual_struct[nVar_Flow-1] < structure_criteria));
- struct_converged_relative = ((residual_struct_rel[0] > structure_criteria_rel) && (residual_struct_rel[nVar_Flow-1] > structure_criteria_rel));
-
- Convergence = ((flow_converged_absolute && struct_converged_absolute) ||
- (flow_converged_absolute && struct_converged_relative) ||
- (flow_converged_relative && struct_converged_relative) ||
- (flow_converged_relative && struct_converged_absolute));
-
- if (rank == MASTER_NODE){
-
- cout << "\n-------------------------------------------------------------------------\n\n";
- cout << "Convergence summary for BGS iteration " << IntIter << "\n\n";
- /*--- TODO: This is a workaround until the TestCases.py script incorporates new classes for nested loops. ---*/
- cout << "Iter[ID]" << " BGSRes[Psi_Rho]" << " BGSRes[Psi_E]" << " BGSRes[Psi_Ux]" << " BGSRes[Psi_Uy]\n";
- cout.precision(6); cout.setf(ios::fixed, ios::floatfield);
- cout << "|"; cout.width(8); cout << IntIter*1000;
- cout << "|"; cout.width(17); cout << residual_flow[0];
- cout << "|"; cout.width(15); cout << residual_flow[nVar_Flow-1];
- cout << "|"; cout.width(16); cout << residual_struct[0];
- cout << "|"; cout.width(16); cout << residual_struct[1];
- cout << "|"; cout << "\n\n-------------------------------------------------------------------------" << endl;
-
-
- bool write_history = true;
- unsigned short iVar;
-
- /*--- Header of the temporary output file ---*/
- if ((write_history) && (rank == MASTER_NODE)){
- ofstream myfile_res;
- bool de_effects = config_container[ZONE_STRUCT]->GetDE_Effects();
-
- myfile_res.open ("history_adjoint_FSI.csv", ios::app);
-
- myfile_res << IntIter << "\t";
-
- myfile_res.precision(15);
-
- for (iVar = 0; iVar < nVar_Flow; iVar++){
- myfile_res << fixed << residual_flow[iVar] << "\t";
- }
-
- for (iVar = 0; iVar < nVar_Struct; iVar++){
- myfile_res << fixed << residual_struct[iVar] << "\t";
- }
-
- for (iVar = 0; iVar < config_container[ZONE_STRUCT]->GetnElasticityMod(); iVar++)
- myfile_res << scientific << solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetGlobal_Sens_E(iVar) << "\t";
- for (iVar = 0; iVar < config_container[ZONE_STRUCT]->GetnPoissonRatio(); iVar++)
- myfile_res << scientific << solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetGlobal_Sens_Nu(iVar) << "\t";
- if (de_effects){
- for (iVar = 0; iVar < config_container[ZONE_STRUCT]->GetnElectric_Field(); iVar++)
- myfile_res << scientific << solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetGlobal_Sens_EField(0) << "\t";
- }
-
- myfile_res << endl;
-
- myfile_res.close();
- }
-
- // TEST: for implementation of python framework in coupled FSI problems
- if ((config_container[ZONE_1]->GetDV_FEA() != NODV_FEA) && (rank == MASTER_NODE)){
-
- /*--- Header of the temporary output file ---*/
- ofstream myfile_res;
-
- switch (config_container[ZONE_1]->GetDV_FEA()) {
- case YOUNG_MODULUS:
- myfile_res.open("grad_young.opt");
- break;
- case POISSON_RATIO:
- myfile_res.open("grad_poisson.opt");
- break;
- case DENSITY_VAL:
- case DEAD_WEIGHT:
- myfile_res.open("grad_density.opt");
- break;
- case ELECTRIC_FIELD:
- myfile_res.open("grad_efield.opt");
- break;
- default:
- myfile_res.open("grad.opt");
- break;
- }
-
- unsigned short iDV;
- unsigned short nDV = solver_container[ZONE_1][INST_0][MESH_0][ADJFEA_SOL]->GetnDVFEA();
-
- myfile_res << "INDEX" << "\t" << "GRAD" << endl;
-
- myfile_res.precision(15);
-
- for (iDV = 0; iDV < nDV; iDV++){
- myfile_res << iDV;
- myfile_res << "\t";
- myfile_res << scientific << solver_container[ZONE_1][INST_0][MESH_0][ADJFEA_SOL]->GetGlobal_Sens_DVFEA(iDV);
- myfile_res << endl;
- }
-
- myfile_res.close();
- }
-
-
- }
-
- /*--- Apply the same convergence criteria to all the processors ---*/
-
-#ifdef HAVE_MPI
-
- unsigned short *sbuf_conv = NULL, *rbuf_conv = NULL;
- sbuf_conv = new unsigned short[1]; sbuf_conv[0] = 0;
- rbuf_conv = new unsigned short[1]; rbuf_conv[0] = 0;
-
- /*--- Convergence criteria ---*/
-
- sbuf_conv[0] = Convergence;
- SU2_MPI::Reduce(sbuf_conv, rbuf_conv, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
-
- /*-- Compute global convergence criteria in the master node --*/
-
- sbuf_conv[0] = 0;
- if (rank == MASTER_NODE) {
- if (rbuf_conv[0] == size) sbuf_conv[0] = 1;
- else sbuf_conv[0] = 0;
- }
-
- SU2_MPI::Bcast(sbuf_conv, 1, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (sbuf_conv[0] == 1) { Convergence = true;}
- else { Convergence = false;}
-
- delete [] sbuf_conv;
- delete [] rbuf_conv;
-
-#endif
-
- /*--- Update the solution for the flow and structural zones ---*/
-
- /*--- Flow ---*/
-
- solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->UpdateSolution_BGS(geometry_container[ZONE_FLOW][INST_0][MESH_0],
- config_container[ZONE_FLOW]);
-
- /*--- Structure ---*/
-
- solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->UpdateSolution_BGS(geometry_container[ZONE_STRUCT][INST_0][MESH_0],
- config_container[ZONE_STRUCT]);
-
- return Convergence;
-}
-
-void CDiscAdjFSIDriver::Transfer_Displacements(unsigned short donorZone, unsigned short targetZone) {
-
-
- interface_container[donorZone][targetZone]->BroadcastData(solver_container[donorZone][INST_0][MESH_0][FEA_SOL],solver_container[targetZone][INST_0][MESH_0][FLOW_SOL],
- geometry_container[donorZone][INST_0][MESH_0],geometry_container[targetZone][INST_0][MESH_0],
- config_container[donorZone], config_container[targetZone]);
-
-}
-
-void CDiscAdjFSIDriver::Transfer_Tractions(unsigned short donorZone, unsigned short targetZone) {
-
- interface_container[donorZone][targetZone]->BroadcastData(solver_container[donorZone][INST_0][MESH_0][FEA_SOL],solver_container[targetZone][INST_0][MESH_0][FLOW_SOL],
- geometry_container[donorZone][INST_0][MESH_0],geometry_container[targetZone][INST_0][MESH_0],
- config_container[donorZone], config_container[targetZone]);
-}
diff --git a/SU2_CFD/src/drivers/CMultizoneDriver.cpp b/SU2_CFD/src/drivers/CMultizoneDriver.cpp
index 3eb3a9c0e716..ec76280e1d38 100644
--- a/SU2_CFD/src/drivers/CMultizoneDriver.cpp
+++ b/SU2_CFD/src/drivers/CMultizoneDriver.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -27,14 +27,10 @@
#include "../../include/drivers/CMultizoneDriver.hpp"
#include "../../include/definition_structure.hpp"
+#include "../../../Common/include/interface_interpolation/CInterpolator.hpp"
-
-CMultizoneDriver::CMultizoneDriver(char* confFile,
- unsigned short val_nZone,
- SU2_Comm MPICommunicator) : CDriver(confFile,
- val_nZone,
- MPICommunicator,
- false) {
+CMultizoneDriver::CMultizoneDriver(char* confFile, unsigned short val_nZone, SU2_Comm MPICommunicator) :
+ CDriver(confFile, val_nZone, MPICommunicator, false) {
/*--- Initialize the counter for TimeIter ---*/
TimeIter = 0;
@@ -289,7 +285,7 @@ void CMultizoneDriver::Preprocess(unsigned long TimeIter) {
for (iZone = 0; iZone < nZone; iZone++) {
for (unsigned short jZone = 0; jZone < nZone; jZone++){
if(jZone != iZone && interpolator_container[iZone][jZone] != NULL && prefixed_motion[iZone])
- interpolator_container[iZone][jZone]->Set_TransferCoeff(config_container);
+ interpolator_container[iZone][jZone]->SetTransferCoeff(config_container);
}
}
}
@@ -409,45 +405,37 @@ void CMultizoneDriver::Run_Jacobi() {
void CMultizoneDriver::Corrector(unsigned short val_iZone) {
- if (config_container[val_iZone]->GetRelaxation())
- iteration_container[val_iZone][INST_0]->Relaxation(output_container[ZONE_0], integration_container, geometry_container, solver_container,
- numerics_container, config_container, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
-
+ if (config_container[val_iZone]->GetRelaxation())
+ iteration_container[val_iZone][INST_0]->Relaxation(output_container[ZONE_0], integration_container,
+ geometry_container, solver_container, numerics_container, config_container,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
}
bool CMultizoneDriver::OuterConvergence(unsigned long OuterIter) {
- /*--- Update the residual for the all the zones ---*/
+ /*--- Update the residual for the all the zones. ---*/
- for (iZone = 0; iZone < nZone; iZone++){
+ for (iZone = 0; iZone < nZone; iZone++) {
- /*--- Account for all the solvers ---*/
+ /*--- Account for all the solvers in this zone. ---*/
+
+ auto solvers = solver_container[iZone][INST_0][MESH_0];
for (unsigned short iSol = 0; iSol < MAX_SOLS; iSol++){
- if (solver_container[iZone][INST_0][MESH_0][iSol] != nullptr){
- solver_container[iZone][INST_0][MESH_0][iSol]->ComputeResidual_Multizone(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
- }
+ if (solvers[iSol] != nullptr)
+ solvers[iSol]->ComputeResidual_Multizone(geometry_container[iZone][INST_0][MESH_0], config_container[iZone]);
}
- /*--- make sure that everything is loaded into the output container ---*/
+ /*--- Make sure that everything is loaded into the output container. ---*/
- output_container[iZone]->SetHistory_Output(geometry_container[iZone][INST_0][MESH_0],solver_container[iZone][INST_0][MESH_0], config_container[iZone]);
+ output_container[iZone]->SetHistory_Output(geometry_container[iZone][INST_0][MESH_0], solvers, config_container[iZone]);
}
- /*--- Update the residual for the all the zones ---*/
- for (iZone = 0; iZone < nZone; iZone++){
- /*--- Accounting for all the solvers ---*/
- for (unsigned short iSol = 0; iSol < MAX_SOLS; iSol++){
- /*-- If the solver position iSol is enabled --*/
- if (solver_container[iZone][INST_0][MESH_0][iSol] != nullptr){
- solver_container[iZone][INST_0][MESH_0][iSol]->UpdateSolution_BGS(geometry_container[iZone][INST_0][MESH_0],
- config_container[iZone]);}
- }
- }
+ /*--- Print out the convergence data to screen and history file. ---*/
- /*--- Print out the convergence data to screen and history file ---*/
- driver_output->SetMultizoneHistory_Output(output_container, config_container, driver_config, driver_config->GetTimeIter(), driver_config->GetOuterIter());
+ driver_output->SetMultizoneHistory_Output(output_container, config_container, driver_config,
+ driver_config->GetTimeIter(), driver_config->GetOuterIter());
return driver_output->GetConvergence();
@@ -549,22 +537,21 @@ void CMultizoneDriver::DynamicMeshUpdate(unsigned long TimeIter) {
void CMultizoneDriver::DynamicMeshUpdate(unsigned short val_iZone, unsigned long TimeIter) {
+ auto iteration = iteration_container[val_iZone][INST_0];
+
/*--- Legacy dynamic mesh update - Only if GRID_MOVEMENT = YES ---*/
- if (config_container[ZONE_0]->GetGrid_Movement() || config_container[ZONE_0]->GetSurface_Movement(FLUID_STRUCTURE_STATIC)) {
- iteration_container[val_iZone][INST_0]->SetGrid_Movement(geometry_container[val_iZone][INST_0],surface_movement[val_iZone],
- grid_movement[val_iZone][INST_0], solver_container[val_iZone][INST_0],
- config_container[val_iZone], 0, TimeIter);
+ if (config_container[ZONE_0]->GetGrid_Movement()) {
+ iteration->SetGrid_Movement(geometry_container[val_iZone][INST_0],surface_movement[val_iZone],
+ grid_movement[val_iZone][INST_0], solver_container[val_iZone][INST_0],
+ config_container[val_iZone], 0, TimeIter);
}
/*--- New solver - all the other routines in SetGrid_Movement should be adapted to this one ---*/
/*--- Works if DEFORM_MESH = YES ---*/
- if (config_container[ZONE_0]->GetDeform_Mesh()) {
- iteration_container[val_iZone][INST_0]->SetMesh_Deformation(geometry_container[val_iZone][INST_0],
- solver_container[val_iZone][INST_0][MESH_0],
- numerics_container[val_iZone][INST_0][MESH_0],
- config_container[ZONE_0],
- NONE);
- }
+ iteration->SetMesh_Deformation(geometry_container[val_iZone][INST_0],
+ solver_container[val_iZone][INST_0][MESH_0],
+ numerics_container[val_iZone][INST_0][MESH_0],
+ config_container[val_iZone], NONE);
}
@@ -621,13 +608,6 @@ bool CMultizoneDriver::Transfer_Data(unsigned short donorZone, unsigned short ta
targetSolver = HEAT_SOL;
break;
}
- case STRUCTURAL_DISPLACEMENTS_LEGACY:
- {
- donorSolver = FEA_SOL;
- targetSolver = FLOW_SOL;
- UpdateMesh = true;
- break;
- }
case BOUNDARY_DISPLACEMENTS:
{
donorSolver = FEA_SOL;
@@ -635,13 +615,6 @@ bool CMultizoneDriver::Transfer_Data(unsigned short donorZone, unsigned short ta
UpdateMesh = true;
break;
}
- case STRUCTURAL_DISPLACEMENTS_DISC_ADJ:
- {
- donorSolver = FEA_SOL;
- targetSolver = FLOW_SOL;
- UpdateMesh = true;
- break;
- }
case FLOW_TRACTION:
{
donorSolver = FLOW_SOL;
diff --git a/SU2_CFD/src/drivers/CSinglezoneDriver.cpp b/SU2_CFD/src/drivers/CSinglezoneDriver.cpp
index a1ab4f317c61..abb2837c9a87 100644
--- a/SU2_CFD/src/drivers/CSinglezoneDriver.cpp
+++ b/SU2_CFD/src/drivers/CSinglezoneDriver.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -226,23 +226,21 @@ void CSinglezoneDriver::Output(unsigned long TimeIter) {
void CSinglezoneDriver::DynamicMeshUpdate(unsigned long TimeIter) {
+ auto iteration = iteration_container[ZONE_0][INST_0];
+
/*--- Legacy dynamic mesh update - Only if GRID_MOVEMENT = YES ---*/
if (config_container[ZONE_0]->GetGrid_Movement()) {
- iteration_container[ZONE_0][INST_0]->SetGrid_Movement(geometry_container[ZONE_0][INST_0],surface_movement[ZONE_0],
- grid_movement[ZONE_0][INST_0], solver_container[ZONE_0][INST_0],
- config_container[ZONE_0], 0, TimeIter);
+ iteration->SetGrid_Movement(geometry_container[ZONE_0][INST_0],surface_movement[ZONE_0],
+ grid_movement[ZONE_0][INST_0], solver_container[ZONE_0][INST_0],
+ config_container[ZONE_0], 0, TimeIter);
}
/*--- New solver - all the other routines in SetGrid_Movement should be adapted to this one ---*/
/*--- Works if DEFORM_MESH = YES ---*/
- if (config_container[ZONE_0]->GetDeform_Mesh()) {
- iteration_container[ZONE_0][INST_0]->SetMesh_Deformation(geometry_container[ZONE_0][INST_0],
- solver_container[ZONE_0][INST_0][MESH_0],
- numerics_container[ZONE_0][INST_0][MESH_0],
- config_container[ZONE_0],
- NONE);
- }
-
+ iteration->SetMesh_Deformation(geometry_container[ZONE_0][INST_0],
+ solver_container[ZONE_0][INST_0][MESH_0],
+ numerics_container[ZONE_0][INST_0][MESH_0],
+ config_container[ZONE_0], NONE);
}
diff --git a/SU2_CFD/src/integration/CStructuralIntegration.cpp b/SU2_CFD/src/integration/CStructuralIntegration.cpp
index e7c2b9d9d447..ce9b9bd49de8 100644
--- a/SU2_CFD/src/integration/CStructuralIntegration.cpp
+++ b/SU2_CFD/src/integration/CStructuralIntegration.cpp
@@ -71,32 +71,20 @@ void CStructuralIntegration::Structural_Iteration(CGeometry ****geometry, CSolve
void CStructuralIntegration::Space_Integration_FEM(CGeometry *geometry, CSolver **solver_container,
CNumerics **numerics, CConfig *config,
unsigned short RunTime_EqSystem) {
- bool dynamic = config->GetTime_Domain();
bool first_iter = (config->GetInnerIter() == 0);
bool linear_analysis = (config->GetGeometricConditions() == SMALL_DEFORMATIONS);
- bool nonlinear_analysis = (config->GetGeometricConditions() == LARGE_DEFORMATIONS);
unsigned short IterativeScheme = config->GetKind_SpaceIteScheme_FEA();
unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem);
CSolver* solver = solver_container[MainSolver];
- /*--- Initial calculation, different logic for restarted simulations. ---*/
- bool initial_calc = false;
- if (config->GetRestart())
- initial_calc = (config->GetTimeIter() == config->GetRestart_Iter()) && first_iter;
- else
- initial_calc = (config->GetTimeIter() == 0) && first_iter;
+ /*--- Mass Matrix was computed during preprocessing, see notes therein. ---*/
- /*--- Mass Matrix computed during preprocessing, see notes therein. ---*/
-
- /*--- If the analysis is linear, only a the constitutive term of the stiffness matrix has to be computed. ---*/
- /*--- This is done only once, at the beginning of the calculation. From then on, K is constant. ---*/
- /*--- For correct differentiation of dynamic cases the matrix needs to be computed every time. ---*/
- if (linear_analysis && (dynamic || initial_calc))
+ if (linear_analysis) {
+ /*--- If the analysis is linear, only a the constitutive term of the stiffness matrix has to be computed. ---*/
solver->Compute_StiffMatrix(geometry, numerics, config);
-
- if (nonlinear_analysis) {
-
+ }
+ else {
/*--- If the analysis is nonlinear the stress terms also need to be computed. ---*/
/*--- For full Newton-Raphson the stiffness matrix and the nodal term are updated every time. ---*/
if (IterativeScheme == NEWTON_RAPHSON) {
@@ -111,7 +99,6 @@ void CStructuralIntegration::Space_Integration_FEM(CGeometry *geometry, CSolver
else
solver->Compute_NodalStressRes(geometry, numerics, config);
}
-
}
/*--- Apply the NATURAL BOUNDARY CONDITIONS (loads). ---*/
diff --git a/SU2_CFD/src/interfaces/CInterface.cpp b/SU2_CFD/src/interfaces/CInterface.cpp
index 754ed141c4ac..b871cb8a4c18 100644
--- a/SU2_CFD/src/interfaces/CInterface.cpp
+++ b/SU2_CFD/src/interfaces/CInterface.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -26,79 +26,42 @@
*/
#include "../../include/interfaces/CInterface.hpp"
+#include "../../../Common/include/interface_interpolation/CInterpolator.hpp"
-CInterface::CInterface(void) {
-
- rank = SU2_MPI::GetRank();
- size = SU2_MPI::GetSize();
-
- Physical_Constants = NULL;
- Donor_Variable = NULL;
- Target_Variable = NULL;
- SpanLevelDonor = NULL;
- SpanValueCoeffTarget = NULL;
-
- nVar = 0;
-
+CInterface::CInterface(void) :
+ rank(SU2_MPI::GetRank()),
+ size(SU2_MPI::GetSize()) {
}
-CInterface::CInterface(unsigned short val_nVar, unsigned short val_nConst, CConfig *config) {
-
- rank = SU2_MPI::GetRank();
- size = SU2_MPI::GetSize();
+CInterface::CInterface(unsigned short val_nVar, unsigned short val_nConst, CConfig *config) :
+ rank(SU2_MPI::GetRank()),
+ size(SU2_MPI::GetSize()),
+ nVar(val_nVar) {
- Physical_Constants = NULL;
- Donor_Variable = NULL;
- Target_Variable = NULL;
-
- unsigned short iVar;
-
- Physical_Constants = new su2double[val_nConst];
- Donor_Variable = new su2double[val_nVar];
- Target_Variable = new su2double[val_nVar];
+ Physical_Constants = new su2double[val_nConst] ();
+ Donor_Variable = new su2double[val_nVar] ();
+ Target_Variable = new su2double[val_nVar] ();
/*--- By default, the value is aggregated in the transfer routine ---*/
valAggregated = true;
-
- nVar = val_nVar;
-
- for (iVar = 0; iVar < nVar; iVar++) {
- Donor_Variable[iVar] = 0.0;
- Target_Variable[iVar] = 0.0;
- }
-
- for (iVar = 0; iVar < val_nConst; iVar++) {
- Physical_Constants[iVar] = 0.0;
- }
-
- SpanLevelDonor = NULL;
- SpanValueCoeffTarget = NULL;
-
}
CInterface::~CInterface(void) {
- if (Physical_Constants != NULL) delete [] Physical_Constants;
- if (Donor_Variable != NULL) delete [] Donor_Variable;
- if (Target_Variable != NULL) delete [] Target_Variable;
-
- if (SpanValueCoeffTarget != NULL) delete[] SpanValueCoeffTarget;
- if (SpanLevelDonor != NULL) delete[] SpanLevelDonor;
+ delete [] Physical_Constants;
+ delete [] Donor_Variable;
+ delete [] Target_Variable;
+ delete[] SpanValueCoeffTarget;
+ delete[] SpanLevelDonor;
}
void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution,
CGeometry *donor_geometry, CGeometry *target_geometry,
CConfig *donor_config, CConfig *target_config) {
-
- unsigned short nMarkerInt, nMarkerDonor, nMarkerTarget; // Number of markers on the interface, donor and target side
- unsigned short iMarkerInt, iMarkerDonor, iMarkerTarget; // Variables for iteration over markers
int Marker_Donor, Marker_Target;
- int Target_check, Donor_check;
-
- unsigned long iVertex; // Variables for iteration over vertices and nodes
-
+ unsigned long iVertex;
unsigned short iVar;
GetPhysical_Constants(donor_solution, target_solution, donor_geometry, target_geometry,
@@ -107,14 +70,8 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
unsigned long Point_Donor_Global, Donor_Global_Index;
unsigned long Point_Donor, Point_Target;
-#ifdef HAVE_MPI
- int *Buffer_Recv_mark = NULL, iRank;
-
- if (rank == MASTER_NODE)
- Buffer_Recv_mark = new int[size];
-#endif
-
- unsigned long Buffer_Send_nVertexDonor[1], *Buffer_Recv_nVertexDonor;
+ unsigned long Buffer_Send_nVertexDonor[1];
+ unsigned long *Buffer_Recv_nVertexDonor = new unsigned long[size];
unsigned long iLocalVertex = 0;
unsigned long nLocalVertexDonor = 0, nLocalVertexDonorOwned = 0;
@@ -125,98 +82,23 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
unsigned long nBuffer_BcastVariables = 0, nBuffer_BcastIndices = 0;
- int nProcessor = 0;
+ const int nProcessor = size;
/*--- Number of markers on the FSI interface ---*/
- nMarkerInt = (donor_config->GetMarker_n_ZoneInterface())/2;
- nMarkerTarget = target_config->GetnMarker_All();
- nMarkerDonor = donor_config->GetnMarker_All();
-
- nProcessor = size;
+ const auto nMarkerInt = donor_config->GetMarker_n_ZoneInterface()/2;
/*--- Outer loop over the markers on the FSI interface: compute one by one ---*/
/*--- The tags are always an integer greater than 1: loop from 1 to nMarkerFSI ---*/
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
+ for (unsigned short iMarkerInt = 1; iMarkerInt <= nMarkerInt; iMarkerInt++) {
- Buffer_Recv_nVertexDonor = NULL;
+ /*--- Check if this interface connects the two zones, if not continue. ---*/
- Marker_Donor = -1;
- Marker_Target = -1;
+ Marker_Donor = CInterpolator::FindInterfaceMarker(donor_config, iMarkerInt);
+ Marker_Target = CInterpolator::FindInterfaceMarker(target_config, iMarkerInt);
- /*--- The donor and target markers are tagged with the same index.
- *--- This is independent of the MPI domain decomposition.
- *--- We need to loop over all markers on both sides and get the number of nodes
- *--- that belong to each FSI marker for each processor ---*/
-
- /*--- On the donor side ---*/
-
- for (iMarkerDonor = 0; iMarkerDonor < nMarkerDonor; iMarkerDonor++) {
- /*--- If the tag GetMarker_All_ZoneInterface(iMarkerDonor) equals the index we are looping at ---*/
- if ( donor_config->GetMarker_All_ZoneInterface(iMarkerDonor) == iMarkerInt ) {
- /*--- Store the identifier for the structural marker ---*/
- Marker_Donor = iMarkerDonor;
- /*--- Exit the for loop: we have found the local index for iMarkerFSI on the FEA side ---*/
- break;
- }
- }
-
- /*--- On the target side we only have to identify the marker;
- * then we'll loop over it and retrieve from the donor points ---*/
-
- for (iMarkerTarget = 0; iMarkerTarget < nMarkerTarget; iMarkerTarget++) {
- /*--- If the tag GetMarker_All_ZoneInterface(iMarkerFlow) equals the index we are looping at ---*/
- if ( target_config->GetMarker_All_ZoneInterface(iMarkerTarget) == iMarkerInt ) {
- /*--- Store the identifier for the fluid marker ---*/
- Marker_Target = iMarkerTarget;
- /*--- Exit the for loop: we have found the local index for iMarkerFSI on the FEA side ---*/
- break;
- }
- }
-
-#ifdef HAVE_MPI
-
- Donor_check = -1;
- Target_check = -1;
-
- /*--- We gather a vector in MASTER_NODE that determines if the boundary is not on the processor
- * because of the partition or because the zone does not include it ---*/
-
- SU2_MPI::Gather(&Marker_Donor , 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE) {
- for (iRank = 0; iRank < nProcessor; iRank++) {
- if( Buffer_Recv_mark[iRank] != -1 ) {
- Donor_check = Buffer_Recv_mark[iRank];
- break;
- }
- }
- }
-
- SU2_MPI::Bcast(&Donor_check , 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- SU2_MPI::Gather(&Marker_Target, 1, MPI_INT, Buffer_Recv_mark, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
- if (rank == MASTER_NODE) {
- for (iRank = 0; iRank < nProcessor; iRank++) {
- if( Buffer_Recv_mark[iRank] != -1 ) {
- Target_check = Buffer_Recv_mark[iRank];
- break;
- }
- }
- }
-
- SU2_MPI::Bcast(&Target_check, 1, MPI_INT, MASTER_NODE, MPI_COMM_WORLD);
-
-#else
- Donor_check = Marker_Donor;
- Target_check = Marker_Target;
-#endif
-
- if(Target_check == -1 || Donor_check == -1) {
- continue;
- }
+ if(!CInterpolator::CheckInterfaceBoundary(Marker_Donor, Marker_Target)) continue;
nLocalVertexDonorOwned = 0;
nLocalVertexDonor = 0;
@@ -233,10 +115,6 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
Buffer_Send_nVertexDonor[0] = nLocalVertexDonor; // Retrieve total number of vertices on Donor marker
- // Allocate memory to receive how many vertices are on each rank on the structural side
- if (rank == MASTER_NODE) Buffer_Recv_nVertexDonor = new unsigned long[size];
-
-#ifdef HAVE_MPI
/*--- We receive MaxLocalVertexDonor as the maximum number of vertices
* in one single processor on the donor side---*/
SU2_MPI::Allreduce(&nLocalVertexDonor, &MaxLocalVertexDonor, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
@@ -245,13 +123,8 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
SU2_MPI::Allreduce(&nLocalVertexDonorOwned, &TotalVertexDonor, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
/*--- We gather a vector in MASTER_NODE that determines how many elements are there
* on each processor on the structural side ---*/
- SU2_MPI::Gather(&Buffer_Send_nVertexDonor, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertexDonor, 1,
- MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
-#else
- MaxLocalVertexDonor = nLocalVertexDonor;
- TotalVertexDonor = nLocalVertexDonorOwned;
- Buffer_Recv_nVertexDonor[0] = Buffer_Send_nVertexDonor[0];
-#endif
+ SU2_MPI::Gather(&Buffer_Send_nVertexDonor, 1, MPI_UNSIGNED_LONG,
+ Buffer_Recv_nVertexDonor, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
/*--- We will be gathering the donor information into the master node ---*/
nBuffer_DonorVariables = MaxLocalVertexDonor * nVar;
@@ -308,20 +181,12 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
}
-#ifdef HAVE_MPI
/*--- Once all the messages have been prepared, we gather them all into the MASTER_NODE ---*/
SU2_MPI::Gather(Buffer_Send_DonorVariables, nBuffer_DonorVariables, MPI_DOUBLE, Buffer_Recv_DonorVariables,
nBuffer_DonorVariables, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
SU2_MPI::Gather(Buffer_Send_DonorIndices, nBuffer_DonorIndices, MPI_LONG, Buffer_Recv_DonorIndices,
nBuffer_DonorIndices, MPI_LONG, MASTER_NODE, MPI_COMM_WORLD);
-#else
- for (unsigned long iVariable = 0; iVariable < nBuffer_DonorVariables; iVariable++)
- Buffer_Recv_DonorVariables[iVariable] = Buffer_Send_DonorVariables[iVariable];
- for (unsigned long iVariable = 0; iVariable < nBuffer_DonorIndices; iVariable++)
- Buffer_Recv_DonorIndices[iVariable] = Buffer_Send_DonorIndices[iVariable];
-#endif
-
/*--- Now we pack the information to send it over to the different processors ---*/
if (rank == MASTER_NODE) {
@@ -352,10 +217,8 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
}
-#ifdef HAVE_MPI
SU2_MPI::Bcast(Buffer_Bcast_Variables, nBuffer_BcastVariables, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
SU2_MPI::Bcast(Buffer_Bcast_Indices, nBuffer_BcastIndices, MPI_LONG, MASTER_NODE, MPI_COMM_WORLD);
-#endif
long indexPoint_iVertex;
unsigned short iDonorPoint, nDonorPoints;
@@ -418,18 +281,11 @@ void CInterface::BroadcastData(CSolver *donor_solution, CSolver *target_solution
delete [] Buffer_Bcast_Variables;
delete [] Buffer_Bcast_Indices;
- if (rank == MASTER_NODE) {
- delete [] Buffer_Recv_nVertexDonor;
- delete [] Buffer_Recv_DonorVariables;
- delete [] Buffer_Recv_DonorIndices;
- }
-
+ delete [] Buffer_Recv_DonorVariables;
+ delete [] Buffer_Recv_DonorIndices;
}
-#ifdef HAVE_MPI
- if (rank == MASTER_NODE && Buffer_Recv_mark != NULL)
- delete [] Buffer_Recv_mark;
-#endif
+ delete [] Buffer_Recv_nVertexDonor;
}
void CInterface::PreprocessAverage(CGeometry *donor_geometry, CGeometry *target_geometry,
@@ -444,12 +300,6 @@ void CInterface::PreprocessAverage(CGeometry *donor_geometry, CGeometry *target_
const su2double *SpanValuesDonor, *SpanValuesTarget;
su2double dist, test, dist2, test2;
-#ifdef HAVE_MPI
- int iSize;
- int *BuffMarkerDonor, *BuffDonorFlag;
-#endif
-
-
nMarkerDonor = donor_geometry->GetnMarker();
nMarkerTarget = target_geometry->GetnMarker();
//TODO turbo this approach only works if all the turboamchinery marker
@@ -478,25 +328,23 @@ void CInterface::PreprocessAverage(CGeometry *donor_geometry, CGeometry *target_
}
#ifdef HAVE_MPI
- BuffMarkerDonor = new int[size];
- BuffDonorFlag = new int[size];
- for (iSize=0; iSize 0.0){
Marker_Donor = BuffMarkerDonor[iSize];
- Donor_Flag = BuffDonorFlag[iSize];
+ Donor_Flag = BuffDonorFlag[iSize];
break;
}
}
@@ -574,6 +422,7 @@ void CInterface::PreprocessAverage(CGeometry *donor_geometry, CGeometry *target_
void CInterface::AllgatherAverage(CSolver *donor_solution, CSolver *target_solution,
CGeometry *donor_geometry, CGeometry *target_geometry,
CConfig *donor_config, CConfig *target_config, unsigned short iMarkerInt){
+
unsigned short nMarkerDonor, nMarkerTarget; // Number of markers on the interface, donor and target side
unsigned short iMarkerDonor, iMarkerTarget; // Variables for iteration over markers
unsigned short iSpan, nSpanDonor, nSpanTarget;
@@ -767,7 +616,6 @@ void CInterface::AllgatherAverage(CSolver *donor_solution, CSolver *target_solut
delete [] BuffAvgKineDonor;
delete [] BuffAvgOmegaDonor;
delete [] BuffMarkerDonor;
-
#endif
/*--- On the target side we have to identify the marker as well ---*/
@@ -904,4 +752,3 @@ void CInterface::GatherAverageTurboGeoValues(CGeometry *donor_geometry, CGeometr
SetAverageTurboGeoValues(donor_geometry, target_geometry, donorZone);
}
-
diff --git a/SU2_CFD/src/interfaces/cfd/CSlidingInterface.cpp b/SU2_CFD/src/interfaces/cfd/CSlidingInterface.cpp
index 6e31afdf8715..f0c024ff379e 100644
--- a/SU2_CFD/src/interfaces/cfd/CSlidingInterface.cpp
+++ b/SU2_CFD/src/interfaces/cfd/CSlidingInterface.cpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -29,52 +29,25 @@
#include "../../../include/interfaces/cfd/CSlidingInterface.hpp"
-CSlidingInterface::CSlidingInterface(void) : CInterface() {
-
-}
+CSlidingInterface::CSlidingInterface(void) : CInterface() { }
CSlidingInterface::CSlidingInterface(unsigned short val_nVar, unsigned short val_nConst,
CConfig *config) : CInterface() {
- rank = SU2_MPI::GetRank();
- size = SU2_MPI::GetSize();
-
- Physical_Constants = NULL;
- Donor_Variable = NULL;
- Target_Variable = NULL;
-
- unsigned short iVar;
-
- Physical_Constants = new su2double[val_nConst];
- Donor_Variable = new su2double[val_nVar];
-
- Target_Variable = new su2double[val_nVar+1];
+ Physical_Constants = new su2double[val_nConst] ();
+ Donor_Variable = new su2double[val_nVar] ();
+ Target_Variable = new su2double[val_nVar+1] ();
valAggregated = false;
nVar = val_nVar;
-
- for (iVar = 0; iVar < nVar; iVar++) {
- Donor_Variable[iVar] = 0.0;
- Target_Variable[iVar] = 0.0;
- }
-
- for (iVar = 0; iVar < val_nConst; iVar++) {
- Physical_Constants[iVar] = 0.0;
- }
-
-}
-
-CSlidingInterface::~CSlidingInterface(void) {
-
}
+CSlidingInterface::~CSlidingInterface(void) { }
void CSlidingInterface::GetPhysical_Constants(CSolver *donor_solution, CSolver *target_solution,
CGeometry *donor_geometry, CGeometry *target_geometry,
- CConfig *donor_config, CConfig *target_config) {
-
-}
+ CConfig *donor_config, CConfig *target_config) { }
void CSlidingInterface::GetDonor_Variable(CSolver *donor_solution, CGeometry *donor_geometry,
CConfig *donor_config, unsigned long Marker_Donor,
diff --git a/SU2_CFD/src/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.cpp b/SU2_CFD/src/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.cpp
deleted file mode 100644
index b9f4dad1bc27..000000000000
--- a/SU2_CFD/src/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*!
- * \file CDiscAdjDisplacementsInterfaceLegacy.cpp
- * \brief Declaration and inlines of the class to transfer structural displacements
- * from a structural zone into a fluid zone in a discrete adjoint simulation.
- * \author Ruben Sanchez
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-
-#include "../../../include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp"
-
-CDiscAdjDisplacementsInterfaceLegacy::CDiscAdjDisplacementsInterfaceLegacy(void) : CInterface() {
-
-}
-
-CDiscAdjDisplacementsInterfaceLegacy::CDiscAdjDisplacementsInterfaceLegacy(unsigned short val_nVar,
- unsigned short val_nConst,
- CConfig *config)
- : CInterface(val_nVar,
- val_nConst,
- config) {
-
-}
-
-CDiscAdjDisplacementsInterfaceLegacy::~CDiscAdjDisplacementsInterfaceLegacy(void) {
-
-}
-
-
-void CDiscAdjDisplacementsInterfaceLegacy::GetPhysical_Constants(CSolver *struct_solution,
- CSolver *flow_solution,
- CGeometry *struct_geometry,
- CGeometry *flow_geometry,
- CConfig *struct_config,
- CConfig *flow_config) {
-}
-
-void CDiscAdjDisplacementsInterfaceLegacy::GetDonor_Variable(CSolver *struct_solution,
- CGeometry *struct_geometry,
- CConfig *struct_config,
- unsigned long Marker_Struct,
- unsigned long Vertex_Struct,
- unsigned long Point_Struct) {
-
-
- su2double *Coord_Struct, *Displacement_Struct;
- unsigned short iVar;
-
- Coord_Struct = struct_geometry->node[Point_Struct]->GetCoord();
-
- /*--- The displacements come from the predicted solution ---*/
- Displacement_Struct = struct_solution->GetNodes()->GetSolution(Point_Struct);
-
- for (iVar = 0; iVar < nVar; iVar++)
- Donor_Variable[iVar] = Coord_Struct[iVar] + Displacement_Struct[iVar];
-}
-
-void CDiscAdjDisplacementsInterfaceLegacy::SetTarget_Variable(CSolver *flow_solution,
- CGeometry *flow_geometry,
- CConfig *flow_config,
- unsigned long Marker_Flow,
- unsigned long Vertex_Flow,
- unsigned long Point_Flow) {
-
- su2double *Coord, VarCoord[3] = {0.0, 0.0, 0.0};
- unsigned short iVar;
-
- Coord = flow_geometry->node[Point_Flow]->GetCoord();
-
- for (iVar = 0; iVar < nVar; iVar++)
- VarCoord[iVar] = Target_Variable[iVar]-Coord[iVar];
-
- flow_geometry->vertex[Marker_Flow][Vertex_Flow]->SetVarCoord(VarCoord);
-}
diff --git a/SU2_CFD/src/interfaces/fsi/CDiscAdjFlowTractionInterface.cpp b/SU2_CFD/src/interfaces/fsi/CDiscAdjFlowTractionInterface.cpp
index dda569a7be2b..74b565c098a3 100644
--- a/SU2_CFD/src/interfaces/fsi/CDiscAdjFlowTractionInterface.cpp
+++ b/SU2_CFD/src/interfaces/fsi/CDiscAdjFlowTractionInterface.cpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -28,17 +28,10 @@
#include "../../../include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp"
-CDiscAdjFlowTractionInterface::CDiscAdjFlowTractionInterface(void) : CFlowTractionInterface() {
-
-}
CDiscAdjFlowTractionInterface::CDiscAdjFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst,
- CConfig *config) :
- CFlowTractionInterface(val_nVar, val_nConst, config) {
-
-}
-
-CDiscAdjFlowTractionInterface::~CDiscAdjFlowTractionInterface(void) {
+ CConfig *config, bool integrate_tractions_) :
+ CFlowTractionInterface(val_nVar, val_nConst, config, integrate_tractions_) {
}
diff --git a/SU2_CFD/src/interfaces/fsi/CDisplacementsInterfaceLegacy.cpp b/SU2_CFD/src/interfaces/fsi/CDisplacementsInterfaceLegacy.cpp
deleted file mode 100644
index 137d6a454ca4..000000000000
--- a/SU2_CFD/src/interfaces/fsi/CDisplacementsInterfaceLegacy.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*!
- * \file CDisplacementsInterfaceLegacy.cpp
- * \brief Declaration and inlines of the class to transfer structural displacements
- * from a structural zone into a fluid zone.
- * \author Ruben Sanchez
- * \version 7.0.3 "Blackbird"
- *
- * SU2 Project Website: https://su2code.github.io
- *
- * The SU2 Project is maintained by the SU2 Foundation
- * (http://su2foundation.org)
- *
- * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
- *
- * SU2 is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * SU2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with SU2. If not, see .
- */
-
-#include "../../../include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp"
-
-CDisplacementsInterfaceLegacy::CDisplacementsInterfaceLegacy(void) : CInterface() {
-
-}
-
-CDisplacementsInterfaceLegacy::CDisplacementsInterfaceLegacy(unsigned short val_nVar,
- unsigned short val_nConst, CConfig *config) :
- CInterface(val_nVar, val_nConst, config) {
-
-}
-
-CDisplacementsInterfaceLegacy::~CDisplacementsInterfaceLegacy(void) {
-
-}
-
-
-void CDisplacementsInterfaceLegacy::GetPhysical_Constants(CSolver *struct_solution, CSolver *flow_solution,
- CGeometry *struct_geometry, CGeometry *flow_geometry,
- CConfig *struct_config, CConfig *flow_config) {
-}
-
-void CDisplacementsInterfaceLegacy::GetDonor_Variable(CSolver *struct_solution, CGeometry *struct_geometry,
- CConfig *struct_config, unsigned long Marker_Struct,
- unsigned long Vertex_Struct, unsigned long Point_Struct) {
-
- su2double *DisplacementDonor, *DisplacementDonor_Prev;
- unsigned short iVar;
-
- /*--- The displacements come from the predicted solution ---*/
- DisplacementDonor = struct_solution->GetNodes()->GetSolution_Pred(Point_Struct);
-
- DisplacementDonor_Prev = struct_solution->GetNodes()->GetSolution_Pred_Old(Point_Struct);
-
- for (iVar = 0; iVar < nVar; iVar++)
- Donor_Variable[iVar] = DisplacementDonor[iVar] - DisplacementDonor_Prev[iVar];
-}
-
-void CDisplacementsInterfaceLegacy::SetTarget_Variable(CSolver *flow_solution, CGeometry *flow_geometry,
- CConfig *flow_config, unsigned long Marker_Flow,
- unsigned long Vertex_Flow, unsigned long Point_Flow) {
-
- flow_geometry->vertex[Marker_Flow][Vertex_Flow]->SetVarCoord(Target_Variable);
-}
diff --git a/SU2_CFD/src/interfaces/fsi/CFlowTractionInterface.cpp b/SU2_CFD/src/interfaces/fsi/CFlowTractionInterface.cpp
index 94a51431fa47..d9769706b831 100644
--- a/SU2_CFD/src/interfaces/fsi/CFlowTractionInterface.cpp
+++ b/SU2_CFD/src/interfaces/fsi/CFlowTractionInterface.cpp
@@ -7,7 +7,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -28,28 +28,18 @@
#include "../../../include/interfaces/fsi/CFlowTractionInterface.hpp"
-CFlowTractionInterface::CFlowTractionInterface(void) : CInterface() {
-}
-
-CFlowTractionInterface::CFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst, CConfig *config) :
- CInterface(val_nVar, val_nConst, config) {
-
-}
-
-CFlowTractionInterface::~CFlowTractionInterface(void) {
+CFlowTractionInterface::CFlowTractionInterface(unsigned short val_nVar, unsigned short val_nConst,
+ CConfig *config, bool integrate_tractions_) :
+ CInterface(val_nVar, val_nConst, config),
+ integrate_tractions(integrate_tractions_) {
}
void CFlowTractionInterface::Preprocess(CConfig *flow_config) {
- /*--- Store if consistent interpolation is in use, in which case we need to transfer stresses
- and integrate on the structural side rather than directly transferring forces. ---*/
- consistent_interpolation = (!flow_config->GetConservativeInterpolation() ||
- (flow_config->GetKindInterpolation() == WEIGHTED_AVERAGE));
-
/*--- Compute the constant factor to dimensionalize pressure and shear stress. ---*/
- su2double *Velocity_ND, *Velocity_Real;
+ const su2double *Velocity_ND, *Velocity_Real;
su2double Density_ND, Density_Real, Velocity2_Real, Velocity2_ND;
Velocity_Real = flow_config->GetVelocity_FreeStream();
@@ -110,89 +100,73 @@ void CFlowTractionInterface::GetPhysical_Constants(CSolver *flow_solution, CSolv
void CFlowTractionInterface::GetDonor_Variable(CSolver *flow_solution, CGeometry *flow_geometry,
CConfig *flow_config, unsigned long Marker_Flow,
unsigned long Vertex_Flow, unsigned long Point_Struct) {
-
-
unsigned short iVar, jVar;
- unsigned long Point_Flow;
- su2double const *Normal_Flow;
// Check the kind of fluid problem
- bool compressible = (flow_config->GetKind_Regime() == COMPRESSIBLE);
- bool incompressible = (flow_config->GetKind_Regime() == INCOMPRESSIBLE);
- bool viscous_flow = ((flow_config->GetKind_Solver() == NAVIER_STOKES) ||
- (flow_config->GetKind_Solver() == RANS) ||
- (flow_config->GetKind_Solver() == INC_NAVIER_STOKES) ||
- (flow_config->GetKind_Solver() == INC_RANS) ||
- (flow_config->GetKind_Solver() == DISC_ADJ_NAVIER_STOKES) ||
- (flow_config->GetKind_Solver() == DISC_ADJ_RANS) ||
- (flow_config->GetKind_Solver() == DISC_ADJ_INC_NAVIER_STOKES) ||
- (flow_config->GetKind_Solver() == DISC_ADJ_INC_RANS));
-
- // Parameters for the calculations
- // Pn: Pressure
- // Pinf: Pressure_infinite
- // div_vel: Velocity divergence
- // Dij: Dirac delta
- // area: area of the face, needed if we transfer stress instead of force
- su2double Pn = 0.0, div_vel = 0.0;
- su2double Viscosity = 0.0;
- su2double Tau[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
- su2double Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
- su2double delta[3][3] = {{1.0, 0.0, 0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
- su2double area = 0.0;
+ bool viscous_flow;
+ switch (flow_config->GetKind_Solver()) {
+ case RANS: case INC_RANS:
+ case NAVIER_STOKES: case INC_NAVIER_STOKES:
+ case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS:
+ case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_INC_NAVIER_STOKES:
+ viscous_flow = true; break;
+ default:
+ viscous_flow = false; break;
+ }
- su2double Pinf = flow_solution->GetPressure_Inf();
+ const auto Point_Flow = flow_geometry->vertex[Marker_Flow][Vertex_Flow]->GetNode();
- Point_Flow = flow_geometry->vertex[Marker_Flow][Vertex_Flow]->GetNode();
// Get the normal at the vertex: this normal goes inside the fluid domain.
- Normal_Flow = flow_geometry->vertex[Marker_Flow][Vertex_Flow]->GetNormal();
-
- if (consistent_interpolation)
- for (iVar = 0; iVar < nVar; ++iVar) area += Normal_Flow[iVar]*Normal_Flow[iVar];
- else
- area = 1.0;
- area = sqrt(area);
+ const su2double* Normal_Flow = flow_geometry->vertex[Marker_Flow][Vertex_Flow]->GetNormal();
+
+ // If we do not want integrated tractions, i.e. forces, we will need to divide by area.
+ su2double oneOnArea = 1.0;
+ if (!integrate_tractions) {
+ oneOnArea = 0.0;
+ for (iVar = 0; iVar < nVar; ++iVar) oneOnArea += pow(Normal_Flow[iVar], 2);
+ oneOnArea = 1.0 / sqrt(oneOnArea);
+ }
// Retrieve the values of pressure
- Pn = flow_solution->GetNodes()->GetPressure(Point_Flow);
+ CVariable* flow_nodes = flow_solution->GetNodes();
+ su2double Pinf = flow_solution->GetPressure_Inf();
+ su2double Pn = flow_nodes->GetPressure(Point_Flow);
// Calculate tn in the fluid nodes for the inviscid term --> Units of force (non-dimensional).
+
for (iVar = 0; iVar < nVar; iVar++)
Donor_Variable[iVar] = -(Pn-Pinf)*Normal_Flow[iVar];
// Calculate tn in the fluid nodes for the viscous term
- if ((incompressible || compressible) && viscous_flow) {
+ if (viscous_flow) {
- Viscosity = flow_solution->GetNodes()->GetLaminarViscosity(Point_Flow);
+ su2double Viscosity = flow_nodes->GetLaminarViscosity(Point_Flow);
- for (iVar = 0; iVar < nVar; iVar++) {
- for (jVar = 0 ; jVar < nVar; jVar++) {
- Grad_Vel[iVar][jVar] = flow_solution->GetNodes()->GetGradient_Primitive(Point_Flow, iVar+1, jVar);
- }
- }
+ const su2double* const* GradVel = &flow_nodes->GetGradient_Primitive(Point_Flow)[1];
// Divergence of the velocity
- div_vel = 0.0; for (iVar = 0; iVar < nVar; iVar++) div_vel += Grad_Vel[iVar][iVar];
+ su2double DivVel = 0.0;
+ for (iVar = 0; iVar < nVar; iVar++) DivVel += GradVel[iVar][iVar];
for (iVar = 0; iVar < nVar; iVar++) {
for (jVar = 0 ; jVar < nVar; jVar++) {
// Viscous stress
- Tau[iVar][jVar] = Viscosity*(Grad_Vel[jVar][iVar] + Grad_Vel[iVar][jVar])
- - TWO3*Viscosity*div_vel*delta[iVar][jVar];
+ su2double delta_ij = (iVar == jVar);
+ su2double tau_ij = Viscosity*(GradVel[jVar][iVar] + GradVel[iVar][jVar] - TWO3*DivVel*delta_ij);
// Viscous component in the tn vector --> Units of force (non-dimensional).
- Donor_Variable[iVar] += Tau[iVar][jVar]*Normal_Flow[jVar];
+ Donor_Variable[iVar] += tau_ij * Normal_Flow[jVar];
}
}
}
// Redimensionalize and take into account ramp transfer of the loads
for (iVar = 0; iVar < nVar; iVar++) {
- Donor_Variable[iVar] *= Physical_Constants[0] * Physical_Constants[1] / area;
+ Donor_Variable[iVar] *= Physical_Constants[0] * Physical_Constants[1] * oneOnArea;
}
}
diff --git a/SU2_CFD/src/iteration_structure.cpp b/SU2_CFD/src/iteration_structure.cpp
index 3059b379d238..4821565942d2 100644
--- a/SU2_CFD/src/iteration_structure.cpp
+++ b/SU2_CFD/src/iteration_structure.cpp
@@ -55,7 +55,6 @@ void CIteration::SetGrid_Movement(CGeometry **geometry,
unsigned long nIterMesh;
bool stat_mesh = true;
bool adjoint = config->GetContinuous_Adjoint();
- bool discrete_adjoint = config->GetDiscrete_Adjoint();
/*--- Only write to screen if this option is enabled ---*/
bool Screen_Output = config->GetDeform_Output();
@@ -67,287 +66,142 @@ void CIteration::SetGrid_Movement(CGeometry **geometry,
case RIGID_MOTION:
- if (rank == MASTER_NODE) {
- cout << endl << " Performing rigid mesh transformation." << endl;
- }
+ if (rank == MASTER_NODE)
+ cout << endl << " Performing rigid mesh transformation." << endl;
- /*--- Move each node in the volume mesh using the specified type
- of rigid mesh motion. These routines also compute analytic grid
- velocities for the fine mesh. ---*/
+ /*--- Move each node in the volume mesh using the specified type
+ of rigid mesh motion. These routines also compute analytic grid
+ velocities for the fine mesh. ---*/
- grid_movement->Rigid_Translation(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Plunging(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Pitching(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Rotation(geometry[MESH_0],
- config, val_iZone, TimeIter);
+ grid_movement->Rigid_Translation(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Plunging(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Pitching(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Rotation(geometry[MESH_0], config, val_iZone, TimeIter);
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
+ /*--- Update the multigrid structure after moving the finest grid,
+ including computing the grid velocities on the coarser levels. ---*/
- grid_movement->UpdateMultiGrid(geometry, config);
+ grid_movement->UpdateMultiGrid(geometry, config);
- break;
+ break;
/*--- Already initialized in the static mesh movement routine at driver level. ---*/
- case STEADY_TRANSLATION: case ROTATING_FRAME:
+ case STEADY_TRANSLATION:
+ case ROTATING_FRAME:
break;
}
- if (config->GetSurface_Movement(DEFORMING)){
- if (rank == MASTER_NODE)
- cout << endl << " Updating surface positions." << endl;
-
- /*--- Translating ---*/
-
- /*--- Compute the new node locations for moving markers ---*/
+ if (config->GetSurface_Movement(AEROELASTIC) ||
+ config->GetSurface_Movement(AEROELASTIC_RIGID_MOTION)) {
- if (!config->GetDeform_Mesh()) {
- surface_movement->Surface_Translating(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
- else {
- solver[MESH_0][MESH_SOL]->Surface_Translating(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
+ /*--- Apply rigid mesh transformation to entire grid first, if necessary ---*/
+ if (IntIter == 0) {
+ if (Kind_Grid_Movement == AEROELASTIC_RIGID_MOTION) {
- /*--- Deform the volume grid around the new boundary locations ---*/
- /*--- Set volume deformation if new elastic mesh solver is not used ---*/
- /*--- If Deform_Mesh true, the mesh deformation is handled by SetMesh_Deformation ---*/
- // To Do: What if multiple prescribed movements? E.g., Pitching + Plunging?
-
- if (rank == MASTER_NODE && !config->GetDeform_Mesh()) {
- cout << " Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
- }
+ if (rank == MASTER_NODE)
+ cout << endl << " Performing rigid mesh transformation." << endl;
- /*--- Plunging ---*/
+ /*--- Move each node in the volume mesh using the specified type
+ of rigid mesh motion. These routines also compute analytic grid
+ velocities for the fine mesh. ---*/
- /*--- Compute the new node locations for moving markers ---*/
+ grid_movement->Rigid_Translation(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Plunging(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Pitching(geometry[MESH_0], config, val_iZone, TimeIter);
+ grid_movement->Rigid_Rotation(geometry[MESH_0], config, val_iZone, TimeIter);
- if (!config->GetDeform_Mesh()) {
- surface_movement->Surface_Plunging(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
- else {
- solver[MESH_0][MESH_SOL]->Surface_Plunging(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
+ /*--- Update the multigrid structure after moving the finest grid,
+ including computing the grid velocities on the coarser levels. ---*/
- /*--- Deform the volume grid around the new boundary locations ---*/
- /*--- Set volume deformation if new elastic mesh solver is not used ---*/
- /*--- If Deform_Mesh true, the mesh deformation is handled by SetMesh_Deformation ---*/
- // To Do: What if multiple prescribed movements? E.g., Pitching + Plunging?
-
- if (rank == MASTER_NODE && !config->GetDeform_Mesh()) {
- cout << " Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
+ grid_movement->UpdateMultiGrid(geometry, config);
}
- /*--- Pitching ---*/
-
- /*--- Compute the new node locations for moving markers ---*/
-
- if (!config->GetDeform_Mesh()) {
- surface_movement->Surface_Pitching(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
- else {
- solver[MESH_0][MESH_SOL]->Surface_Pitching(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
+ }
- /*--- Deform the volume grid around the new boundary locations ---*/
- /*--- Set volume deformation if new elastic mesh solver is not used ---*/
- /*--- If Deform_Mesh true, the mesh deformation is handled by SetMesh_Deformation ---*/
- // To Do: What if multiple prescribed movements? E.g., Pitching + Plunging?
-
- if (rank == MASTER_NODE && !config->GetDeform_Mesh()) {
- cout << " Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
- }
+ /*--- Use the if statement to move the grid only at selected dual time step iterations. ---*/
+ else if (IntIter % config->GetAeroelasticIter() == 0) {
- /*--- Rotating ---*/
+ if (rank == MASTER_NODE)
+ cout << endl << " Solving aeroelastic equations and updating surface positions." << endl;
- /*--- Compute the new node locations for moving markers ---*/
+ /*--- Solve the aeroelastic equations for the new node locations of the moving markers(surfaces) ---*/
- if (!config->GetDeform_Mesh()) {
- surface_movement->Surface_Rotating(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
- else {
- solver[MESH_0][MESH_SOL]->Surface_Rotating(geometry[MESH_0],
- config, TimeIter, val_iZone);
- }
+ solver[MESH_0][FLOW_SOL]->Aeroelastic(surface_movement, geometry[MESH_0], config, TimeIter);
/*--- Deform the volume grid around the new boundary locations ---*/
- /*--- Set volume deformation if new elastic mesh solver is not used ---*/
- /*--- If Deform_Mesh true, the mesh deformation is handled by SetMesh_Deformation ---*/
- // To Do: What if multiple prescribed movements? E.g., Pitching + Plunging?
- if (rank == MASTER_NODE && !config->GetDeform_Mesh()) {
- cout << " Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
- }
+
+ if (rank == MASTER_NODE)
+ cout << " Deforming the volume grid due to the aeroelastic movement." << endl;
+ grid_movement->SetVolume_Deformation(geometry[MESH_0], config, true);
/*--- Update the grid velocities on the fine mesh using finite
differencing based on node coordinates at previous times. ---*/
- if (!adjoint) {
- if (rank == MASTER_NODE)
- cout << " Computing grid velocities by finite differencing." << endl;
- geometry[MESH_0]->SetGridVelocity(config, TimeIter);
- }
+ if (rank == MASTER_NODE)
+ cout << " Computing grid velocities by finite differencing." << endl;
+ geometry[MESH_0]->SetGridVelocity(config, TimeIter);
/*--- Update the multigrid structure after moving the finest grid,
including computing the grid velocities on the coarser levels. ---*/
grid_movement->UpdateMultiGrid(geometry, config);
+ }
- }
-
- if (config->GetSurface_Movement(AEROELASTIC)
- || config->GetSurface_Movement(AEROELASTIC_RIGID_MOTION)){
-
- /*--- Apply rigid mesh transformation to entire grid first, if necessary ---*/
- if (IntIter == 0) {
- if (Kind_Grid_Movement == AEROELASTIC_RIGID_MOTION) {
-
- if (rank == MASTER_NODE) {
- cout << endl << " Performing rigid mesh transformation." << endl;
- }
-
- /*--- Move each node in the volume mesh using the specified type
- of rigid mesh motion. These routines also compute analytic grid
- velocities for the fine mesh. ---*/
-
- grid_movement->Rigid_Translation(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Plunging(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Pitching(geometry[MESH_0],
- config, val_iZone, TimeIter);
- grid_movement->Rigid_Rotation(geometry[MESH_0],
- config, val_iZone, TimeIter);
-
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
-
- grid_movement->UpdateMultiGrid(geometry, config);
- }
-
- }
-
- /*--- Use the if statement to move the grid only at selected dual time step iterations. ---*/
- else if (IntIter % config->GetAeroelasticIter() == 0) {
-
- if (rank == MASTER_NODE)
- cout << endl << " Solving aeroelastic equations and updating surface positions." << endl;
-
- /*--- Solve the aeroelastic equations for the new node locations of the moving markers(surfaces) ---*/
-
- solver[MESH_0][FLOW_SOL]->Aeroelastic(surface_movement, geometry[MESH_0], config, TimeIter);
-
- /*--- Deform the volume grid around the new boundary locations ---*/
-
- if (rank == MASTER_NODE)
- cout << " Deforming the volume grid due to the aeroelastic movement." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
-
- /*--- Update the grid velocities on the fine mesh using finite
- differencing based on node coordinates at previous times. ---*/
+ }
- if (rank == MASTER_NODE)
- cout << " Computing grid velocities by finite differencing." << endl;
- geometry[MESH_0]->SetGridVelocity(config, TimeIter);
+ if (config->GetSurface_Movement(FLUID_STRUCTURE)) {
+ if (rank == MASTER_NODE && Screen_Output)
+ cout << endl << "Deforming the grid for Fluid-Structure Interaction applications." << endl;
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
+ /*--- Deform the volume grid around the new boundary locations ---*/
- grid_movement->UpdateMultiGrid(geometry, config);
- }
- }
- if (config->GetSurface_Movement(FLUID_STRUCTURE)){
- if (rank == MASTER_NODE && Screen_Output)
- cout << endl << "Deforming the grid for Fluid-Structure Interaction applications." << endl;
+ if (rank == MASTER_NODE && Screen_Output)
+ cout << "Deforming the volume grid." << endl;
+ grid_movement->SetVolume_Deformation(geometry[MESH_0], config, true, false);
- /*--- Deform the volume grid around the new boundary locations ---*/
+ nIterMesh = grid_movement->Get_nIterMesh();
+ stat_mesh = (nIterMesh == 0);
+ if (!adjoint && !stat_mesh) {
if (rank == MASTER_NODE && Screen_Output)
- cout << "Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true, false);
-
- nIterMesh = grid_movement->Get_nIterMesh();
- stat_mesh = (nIterMesh == 0);
-
- if (!adjoint && !stat_mesh) {
+ cout << "Computing grid velocities by finite differencing." << endl;
+ geometry[MESH_0]->SetGridVelocity(config, TimeIter);
+ }
+ else if (stat_mesh) {
if (rank == MASTER_NODE && Screen_Output)
- cout << "Computing grid velocities by finite differencing." << endl;
- geometry[MESH_0]->SetGridVelocity(config, TimeIter);
- }
- else if (stat_mesh) {
- if (rank == MASTER_NODE && Screen_Output)
- cout << "The mesh is up-to-date. Using previously stored grid velocities." << endl;
- }
+ cout << "The mesh is up-to-date. Using previously stored grid velocities." << endl;
+ }
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
+ /*--- Update the multigrid structure after moving the finest grid,
+ including computing the grid velocities on the coarser levels. ---*/
- grid_movement->UpdateMultiGrid(geometry, config);
+ grid_movement->UpdateMultiGrid(geometry, config);
}
- if (config->GetSurface_Movement(FLUID_STRUCTURE_STATIC)){
-
- if ((rank == MASTER_NODE) && (!discrete_adjoint) && Screen_Output)
- cout << endl << "Deforming the grid for static Fluid-Structure Interaction applications." << endl;
-
- /*--- Deform the volume grid around the new boundary locations ---*/
- if ((rank == MASTER_NODE) && (!discrete_adjoint)&& Screen_Output)
- cout << "Deforming the volume grid." << endl;
+ if (config->GetSurface_Movement(EXTERNAL) ||
+ config->GetSurface_Movement(EXTERNAL_ROTATION)) {
- grid_movement->SetVolume_Deformation_Elas(geometry[MESH_0], config, true, false);
-
- if ((rank == MASTER_NODE) && (!discrete_adjoint)&& Screen_Output)
- cout << "There is no grid velocity." << endl;
-
- /*--- Update the multigrid structure after moving the finest grid,
- including computing the grid velocities on the coarser levels. ---*/
-
- grid_movement->UpdateMultiGrid(geometry, config);
-
- }
- if (config->GetSurface_Movement(EXTERNAL) || config->GetSurface_Movement(EXTERNAL_ROTATION)){
/*--- Apply rigid rotation to entire grid first, if necessary ---*/
if (Kind_Grid_Movement == EXTERNAL_ROTATION) {
if (rank == MASTER_NODE)
cout << " Updating node locations by rigid rotation." << endl;
- grid_movement->Rigid_Rotation(geometry[MESH_0],
- config, val_iZone, TimeIter);
+ grid_movement->Rigid_Rotation(geometry[MESH_0], config, val_iZone, TimeIter);
}
/*--- Load new surface node locations from external files ---*/
- if (rank == MASTER_NODE)
+ if (rank == MASTER_NODE)
cout << " Updating surface locations from file." << endl;
- surface_movement->SetExternal_Deformation(geometry[MESH_0],
- config, val_iZone, TimeIter);
+ surface_movement->SetExternal_Deformation(geometry[MESH_0], config, val_iZone, TimeIter);
/*--- Deform the volume grid around the new boundary locations ---*/
if (rank == MASTER_NODE)
cout << " Deforming the volume grid." << endl;
- grid_movement->SetVolume_Deformation(geometry[MESH_0],
- config, true);
+ grid_movement->SetVolume_Deformation(geometry[MESH_0], config, true);
/*--- Update the grid velocities on the fine mesh using finite
differencing based on node coordinates at previous times. ---*/
@@ -356,7 +210,7 @@ void CIteration::SetGrid_Movement(CGeometry **geometry,
if (rank == MASTER_NODE)
cout << " Computing grid velocities by finite differencing." << endl;
geometry[MESH_0]->SetGridVelocity(config, TimeIter);
- }
+ }
/*--- Update the multigrid structure after moving the finest grid,
including computing the grid velocities on the coarser levels. ---*/
@@ -364,6 +218,7 @@ void CIteration::SetGrid_Movement(CGeometry **geometry,
grid_movement->UpdateMultiGrid(geometry, config);
}
+
}
void CIteration::SetMesh_Deformation(CGeometry **geometry,
@@ -372,35 +227,30 @@ void CIteration::SetMesh_Deformation(CGeometry **geometry,
CConfig *config,
unsigned short kind_recording) {
- bool ActiveTape = NO;
+ if (!config->GetDeform_Mesh()) return;
/*--- Perform the elasticity mesh movement ---*/
- if (config->GetDeform_Mesh()) {
-
- if ((kind_recording != MESH_DEFORM) && !config->GetMultizone_Problem()) {
- /*--- In a primal run, AD::TapeActive returns a false ---*/
- /*--- In any other recordings, the tape is passive during the deformation ---*/
- ActiveTape = AD::TapeActive();
- AD::StopRecording();
- }
- /*--- Set the stiffness of each element mesh into the mesh numerics ---*/
+ bool ActiveTape = AD::TapeActive();
- solver[MESH_SOL]->SetMesh_Stiffness(geometry, numerics[MESH_SOL], config);
+ if ((kind_recording != MESH_DEFORM) && !config->GetMultizone_Problem()) {
+ /*--- In a primal run, AD::TapeActive returns a false ---*/
+ /*--- In any other recordings, the tape is passive during the deformation. ---*/
+ AD::StopRecording();
+ }
- /*--- Deform the volume grid around the new boundary locations ---*/
+ /*--- Set the stiffness of each element mesh into the mesh numerics ---*/
- solver[MESH_SOL]->DeformMesh(geometry, numerics[MESH_SOL], config);
+ solver[MESH_SOL]->SetMesh_Stiffness(geometry, numerics[MESH_SOL], config);
- if (ActiveTape) {
- /*--- Start recording if it was stopped ---*/
- AD::StartRecording();
- }
- }
+ /*--- Deform the volume grid around the new boundary locations ---*/
-}
+ solver[MESH_SOL]->DeformMesh(geometry, numerics[MESH_SOL], config);
+ /*--- Continue recording. ---*/
+ if (ActiveTape) AD::StartRecording();
+}
void CIteration::Preprocess(COutput *output,
CIntegration ****integration,
@@ -1351,17 +1201,16 @@ CFEAIteration::CFEAIteration(CConfig *config) : CIteration(config) { }
CFEAIteration::~CFEAIteration(void) { }
void CFEAIteration::Preprocess() { }
void CFEAIteration::Iterate(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst
- ) {
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst) {
su2double loadIncrement;
unsigned long IntIter = 0;
@@ -1370,227 +1219,176 @@ void CFEAIteration::Iterate(COutput *output,
unsigned long iIncrement;
unsigned long nIncrements = config[val_iZone]->GetNumberIncrements();
- bool nonlinear = (config[val_iZone]->GetGeometricConditions() == LARGE_DEFORMATIONS); // Geometrically non-linear problems
- bool linear = (config[val_iZone]->GetGeometricConditions() == SMALL_DEFORMATIONS); // Geometrically non-linear problems
-
+ bool nonlinear = (config[val_iZone]->GetGeometricConditions() == LARGE_DEFORMATIONS);
+ bool linear = (config[val_iZone]->GetGeometricConditions() == SMALL_DEFORMATIONS);
bool disc_adj_fem = (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM);
+ bool incremental_load = config[val_iZone]->GetIncrementalLoad(); // Loads applied in steps
- bool incremental_load = config[val_iZone]->GetIncrementalLoad(); // If an incremental load is applied
-
- /*--- This is to prevent problems when running a linear solver ---*/
- if (!nonlinear) incremental_load = false;
+ CIntegration* feaIntegration = integration[val_iZone][val_iInst][FEA_SOL];
+ CSolver* feaSolver = solver[val_iZone][val_iInst][MESH_0][FEA_SOL];
/*--- Set the convergence monitor to false, to prevent the solver to stop in intermediate FSI subiterations ---*/
- integration[val_iZone][val_iInst][FEA_SOL]->SetConvergence(false);
+ feaIntegration->SetConvergence(false);
+
+ /*--- FEA equations ---*/
+ config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
if (linear) {
config[val_iZone]->SetInnerIter(0);
- /*--- FEA equations ---*/
-
- config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
-
/*--- Run the iteration ---*/
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ feaIntegration->Structural_Iteration(geometry, solver, numerics, config,
+ RUNTIME_FEA_SYS, val_iZone, val_iInst);
- if (!disc_adj_fem){
- Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ if (!disc_adj_fem) {
+ Monitor(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
/*--- Set the convergence monitor to true, to prevent the solver to stop in intermediate FSI subiterations ---*/
output->SetConvergence(true);
}
}
- /*--- If the structure is held static and the solver is nonlinear, we don't need to solve for static time, but we need to compute Mass Matrix and Integration constants ---*/
- else if (nonlinear) {
+ else if (nonlinear && !incremental_load) {
/*--- THIS IS THE DIRECT APPROACH (NO INCREMENTAL LOAD APPLIED) ---*/
- if (!incremental_load) {
-
- /*--- Keep the current inner iter, we need to restore it in discrete adjoint cases as file output depends on it ---*/
- unsigned long CurIter = config[val_iZone]->GetInnerIter();
-
- IntIter = 0;
- config[val_iZone]->SetInnerIter(IntIter);
-
- /*--- FEA equations ---*/
-
- config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
-
- /*--- Run the iteration ---*/
-
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ /*--- Keep the current inner iter, we need to restore it in discrete adjoint cases as file output depends on it ---*/
+ const auto CurIter = config[val_iZone]->GetInnerIter();
- if (!disc_adj_fem)
- Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ /*--- Newton-Raphson subiterations ---*/
- /*----------------- If the solver is non-linear, we need to subiterate using a Newton-Raphson approach ----------------------*/
-
- for (IntIter = 1; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
-
- /*--- Limit to only one iteration for the discrete adjoint recording, restore inner iter (see above) ---*/
- if (disc_adj_fem) {
- config[val_iZone]->SetInnerIter(CurIter);
- break;
- }
-
- config[val_iZone]->SetInnerIter(IntIter);
-
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
-
- StopCalc = Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ for (IntIter = 0; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
+ config[val_iZone]->SetInnerIter(IntIter);
- if (StopCalc) break;
+ feaIntegration->Structural_Iteration(geometry, solver, numerics, config,
+ RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ /*--- Limit to only one iteration for the discrete adjoint recording, restore inner iter (see above) ---*/
+ if (disc_adj_fem) {
+ config[val_iZone]->SetInnerIter(CurIter);
+ break;
}
+ else {
+ StopCalc = Monitor(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ if (StopCalc && (IntIter > 0)) break;
+ }
}
- /*--- The incremental load is only used in nonlinear cases ---*/
- else if (incremental_load) {
- /*--- Set the initial condition: store the current solution as Solution_Old ---*/
-
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->SetInitialCondition(geometry[val_iZone][val_iInst], solver[val_iZone][val_iInst], config[val_iZone], TimeIter);
-
- /*--- The load increment is 1.0 ---*/
+ }
+ else {
- loadIncrement = 1.0;
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->SetLoad_Increment(loadIncrement);
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->SetForceCoeff(loadIncrement);
+ /*--- THIS IS THE INCREMENTAL LOAD APPROACH (only makes sense for nonlinear) ---*/
- /*--- Set the value of the internal iteration ---*/
+ /*--- Set the initial condition: store the current solution as Solution_Old ---*/
- IntIter = 0;
- config[val_iZone]->SetInnerIter(IntIter);
+ feaSolver->SetInitialCondition(geometry[val_iZone][val_iInst],
+ solver[val_iZone][val_iInst], config[val_iZone], TimeIter);
- /*--- FEA equations ---*/
+ /*--- Assume the initial load increment as 1.0 ---*/
- config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
+ loadIncrement = 1.0;
+ feaSolver->SetLoad_Increment(loadIncrement);
+ feaSolver->SetForceCoeff(loadIncrement);
- /*--- Run the first iteration ---*/
+ /*--- Run two nonlinear iterations to check if incremental loading can be skipped ---*/
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ for (IntIter = 0; IntIter < 2; ++IntIter) {
- /*--- Write the convergence history (first, compute Von Mises stress) ---*/
+ config[val_iZone]->SetInnerIter(IntIter);
- Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ /*--- Run the first iteration ---*/
- /*--- Run the second iteration ---*/
+ feaIntegration->Structural_Iteration(geometry, solver, numerics, config,
+ RUNTIME_FEA_SYS, val_iZone, val_iInst);
- IntIter = 1;
- config[val_iZone]->SetInnerIter(IntIter);
+ /*--- Write the convergence history (first computes Von Mises stress) ---*/
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ Monitor(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ }
- /*--- Write the convergence history (first, compute Von Mises stress) ---*/
- Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ bool meetCriteria;
+ su2double Residual_UTOL, Residual_RTOL, Residual_ETOL;
+ su2double Criteria_UTOL, Criteria_RTOL, Criteria_ETOL;
- bool meetCriteria;
- su2double Residual_UTOL, Residual_RTOL, Residual_ETOL;
- su2double Criteria_UTOL, Criteria_RTOL, Criteria_ETOL;
+ Criteria_UTOL = config[val_iZone]->GetIncLoad_Criteria(0);
+ Criteria_RTOL = config[val_iZone]->GetIncLoad_Criteria(1);
+ Criteria_ETOL = config[val_iZone]->GetIncLoad_Criteria(2);
- Criteria_UTOL = config[val_iZone]->GetIncLoad_Criteria(0);
- Criteria_RTOL = config[val_iZone]->GetIncLoad_Criteria(1);
- Criteria_ETOL = config[val_iZone]->GetIncLoad_Criteria(2);
+ Residual_UTOL = log10(feaSolver->LinSysSol.norm());
+ Residual_RTOL = log10(feaSolver->LinSysRes.norm());
+ Residual_ETOL = log10(feaSolver->LinSysSol.dot(feaSolver->LinSysRes));
- Residual_UTOL = log10(solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->LinSysSol.norm());
- Residual_RTOL = log10(solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->LinSysRes.norm());
- Residual_ETOL = log10(solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->LinSysSol.dot(
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->LinSysRes));
+ meetCriteria = ( ( Residual_UTOL < Criteria_UTOL ) &&
+ ( Residual_RTOL < Criteria_RTOL ) &&
+ ( Residual_ETOL < Criteria_ETOL ) );
- meetCriteria = ( ( Residual_UTOL < Criteria_UTOL ) &&
- ( Residual_RTOL < Criteria_RTOL ) &&
- ( Residual_ETOL < Criteria_ETOL ) );
+ /*--- If the criteria is met, i.e. the load is not "too big", continue the regular calculation ---*/
- /*--- If the criteria is met and the load is not "too big", do the regular calculation ---*/
- if (meetCriteria) {
+ if (meetCriteria) {
- for (IntIter = 2; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
+ /*--- Newton-Raphson subiterations ---*/
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
+ for (IntIter = 2; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
- /*--- Write the convergence history (first, compute Von Mises stress) ---*/
- StopCalc = Monitor(output, integration, geometry, solver, numerics, config,
- surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ config[val_iZone]->SetInnerIter(IntIter);
- if (StopCalc) break;
+ feaIntegration->Structural_Iteration(geometry, solver, numerics, config,
+ RUNTIME_FEA_SYS, val_iZone, val_iInst);
- }
+ StopCalc = Monitor(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+ if (StopCalc) break;
}
- /*--- If the criteria is not met, a whole set of subiterations for the different loads must be done ---*/
+ }
- else {
+ /*--- If the criteria is not met, a whole set of subiterations for the different loads must be done ---*/
- /*--- Here we have to restart the solution to the original one of the iteration ---*/
- /*--- Retrieve the Solution_Old as the current solution before subiterating ---*/
+ else {
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->ResetInitialCondition(geometry[val_iZone][val_iInst],
- solver[val_iZone][val_iInst], config[val_iZone], TimeIter);
+ /*--- Here we have to restore the solution to the one before testing the criteria ---*/
+ /*--- Retrieve the Solution_Old as the current solution before subiterating ---*/
- /*--- For the number of increments ---*/
- for (iIncrement = 0; iIncrement < nIncrements; iIncrement++) {
+ feaSolver->ResetInitialCondition(geometry[val_iZone][val_iInst],
+ solver[val_iZone][val_iInst], config[val_iZone], TimeIter);
- loadIncrement = (iIncrement + 1.0) * (1.0 / nIncrements);
+ /*--- For the number of increments ---*/
+ for (iIncrement = 0; iIncrement < nIncrements; iIncrement++) {
- /*--- Set the load increment and the initial condition, and output the parameters of UTOL, RTOL, ETOL for the previous iteration ---*/
+ /*--- Set the load increment and the initial condition, and output the
+ * parameters of UTOL, RTOL, ETOL for the previous iteration ---*/
- /*--- Set the convergence monitor to false, to force se solver to converge every subiteration ---*/
- output->SetConvergence(false);
+ loadIncrement = (iIncrement + 1.0) * (1.0 / nIncrements);
+ feaSolver->SetLoad_Increment(loadIncrement);
- /*--- FEA equations ---*/
+ /*--- Set the convergence monitor to false, to force the solver to converge every subiteration ---*/
+ output->SetConvergence(false);
- config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
+ if (rank == MASTER_NODE)
+ cout << "\nIncremental load: increment " << iIncrement + 1 << endl;
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->SetLoad_Increment(loadIncrement);
+ /*--- Newton-Raphson subiterations ---*/
- if (rank == MASTER_NODE) {
- cout << endl;
- cout << "Incremental load: increment " << iIncrement + 1 << endl;
- }
+ for (IntIter = 0; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
- /*--- Set the value of the internal iteration ---*/
- IntIter = 0;
config[val_iZone]->SetInnerIter(IntIter);
- /*--- FEA equations ---*/
+ feaIntegration->Structural_Iteration(geometry, solver, numerics, config,
+ RUNTIME_FEA_SYS, val_iZone, val_iInst);
- config[val_iZone]->SetGlobalParam(FEM_ELASTICITY, RUNTIME_FEA_SYS);
-
- /*--- Run the iteration ---*/
-
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
-
- Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
-
-
- /*----------------- If the solver is non-linear, we need to subiterate using a Newton-Raphson approach ----------------------*/
-
- for (IntIter = 1; IntIter < config[val_iZone]->GetnInner_Iter(); IntIter++) {
-
- config[val_iZone]->SetInnerIter(IntIter);
-
- integration[val_iZone][val_iInst][FEA_SOL]->Structural_Iteration(geometry, solver, numerics,
- config, RUNTIME_FEA_SYS, val_iZone, val_iInst);
-
- /*--- Write the convergence history (first, compute Von Mises stress) ---*/
- StopCalc = Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
-
- if (StopCalc) break;
+ /*--- Write the convergence history (first, compute Von Mises stress) ---*/
+ StopCalc = Monitor(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
- }
+ if (StopCalc && (IntIter > 0)) break;
}
@@ -1602,59 +1400,66 @@ void CFEAIteration::Iterate(COutput *output,
/*--- Finally, we need to compute the objective function, in case that we are running a discrete adjoint solver... ---*/
- switch (config[val_iZone]->GetKind_ObjFunc()){
+ switch (config[val_iZone]->GetKind_ObjFunc()) {
case REFERENCE_GEOMETRY:
- if ((config[val_iZone]->GetDV_FEA() == YOUNG_MODULUS) || (config[val_iZone]->GetDV_FEA() == DENSITY_VAL)){
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Stiffness_Penalty(geometry[val_iZone][val_iInst][MESH_0],solver[val_iZone][val_iInst][MESH_0],
- numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
+ if ((config[val_iZone]->GetDV_FEA() == YOUNG_MODULUS) || (config[val_iZone]->GetDV_FEA() == DENSITY_VAL)) {
+ feaSolver->Stiffness_Penalty(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0],
+ numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
}
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_OFRefGeom(geometry[val_iZone][val_iInst][MESH_0],solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
+ feaSolver->Compute_OFRefGeom(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
break;
case REFERENCE_NODE:
- if ((config[val_iZone]->GetDV_FEA() == YOUNG_MODULUS) || (config[val_iZone]->GetDV_FEA() == DENSITY_VAL)){
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Stiffness_Penalty(geometry[val_iZone][val_iInst][MESH_0],solver[val_iZone][val_iInst][MESH_0],
- numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
+ if ((config[val_iZone]->GetDV_FEA() == YOUNG_MODULUS) || (config[val_iZone]->GetDV_FEA() == DENSITY_VAL)) {
+ feaSolver->Stiffness_Penalty(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0],
+ numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
}
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_OFRefNode(geometry[val_iZone][val_iInst][MESH_0],solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
+ feaSolver->Compute_OFRefNode(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
break;
case VOLUME_FRACTION:
case TOPOL_DISCRETENESS:
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_OFVolFrac(geometry[val_iZone][val_iInst][MESH_0],solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
+ feaSolver->Compute_OFVolFrac(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
break;
case TOPOL_COMPLIANCE:
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_OFCompliance(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
+ feaSolver->Compute_OFCompliance(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
break;
}
}
void CFEAIteration::Update(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst) {
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst) {
su2double Physical_dt, Physical_t;
- unsigned long TimeIter = config[val_iZone]->GetTimeIter();
- bool dynamic = (config[val_iZone]->GetTime_Domain()); // Dynamic problems
- bool static_fem = (!config[val_iZone]->GetTime_Domain()); // Static problems
- bool fsi = config[val_iZone]->GetFSI_Simulation(); // Fluid-Structure Interaction problems
+ unsigned long TimeIter = config[val_iZone]->GetTimeIter();
+ bool dynamic = (config[val_iZone]->GetTime_Domain()); // Dynamic problems
+ bool fsi = config[val_iZone]->GetFSI_Simulation(); // Fluid-Structure Interaction problems
+
+ CSolver* feaSolver = solver[val_iZone][val_iInst][MESH_0][FEA_SOL];
/*----------------- Compute averaged nodal stress and reactions ------------------------*/
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_NodalStress(geometry[val_iZone][val_iInst][MESH_0], numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
+ feaSolver->Compute_NodalStress(geometry[val_iZone][val_iInst][MESH_0],
+ numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
/*----------------- Update structural solver ----------------------*/
if (dynamic) {
- integration[val_iZone][val_iInst][FEA_SOL]->SetStructural_Solver(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone], MESH_0);
+ integration[val_iZone][val_iInst][FEA_SOL]->SetStructural_Solver(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone], MESH_0);
integration[val_iZone][val_iInst][FEA_SOL]->SetConvergence(false);
/*--- Verify convergence criteria (based on total time) ---*/
@@ -1664,87 +1469,84 @@ void CFEAIteration::Update(COutput *output,
if (Physical_t >= config[val_iZone]->GetTotal_DynTime())
integration[val_iZone][val_iInst][FEA_SOL]->SetConvergence(true);
- } else if ( static_fem && fsi) {
+ } else if (fsi) {
/*--- For FSI problems, output the relaxed result, which is the one transferred into the fluid domain (for restart purposes) ---*/
- switch (config[val_iZone]->GetKind_TimeIntScheme_FEA()) {
- case (NEWMARK_IMPLICIT):
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->ImplicitNewmark_Relaxation(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
- break;
+ if (config[val_iZone]->GetKind_TimeIntScheme_FEA() == NEWMARK_IMPLICIT) {
+ feaSolver->ImplicitNewmark_Relaxation(geometry[val_iZone][val_iInst][MESH_0],
+ solver[val_iZone][val_iInst][MESH_0], config[val_iZone]);
}
}
}
void CFEAIteration::Predictor(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst) {
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst) {
+
+ CSolver* feaSolver = solver[val_iZone][val_iInst][MESH_0][FEA_SOL];
/*--- Predict displacements ---*/
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->PredictStruct_Displacement(geometry[val_iZone][val_iInst], config[val_iZone],
- solver[val_iZone][val_iInst]);
+ feaSolver->PredictStruct_Displacement(geometry[val_iZone][val_iInst], config[val_iZone], solver[val_iZone][val_iInst]);
/*--- For parallel simulations we need to communicate the predicted solution before updating the fluid mesh ---*/
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->InitiateComms(geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], SOLUTION_PRED);
- solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->CompleteComms(geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], SOLUTION_PRED);
+ feaSolver->InitiateComms(geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], SOLUTION_PRED);
+ feaSolver->CompleteComms(geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], SOLUTION_PRED);
}
void CFEAIteration::Relaxation(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst) {
-
- unsigned long OuterIter = config[val_iZone]->GetOuterIter();
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst) {
+
+ CSolver* feaSolver = solver[val_iZone][val_iInst][MESH_0][FEA_SOL];
/*-------------------- Aitken's relaxation ------------------------*/
/*------------------- Compute the coefficient ---------------------*/
- solver[val_iZone][INST_0][MESH_0][FEA_SOL]->ComputeAitken_Coefficient(geometry[val_iZone][INST_0], config[val_iZone],
- solver[val_iZone][INST_0], OuterIter);
+ feaSolver->ComputeAitken_Coefficient(geometry[val_iZone][INST_0], config[val_iZone],
+ solver[val_iZone][INST_0], config[val_iZone]->GetOuterIter());
/*----------------- Set the relaxation parameter ------------------*/
- solver[val_iZone][INST_0][MESH_0][FEA_SOL]->SetAitken_Relaxation(geometry[val_iZone][INST_0], config[val_iZone],
- solver[val_iZone][INST_0]);
+ feaSolver->SetAitken_Relaxation(geometry[val_iZone][INST_0], config[val_iZone], solver[val_iZone][INST_0]);
/*----------------- Communicate the predicted solution and the old one ------------------*/
- solver[val_iZone][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry[val_iZone][INST_0][MESH_0], config[val_iZone], SOLUTION_PRED_OLD);
- solver[val_iZone][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry[val_iZone][INST_0][MESH_0], config[val_iZone], SOLUTION_PRED_OLD);
+ feaSolver->InitiateComms(geometry[val_iZone][INST_0][MESH_0], config[val_iZone], SOLUTION_PRED_OLD);
+ feaSolver->CompleteComms(geometry[val_iZone][INST_0][MESH_0], config[val_iZone], SOLUTION_PRED_OLD);
}
bool CFEAIteration::Monitor(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst) {
-
- bool StopCalc = false;
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst) {
#ifndef HAVE_MPI
StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
@@ -1754,32 +1556,20 @@ bool CFEAIteration::Monitor(COutput *output,
UsedTime = StopTime - StartTime;
solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->Compute_NodalStress(geometry[val_iZone][val_iInst][MESH_0],
- numerics[val_iZone][val_iInst][MESH_0][FEA_SOL], config[val_iZone]);
+ numerics[val_iZone][val_iInst][MESH_0][FEA_SOL],
+ config[val_iZone]);
if (config[val_iZone]->GetMultizone_Problem() || config[val_iZone]->GetSinglezone_Driver()){
- output->SetHistory_Output(geometry[val_iZone][INST_0][MESH_0], solver[val_iZone][INST_0][MESH_0], config[val_iZone],
- config[val_iZone]->GetTimeIter(), config[val_iZone]->GetOuterIter(), config[val_iZone]->GetInnerIter());
+ output->SetHistory_Output(geometry[val_iZone][INST_0][MESH_0], solver[val_iZone][INST_0][MESH_0],
+ config[val_iZone], config[val_iZone]->GetTimeIter(),
+ config[val_iZone]->GetOuterIter(), config[val_iZone]->GetInnerIter());
}
- StopCalc = output->GetConvergence();
-
- return StopCalc;
+ return output->GetConvergence();
}
void CFEAIteration::Postprocess(COutput *output,
- CIntegration ****integration,
- CGeometry ****geometry,
- CSolver *****solver,
- CNumerics ******numerics,
- CConfig **config,
- CSurfaceMovement **surface_movement,
- CVolumetricMovement ***grid_movement,
- CFreeFormDefBox*** FFDBox,
- unsigned short val_iZone,
- unsigned short val_iInst) { }
-
-void CFEAIteration::Solve(COutput *output,
CIntegration ****integration,
CGeometry ****geometry,
CSolver *****solver,
@@ -1789,14 +1579,24 @@ void CFEAIteration::Solve(COutput *output,
CVolumetricMovement ***grid_movement,
CFreeFormDefBox*** FFDBox,
unsigned short val_iZone,
- unsigned short val_iInst
- ) {
+ unsigned short val_iInst) { }
- /*------------------ Structural subiteration ----------------------*/
- Iterate(output, integration, geometry,
- solver, numerics, config,
- surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
+void CFEAIteration::Solve(COutput *output,
+ CIntegration ****integration,
+ CGeometry ****geometry,
+ CSolver *****solver,
+ CNumerics ******numerics,
+ CConfig **config,
+ CSurfaceMovement **surface_movement,
+ CVolumetricMovement ***grid_movement,
+ CFreeFormDefBox*** FFDBox,
+ unsigned short val_iZone,
+ unsigned short val_iInst
+ ) {
+ /*------------------ Structural subiteration ----------------------*/
+ Iterate(output, integration, geometry, solver, numerics, config,
+ surface_movement, grid_movement, FFDBox, val_iZone, INST_0);
/*--- Write the convergence history for the structure (only screen output) ---*/
// if (multizone) output->SetConvHistory_Body(geometry, solver, config, integration, false, 0.0, val_iZone, INST_0);
diff --git a/SU2_CFD/src/meson.build b/SU2_CFD/src/meson.build
index 20efb35eea45..b45bf0ebda1c 100644
--- a/SU2_CFD/src/meson.build
+++ b/SU2_CFD/src/meson.build
@@ -131,9 +131,7 @@ su2_cfd_src += files(['interfaces/CInterface.cpp',
'interfaces/cht/CConjugateHeatInterface.cpp',
'interfaces/fsi/CDisplacementsInterface.cpp',
'interfaces/fsi/CFlowTractionInterface.cpp',
- 'interfaces/fsi/CDiscAdjFlowTractionInterface.cpp',
- 'interfaces/fsi/CDisplacementsInterfaceLegacy.cpp',
- 'interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.cpp'])
+ 'interfaces/fsi/CDiscAdjFlowTractionInterface.cpp'])
su2_cfd_src += files(['drivers/CDriver.cpp',
'drivers/CMultizoneDriver.cpp',
diff --git a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp
index 4a13c1483f49..29c5b380c094 100644
--- a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp
+++ b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp
@@ -366,7 +366,6 @@ CFEAMeshElasticity::CFEAMeshElasticity(unsigned short val_nDim, unsigned short v
case INVERSE_VOLUME:
case SOLID_WALL_DISTANCE:
element_based = true;
- Nu = config->GetDeform_Coeff();
break;
case CONSTANT_STIFFNESS:
element_based = false;
diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp
index d52ade6b9124..1d64d91625b1 100644
--- a/SU2_CFD/src/output/CFlowCompOutput.cpp
+++ b/SU2_CFD/src/output/CFlowCompOutput.cpp
@@ -58,6 +58,7 @@ CFlowCompOutput::CFlowCompOutput(CConfig *config, unsigned short nDim) : CFlowOu
requestedVolumeFields.emplace_back("COORDINATES");
requestedVolumeFields.emplace_back("SOLUTION");
requestedVolumeFields.emplace_back("PRIMITIVE");
+ if (config->GetGrid_Movement()) requestedVolumeFields.emplace_back("GRID_VELOCITY");
nRequestedVolumeFields = requestedVolumeFields.size();
}
diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp
index 64dd61c090d8..b631a6a20b65 100644
--- a/SU2_CFD/src/output/CFlowIncOutput.cpp
+++ b/SU2_CFD/src/output/CFlowIncOutput.cpp
@@ -60,6 +60,7 @@ CFlowIncOutput::CFlowIncOutput(CConfig *config, unsigned short nDim) : CFlowOutp
requestedVolumeFields.emplace_back("COORDINATES");
requestedVolumeFields.emplace_back("SOLUTION");
requestedVolumeFields.emplace_back("PRIMITIVE");
+ if (config->GetGrid_Movement()) requestedVolumeFields.emplace_back("GRID_VELOCITY");
nRequestedVolumeFields = requestedVolumeFields.size();
}
diff --git a/SU2_CFD/src/output/output_structure_legacy.cpp b/SU2_CFD/src/output/output_structure_legacy.cpp
index 996c8def10e8..c3427fb4e23c 100644
--- a/SU2_CFD/src/output/output_structure_legacy.cpp
+++ b/SU2_CFD/src/output/output_structure_legacy.cpp
@@ -3661,64 +3661,6 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver
}
}
- if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())) {
- /*--- Loop over this partition to collect the current variable ---*/
-
- jPoint = 0;
- for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
-
- /*--- Check for halos & write only if requested ---*/
-
- if (!Local_Halo[iPoint] || Wrt_Halo) {
-
- /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
-
- Buffer_Send_Var[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 0);
- Buffer_Send_Res[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 1);
- if (geometry->GetnDim() == 3)
- Buffer_Send_Vol[jPoint] = solver[ADJFEA_SOL]->GetNodes()->GetGeometry_CrossTerm_Derivative(iPoint, 2);
- jPoint++;
- }
- }
-
- /*--- Gather the data on the master node. ---*/
-
-#ifdef HAVE_MPI
- SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
- SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
- if (nDim == 3)
- SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
-#else
- for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
- for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
- if (nDim == 3)
- for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
-#endif
-
- /*--- The master node unpacks and sorts this variable by global index ---*/
-
- if (rank == MASTER_NODE) {
- jPoint = 0; iVar = iVar_FEA_Extra;
- for (iProcessor = 0; iProcessor < size; iProcessor++) {
- for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
-
- /*--- Get global index, then loop over each variable and store ---*/
-
- iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
- Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
- Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
- if (nDim == 3)
- Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
- jPoint++;
- }
-
- /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
-
- jPoint = (iProcessor+1)*nBuffer_Scalar;
- }
- }
- }
-
if (config->GetExtraOutput()) {
for (jVar = 0; jVar < nVar_Extra; jVar++) {
@@ -11210,313 +11152,6 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr
}
-void COutputLegacy::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container,
- CConfig **config, CIntegration ****integration, unsigned long iExtIter,
- unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header) {
-
- int rank = MASTER_NODE;
-#ifdef HAVE_MPI
- MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-#endif
-
- /*--- Output only using the Master Node ---*/
-
- if ((rank == MASTER_NODE) && (header)){
-
- char cstr[200], buffer[50], turb_resid[1000];
- string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff;
-
- bool turbulent = ((config[ZONE_FLOW]->GetKind_Solver() == RANS) || (config[ZONE_FLOW]->GetKind_Solver() == ADJ_RANS) ||
- (config[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS));
-
- unsigned short direct_diff = config[ZONE_FLOW]->GetDirectDiff();
-
- /*--- Write file name with extension ---*/
-// string filename = config[ZONE_FLOW]->GetConv_FileName_FSI();
-// strcpy (cstr, filename.data());
-
- if (config[ZONE_FLOW]->GetTime_Domain() && config[ZONE_FLOW]->GetRestart()) {
- long iExtIter = config[ZONE_FLOW]->GetRestart_Iter();
- if (SU2_TYPE::Int(iExtIter) < 10) SPRINTF (buffer, "_0000%d", SU2_TYPE::Int(iExtIter));
- if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d", SU2_TYPE::Int(iExtIter));
- if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d", SU2_TYPE::Int(iExtIter));
- if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d", SU2_TYPE::Int(iExtIter));
- if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d", SU2_TYPE::Int(iExtIter));
- strcat(cstr, buffer);
- }
-
- if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TAB_TECPLOT)) SPRINTF (buffer, ".dat");
- else if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TAB_CSV)) SPRINTF (buffer, ".vtk");
- strcat(cstr, buffer);
-
- FSIHist_file->open(cstr, ios::out);
- FSIHist_file->precision(15);
-
- /*--- Begin of the header ---*/
-
- char begin[]= "\"ExtIter\",\"BGSIter\"";
-
- /*--- Header for the coefficients ---*/
-
- char flow_coeff[]= ",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\",\"CL/CD\"";
- char fem_coeff[]= ",\"VM_Stress\"";
- char of_1[] = ",\"TgtGeom\"";
- char of_2[] = ",\"TgtNode\"";
-
- char d_flow_coeff[] = ",\"D(CL)\",\"D(CD)\",\"D(CSF)\",\"D(CMx)\",\"D(CMy)\",\"D(CMz)\",\"D(CFx)\",\"D(CFy)\",\"D(CFz)\",\"D(CL/CD)\",\"D(Custom_ObjFunc)\"";
-
- /*--- Header for the residuals ---*/
-
- char fsi_resid[]= ",\"Res_FSI\",\"RelaxCoeff\",\"ForceCoeff\"";
-
- char flow_resid[]= ",\"Res_BGS[F0]\",\"Res_BGS[F1]\",\"Res_BGS[F2]\",\"Res_BGS[F3]\",\"Res_BGS[F4]\"";
- char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\"";
- char fem_resid[]= ",\"Res_BGS[S0]\",\"Res_BGS[S1]\",\"Res_BGS[S2]\"";
-
- /*--- End of the header ---*/
-
- char end[]= ",\"Time(min)\"\n";
-
- if ((config[ZONE_FLOW]->GetTabular_FileFormat() == TECPLOT) ||
- (config[ZONE_FLOW]->GetTabular_FileFormat() == TECPLOT_BINARY)) {
- FSIHist_file[0] << "TITLE = \"SU2 FSI Simulation\"" << endl;
- FSIHist_file[0] << "VARIABLES = ";
- }
-
- /*--- Write the header, case depending ---*/
-
- FSIHist_file[0] << begin;
-
- FSIHist_file[0] << fsi_resid;
-
- switch (config[ZONE_FLOW]->GetKind_Solver()) {
-
- /*--- Flow residual output ---*/
-
- case EULER : case NAVIER_STOKES: case RANS :
- case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS :
- FSIHist_file[0] << flow_resid;
- if (turbulent) FSIHist_file[0] << turb_resid;
- break;
-
- case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
- case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS:
- FSIHist_file[0] << adj_flow_resid;
- break;
-
- }
-
- /*--- FEA residual output ---*/
-
- switch (config[ZONE_STRUCT]->GetKind_Solver()) {
-
- case FEM_ELASTICITY:
- FSIHist_file[0] << fem_resid;
- break;
-
- case DISC_ADJ_FEM:
- FSIHist_file[0] << fem_resid ;
- break;
-
- }
-
- /*--- Flow coefficients output ---*/
- switch (config[ZONE_FLOW]->GetKind_Solver()) {
-
- case EULER : case NAVIER_STOKES: case RANS :
- case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS :
- FSIHist_file[0] << flow_coeff;
- if (turbulent) FSIHist_file[0] << turb_resid;
- if (direct_diff != NO_DERIVATIVE) {
- FSIHist_file[0] << d_flow_coeff;
- }
- break;
-
- case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
- case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS:
- FSIHist_file[0] << adj_flow_resid;
- break;
-
- }
-
- switch (config[ZONE_STRUCT]->GetKind_Solver()) {
-
- case FEM_ELASTICITY:
- FSIHist_file[0] << fem_coeff;
- break;
-
- case DISC_ADJ_FEM:
- FSIHist_file[0] << fem_coeff;
- break;
-
- }
-
- switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
- case REFERENCE_GEOMETRY:
- FSIHist_file[0] << of_1;
- break;
- case REFERENCE_NODE:
- FSIHist_file[0] << of_2;
- break;
- default:
- break;
- }
-
- FSIHist_file[0] << end;
-
-
- }
-
- if ((rank == MASTER_NODE) && (!header)){
-
- unsigned short nDim = geometry[ZONE_STRUCT][INST_0][MESH_0]->GetnDim();
-
- unsigned long iExtIter = config[ZONE_STRUCT]->GetInnerIter();
- unsigned long ExtIter_OffSet = config[ZONE_STRUCT]->GetExtIter_OffSet();
- unsigned long iOuterIter = config[ZONE_STRUCT]->GetOuterIter();
- su2double dummy = 0.0;
-
- bool first_iter = ((iExtIter==0) && (iOuterIter == 0));
-
-
- bool compressible = (config[ZONE_FLOW]->GetKind_Regime() == COMPRESSIBLE);
- bool incompressible = (config[ZONE_FLOW]->GetKind_Regime() == INCOMPRESSIBLE);
-
-
- bool fem = ((config[ZONE_STRUCT]->GetKind_Solver() == FEM_ELASTICITY) ||
- (config[ZONE_STRUCT]->GetKind_Solver() == DISC_ADJ_FEM));
- bool linear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == SMALL_DEFORMATIONS);
- bool nonlinear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == LARGE_DEFORMATIONS);
-
- bool disc_adj_flow = config[ZONE_FLOW]->GetDiscrete_Adjoint();
- bool disc_adj_fem = config[ZONE_STRUCT]->GetDiscrete_Adjoint();
-
-
- /*--- WARNING: These buffers have hard-coded lengths. Note that you
- may have to adjust them to be larger if adding more entries. ---*/
-
- char begin[1000], direct_coeff[1000],
- fsi_resid[1000], fsi_coeffs[1000],
- flow_resid[1000], fem_resid[1000],
- objective_function[1000], end[1000];
-
- su2double *residual_flow = NULL;
- su2double *residual_fem = NULL;
- su2double *residual_fsi = NULL;
- su2double *coeffs_fsi = NULL;
-
- /*--- Initialize number of variables ---*/
- unsigned short nVar_FSI = 1, nCoeff_FSI = 2, nVar_Flow = 0, nVar_FEM = 0;
-
- unsigned short iVar;
-
- /*--- Direct problem variables ---*/
- if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+1;
-
- if (fem) {
- if (linear_analysis) nVar_FEM = nDim;
- if (nonlinear_analysis) nVar_FEM = 3;
- if (disc_adj_fem) nVar_FEM = nDim;
- }
-
- residual_flow = new su2double[nVar_Flow];
- residual_fem = new su2double[nVar_FEM];
- residual_fsi = new su2double[nVar_FSI];
- coeffs_fsi = new su2double[nCoeff_FSI];
-
- /*--- Initialize variables to store information from all domains (direct solution) ---*/
-
- su2double Total_CL = 0.0, Total_CD = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
- Total_OF = 0.0;
-
- Total_CL = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL();
- Total_CD = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD();
- Total_CEff = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CEff();
- Total_CMx = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMx();
- Total_CMy = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMy();
- Total_CMz = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMz();
-
- bool print_of = false;
-
- switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
- case REFERENCE_GEOMETRY:
- Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefGeom();
- print_of = true;
- break;
- case REFERENCE_NODE:
- Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefNode();
- print_of = true;
- break;
- default:
- break;
- }
-
- if ((!disc_adj_flow) && (!disc_adj_fem)){
- /*--- Flow Residuals ---*/
- for (iVar = 0; iVar < nVar_Flow; iVar++)
- residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetRes_BGS(iVar);
-
- /*--- FEA Residuals ---*/
- for (iVar = 0; iVar < nVar_FEM; iVar++)
- residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_BGS(iVar);
-
- residual_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetFSI_Residual();
- coeffs_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRelaxCoeff();
- coeffs_fsi[1] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetForceCoeff();
-
- }
- else{
- /*--- Flow Residuals ---*/
- for (iVar = 0; iVar < nVar_Flow; iVar++)
- residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_BGS(iVar);
- /*--- FEA Residuals ---*/
- for (iVar = 0; iVar < nVar_FEM; iVar++)
- residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_BGS(iVar);
- }
-
- /*--- Write the begining of the history file ---*/
- SPRINTF(begin, "%12d, %12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet), SU2_TYPE::Int(iOuterIter));
- /*--- Write the end of the history file ---*/
- SPRINTF (end, "\n");
-
- SPRINTF (fsi_resid, ", %14.8e", log10 (residual_fsi[0]));
- SPRINTF (fsi_coeffs, ", %14.8e, %14.8e", coeffs_fsi[0], coeffs_fsi[1]);
-
- /*--- Flow residual ---*/
- if (nDim == 2) {
- if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
- if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), dummy, dummy);
- }
- else {
- if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) );
- if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
- }
-
- /*--- FEM residual ---*/
- if (nDim == 2) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy);
- else SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[1]));
-
- /*--- Direct coefficients ---*/
- SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",Total_CL, Total_CD, Total_CMx, Total_CMy, Total_CMz, Total_CEff);
-
- if (print_of) SPRINTF (objective_function, ", %14.8e", Total_OF);
-
- if (!first_iter){
- if (!print_of) FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << end;
- else FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << objective_function << end;
- FSIHist_file[0].flush();
- }
-
- delete [] residual_flow;
- delete [] residual_fem;
- delete [] residual_fsi;
- delete [] coeffs_fsi;
-
-
- }
-
-}
-
void COutputLegacy::SetSensitivity_Files(CGeometry ***geometry, CConfig **config, unsigned short val_nZone) {
unsigned short iMarker,iDim, nDim, iVar, nMarker, nVar;
diff --git a/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp b/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp
index 25c22d462745..6bf7e05d468a 100644
--- a/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp
+++ b/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp
@@ -741,7 +741,6 @@ void CDiscAdjFEASolver::ExtractAdjoint_Variables(CGeometry *geometry, CConfig *c
void CDiscAdjFEASolver::SetAdjoint_Output(CGeometry *geometry, CConfig *config){
bool dynamic = (config->GetTime_Domain());
- bool fsi = config->GetFSI_Simulation();
bool deform_mesh = (config->GetnMarker_Deform_Mesh() > 0);
unsigned short iVar;
@@ -751,21 +750,11 @@ void CDiscAdjFEASolver::SetAdjoint_Output(CGeometry *geometry, CConfig *config){
for (iVar = 0; iVar < nVar; iVar++){
Solution[iVar] = nodes->GetSolution(iPoint,iVar);
}
- if (fsi) {
- for (iVar = 0; iVar < nVar; iVar++){
- Solution[iVar] += nodes->GetGeometry_CrossTerm_Derivative(iPoint,iVar);
- }
- for (iVar = 0; iVar < nVar; iVar++){
- Solution[iVar] += nodes->GetCross_Term_Derivative(iPoint,iVar);
- }
- }
-
if(deform_mesh){
for (iVar = 0; iVar < nVar; iVar++){
Solution[iVar] += nodes->GetSourceTerm_DispAdjoint(iPoint,iVar);
}
}
-
if (dynamic){
for (iVar = 0; iVar < nVar; iVar++){
Solution_Accel[iVar] = nodes->GetSolution_Accel(iPoint,iVar);
@@ -815,47 +804,6 @@ void CDiscAdjFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_cont
}
-void CDiscAdjFEASolver::ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *config){
-
- unsigned short iVar;
- unsigned long iPoint;
-
- for (iPoint = 0; iPoint < nPoint; iPoint++){
-
- /*--- Extract the adjoint solution ---*/
-
- direct_solver->GetNodes()->GetAdjointSolution_LocalIndex(iPoint,Solution);
-
- for (iVar = 0; iVar < nVar; iVar++) nodes->SetCross_Term_Derivative(iPoint,iVar, Solution[iVar]);
-
- }
-
-}
-
-void CDiscAdjFEASolver::ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config){
-
- unsigned short iVar;
- unsigned long iPoint;
-
- su2double relax = config->GetAitkenStatRelax();
-
- for (iPoint = 0; iPoint < nPoint; iPoint++){
-
- /*--- Extract the adjoint solution ---*/
-
- direct_solver->GetNodes()->GetAdjointSolution_LocalIndex(iPoint,Solution);
-
- /*--- Relax and set the solution ---*/
-
- for(iVar = 0; iVar < nVar; iVar++)
- Solution[iVar] = relax*Solution[iVar] + (1.0-relax)*nodes->GetGeometry_CrossTerm_Derivative(iPoint,iVar);
-
- for (iVar = 0; iVar < nVar; iVar++) nodes->SetGeometry_CrossTerm_Derivative(iPoint,iVar, Solution[iVar]);
-
- }
-
-}
-
void CDiscAdjFEASolver::SetSensitivity(CGeometry *geometry, CSolver **solver, CConfig *config){
unsigned short iVar;
@@ -910,40 +858,6 @@ void CDiscAdjFEASolver::SetSurface_Sensitivity(CGeometry *geometry, CConfig *con
}
-void CDiscAdjFEASolver::ComputeResidual_Multizone(CGeometry *geometry, CConfig *config){
-
- unsigned short iVar;
- unsigned long iPoint;
- su2double residual, bgs_sol;
-
- /*--- Set Residuals to zero ---*/
-
- for (iVar = 0; iVar < nVar; iVar++){
- SetRes_BGS(iVar,0.0);
- SetRes_Max_BGS(iVar,0.0,0);
- }
-
- /*--- Compute the BGS solution (adding the cross term) ---*/
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- for (iVar = 0; iVar < nVar; iVar++){
- bgs_sol = nodes->GetSolution(iPoint, iVar) + nodes->GetGeometry_CrossTerm_Derivative(iPoint, iVar);
- nodes->Set_BGSSolution(iPoint,iVar, bgs_sol);
- }
- }
-
- /*--- Set the residuals ---*/
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- for (iVar = 0; iVar < nVar; iVar++){
- residual = nodes->Get_BGSSolution(iPoint, iVar) - nodes->Get_BGSSolution_k(iPoint, iVar);
- AddRes_BGS(iVar,residual*residual);
- AddRes_Max_BGS(iVar,fabs(residual),geometry->node[iPoint]->GetGlobalIndex(),geometry->node[iPoint]->GetCoord());
- }
- }
-
- SetResidual_BGS(geometry, config);
-
-}
-
void CDiscAdjFEASolver::ReadDV(CConfig *config) {
unsigned long index;
diff --git a/SU2_CFD/src/solvers/CDiscAdjMeshSolver.cpp b/SU2_CFD/src/solvers/CDiscAdjMeshSolver.cpp
index cab39bc108ea..9b920b1a6c48 100644
--- a/SU2_CFD/src/solvers/CDiscAdjMeshSolver.cpp
+++ b/SU2_CFD/src/solvers/CDiscAdjMeshSolver.cpp
@@ -239,39 +239,6 @@ void CDiscAdjMeshSolver::SetSensitivity(CGeometry *geometry, CSolver **solver, C
}
-void CDiscAdjMeshSolver::ComputeResidual_Multizone(CGeometry *geometry, CConfig *config){
-
- // ToDo: Can this be made generic to use the CSolver impl
-
- unsigned short iVar;
- unsigned long iPoint;
- su2double residual;
-
- /*--- Set Residuals to zero ---*/
-
- for (iVar = 0; iVar < nVar; iVar++){
- SetRes_BGS(iVar,0.0);
- SetRes_Max_BGS(iVar,0.0,0);
- }
-
- /*--- Set the residuals ---*/
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- /*--- Only for the boundary vertices ---*/
- if (nodes->Get_isVertex(iPoint)){
- for (iVar = 0; iVar < nVar; iVar++){
- /*--- Compute only for the sensitivities of the boundary displacements ---*/
- residual = nodes->GetBoundDisp_Sens(iPoint,iVar) - nodes->Get_BGSSolution_k(iPoint,iVar);
- AddRes_BGS(iVar,residual*residual);
- AddRes_Max_BGS(iVar,fabs(residual),geometry->node[iPoint]->GetGlobalIndex(),geometry->node[iPoint]->GetCoord());
- }
- }
- }
-
- SetResidual_BGS(geometry, config);
-
-}
-
void CDiscAdjMeshSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int val_iter, bool val_update_geo) {
}
-
diff --git a/SU2_CFD/src/solvers/CDiscAdjSolver.cpp b/SU2_CFD/src/solvers/CDiscAdjSolver.cpp
index a057aa9d15ca..6523ea691858 100644
--- a/SU2_CFD/src/solvers/CDiscAdjSolver.cpp
+++ b/SU2_CFD/src/solvers/CDiscAdjSolver.cpp
@@ -690,71 +690,10 @@ void CDiscAdjSolver::ExtractAdjoint_Geometry(CGeometry *geometry, CConfig *confi
// SetResidual_RMS(geometry, config);
}
-void CDiscAdjSolver::ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *config) {
-
- unsigned short iVar;
- unsigned long iPoint;
-
- for (iPoint = 0; iPoint < nPoint; iPoint++){
-
- /*--- Extract the adjoint solution ---*/
-
- direct_solver->GetNodes()->GetAdjointSolution_LocalIndex(iPoint,Solution);
-
- for (iVar = 0; iVar < nVar; iVar++) nodes->SetCross_Term_Derivative(iPoint,iVar, Solution[iVar]);
-
- }
-
-}
-
-void CDiscAdjSolver::ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config) {
-
- unsigned short iDim;
- unsigned long iPoint;
-
-
- for (iPoint = 0; iPoint < nPoint; iPoint++){
-
- /*--- Extract the adjoint solution ---*/
-
- if (config->GetMultizone_Problem())
- geometry->node[iPoint]->GetAdjointCoord_LocalIndex(Solution_Geometry);
- else
- geometry->node[iPoint]->GetAdjointCoord(Solution_Geometry);
-
- for (iDim = 0; iDim < nDim; iDim++) nodes->SetGeometry_CrossTerm_Derivative(iPoint,iDim, Solution_Geometry[iDim]);
-
- }
-
-}
-
-void CDiscAdjSolver::ExtractAdjoint_CrossTerm_Geometry_Flow(CGeometry *geometry, CConfig *config){
-
- unsigned short iDim;
- unsigned long iPoint;
-
-
- for (iPoint = 0; iPoint < nPoint; iPoint++){
-
- /*--- Extract the adjoint solution ---*/
-
- if (config->GetMultizone_Problem())
- geometry->node[iPoint]->GetAdjointCoord_LocalIndex(Solution_Geometry);
- else
- geometry->node[iPoint]->GetAdjointCoord(Solution_Geometry);
-
- for (iDim = 0; iDim < nDim; iDim++) nodes->SetGeometry_CrossTerm_Derivative_Flow(iPoint,iDim, Solution_Geometry[iDim]);
-
- }
-
-}
-
-
void CDiscAdjSolver::SetAdjoint_Output(CGeometry *geometry, CConfig *config) {
bool dual_time = (config->GetTime_Marching() == DT_STEPPING_1ST ||
config->GetTime_Marching() == DT_STEPPING_2ND);
- bool fsi = config->GetFSI_Simulation();
unsigned short iVar;
unsigned long iPoint;
@@ -763,11 +702,6 @@ void CDiscAdjSolver::SetAdjoint_Output(CGeometry *geometry, CConfig *config) {
for (iVar = 0; iVar < nVar; iVar++) {
Solution[iVar] = nodes->GetSolution(iPoint,iVar);
}
- if (fsi) {
- for (iVar = 0; iVar < nVar; iVar++) {
- Solution[iVar] += nodes->GetCross_Term_Derivative(iPoint,iVar);
- }
- }
if (dual_time) {
for (iVar = 0; iVar < nVar; iVar++) {
Solution[iVar] += nodes->GetDual_Time_Derivative(iPoint,iVar);
@@ -787,8 +721,6 @@ void CDiscAdjSolver::SetAdjoint_OutputMesh(CGeometry *geometry, CConfig *config)
// bool dual_time = (config->GetUnsteady_Simulation() == DT_STEPPING_1ST ||
// config->GetUnsteady_Simulation() == DT_STEPPING_2ND);
- bool fsi = config->GetFSI_Simulation();
-
unsigned short iDim;
unsigned long iPoint;
@@ -796,14 +728,6 @@ void CDiscAdjSolver::SetAdjoint_OutputMesh(CGeometry *geometry, CConfig *config)
for (iDim = 0; iDim < nDim; iDim++){
Solution_Geometry[iDim] = 0.0;
}
- if (fsi){
- for (iDim = 0; iDim < nDim; iDim++){
- Solution_Geometry[iDim] += nodes->GetGeometry_CrossTerm_Derivative(iPoint,iDim);
- }
- for (iDim = 0; iDim < nDim; iDim++){
- Solution_Geometry[iDim] += nodes->GetGeometry_CrossTerm_Derivative_Flow(iPoint,iDim);
- }
- }
// if (dual_time){
// for (iDim = 0; iDim < nVar; iDim++){
// Solution_Geometry[iDim] += nodes->GetDual_Time_Derivative_Geometry(iPoint,iDim);
@@ -1076,48 +1000,7 @@ void CDiscAdjSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfi
/*--- Delete the class memory that is used to load the restart. ---*/
- if (Restart_Vars != NULL) delete [] Restart_Vars;
- if (Restart_Data != NULL) delete [] Restart_Data;
- Restart_Vars = NULL; Restart_Data = NULL;
-
-}
-
-void CDiscAdjSolver::ComputeResidual_Multizone(CGeometry *geometry, CConfig *config) {
-
- unsigned short iVar;
- unsigned long iPoint;
- su2double residual, bgs_sol;
-
- /*--- Set Residuals to zero ---*/
-
- for (iVar = 0; iVar < nVar; iVar++){
- SetRes_BGS(iVar,0.0);
- SetRes_Max_BGS(iVar,0.0,0);
- }
-
- /*--- Compute the BGS solution (adding the cross term) ---*/
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- for (iVar = 0; iVar < nVar; iVar++){
- if(config->GetMultizone_Problem() && !config->GetFSI_Simulation()) {
- bgs_sol = nodes->GetSolution(iPoint,iVar);
- }
- else {
- bgs_sol = nodes->GetSolution(iPoint,iVar) + nodes->GetCross_Term_Derivative(iPoint,iVar);
- }
- nodes->Set_BGSSolution(iPoint, iVar, bgs_sol);
- }
- }
-
- /*--- Set the residuals ---*/
-
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- for (iVar = 0; iVar < nVar; iVar++){
- residual = nodes->Get_BGSSolution(iPoint,iVar) - nodes->Get_BGSSolution_k(iPoint,iVar);
- AddRes_BGS(iVar,residual*residual);
- AddRes_Max_BGS(iVar,fabs(residual),geometry->node[iPoint]->GetGlobalIndex(),geometry->node[iPoint]->GetCoord());
- }
- }
-
- SetResidual_BGS(geometry, config);
+ delete [] Restart_Vars; Restart_Vars = nullptr;
+ delete [] Restart_Data; Restart_Data = nullptr;
}
diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp
index e3a818780aac..692a25b7f7d8 100644
--- a/SU2_CFD/src/solvers/CEulerSolver.cpp
+++ b/SU2_CFD/src/solvers/CEulerSolver.cpp
@@ -11483,19 +11483,14 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
unsigned short iDim, iVar, iMesh, iMeshFine;
unsigned long iPoint, index, iChildren, Point_Fine;
unsigned short turb_model = config->GetKind_Turb_Model();
- su2double Area_Children, Area_Parent, *Coord, *Solution_Fine;
+ su2double Area_Children, Area_Parent, Coord[MAXNDIM] = {0.0}, *Solution_Fine;
bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) ||
(config->GetTime_Marching() == DT_STEPPING_2ND));
- bool static_fsi = ((config->GetTime_Marching() == STEADY) &&
- config->GetFSI_Simulation());
+ bool static_fsi = ((config->GetTime_Marching() == STEADY) && config->GetFSI_Simulation());
bool steady_restart = config->GetSteadyRestart();
- bool turbulent = (config->GetKind_Turb_Model() != NONE);
-
- string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter);
+ bool turbulent = (config->GetKind_Turb_Model() != NONE);
- Coord = new su2double [nDim];
- for (iDim = 0; iDim < nDim; iDim++)
- Coord[iDim] = 0.0;
+ string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter);
int counter = 0;
long iPoint_Local = 0; unsigned long iPoint_Global = 0;
@@ -11550,13 +11545,12 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
/*--- If we are restarting the solution from a previously computed static calculation (no grid movement) ---*/
/*--- the grid velocities are set to 0. This is useful for FSI computations ---*/
+ /*--- Rewind the index to retrieve the Coords. ---*/
+ index = counter*Restart_Vars[1];
+ for (iDim = 0; iDim < nDim; iDim++) { Coord[iDim] = Restart_Data[index+iDim]; }
+
su2double GridVel[3] = {0.0,0.0,0.0};
if (!steady_restart) {
-
- /*--- Rewind the index to retrieve the Coords. ---*/
- index = counter*Restart_Vars[1];
- for (iDim = 0; iDim < nDim; iDim++) { Coord[iDim] = Restart_Data[index+iDim]; }
-
/*--- Move the index forward to get the grid velocities. ---*/
index = counter*Restart_Vars[1] + skipVars + nVar + turbVars;
for (iDim = 0; iDim < nDim; iDim++) { GridVel[iDim] = Restart_Data[index+iDim]; }
@@ -11568,6 +11562,9 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
}
}
+ /*--- For static FSI problems, grid_movement is 0 but we need to read in and store the
+ grid coordinates for each node (but not the grid velocities, as there are none). ---*/
+
if (static_fsi && val_update_geo) {
/*--- Rewind the index to retrieve the Coords. ---*/
index = counter*Restart_Vars[1];
@@ -11587,8 +11584,8 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
/*--- Detect a wrong solution file ---*/
if (iPoint_Global_Local < nPointDomain) {
- SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
- string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
+ SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
+ string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
}
/*--- Communicate the loaded solution on the fine grid before we transfer
@@ -11694,8 +11691,6 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
}
}
- delete [] Coord;
-
/*--- Delete the class memory that is used to load the restart. ---*/
delete [] Restart_Vars; Restart_Vars = nullptr;
diff --git a/SU2_CFD/src/solvers/CFEASolver.cpp b/SU2_CFD/src/solvers/CFEASolver.cpp
index cbfe80eccfa9..5a24ace56ff1 100644
--- a/SU2_CFD/src/solvers/CFEASolver.cpp
+++ b/SU2_CFD/src/solvers/CFEASolver.cpp
@@ -28,55 +28,13 @@
#include "../../include/solvers/CFEASolver.hpp"
#include "../../include/variables/CFEABoundVariable.hpp"
#include "../../../Common/include/toolboxes/printing_toolbox.hpp"
+#include "../../../Common/include/toolboxes/geometry_toolbox.hpp"
#include
+#include
+#include
-/*!
- * \brief Anonymous namespace with helper functions of the FEA solver.
- */
-namespace {
-
- template
- void CrossProduct(const T* a, const T* b, T* c) {
- c[0] = a[1]*b[2] - a[2]*b[1];
- c[1] = a[2]*b[0] - a[0]*b[2];
- c[2] = a[0]*b[1] - a[1]*b[0];
- }
-
- template
- void LineNormal(const T& coords, U* normal) {
- normal[0] = coords[0][1] - coords[1][1];
- normal[1] = coords[1][0] - coords[0][0];
- }
-
- template
- void TriangleNormal(const T& coords, U* normal) {
- /*--- Cross product of two sides. ---*/
- U a[3], b[3];
-
- for (int iDim = 0; iDim < 3; iDim++) {
- a[iDim] = coords[1][iDim] - coords[0][iDim];
- b[iDim] = coords[2][iDim] - coords[0][iDim];
- }
-
- CrossProduct(a, b, normal);
- normal[0] *= 0.5; normal[1] *= 0.5; normal[2] *= 0.5;
- }
-
- template
- void QuadrilateralNormal(const T& coords, U* normal) {
- /*--- Cross product of the two diagonals. ---*/
- U a[3], b[3];
-
- for (int iDim = 0; iDim < 3; iDim++) {
- a[iDim] = coords[2][iDim] - coords[0][iDim];
- b[iDim] = coords[3][iDim] - coords[1][iDim];
- }
-
- CrossProduct(a, b, normal);
- normal[0] *= 0.5; normal[1] *= 0.5; normal[2] *= 0.5;
- }
+using namespace GeometryToolbox;
-}
CFEASolver::CFEASolver(bool mesh_deform_mode) : CSolver(mesh_deform_mode) {
@@ -96,15 +54,10 @@ CFEASolver::CFEASolver(bool mesh_deform_mode) : CSolver(mesh_deform_mode) {
for (unsigned short iTerm = 0; iTerm < MAX_TERMS; iTerm++)
element_container[iTerm] = new CElement* [MAX_FE_KINDS*omp_get_max_threads()]();
- nodes = nullptr;
-
- element_properties = nullptr;
-
- iElem_iDe = nullptr;
-
topol_filter_applied = false;
-
element_based = false;
+ initial_calc = true;
+
}
CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() {
@@ -118,8 +71,8 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() {
/*--- A priori we don't have an element-based input file (most of the applications will be like this) ---*/
element_based = false;
-
topol_filter_applied = false;
+ initial_calc = true;
nElement = geometry->GetnElem();
nDim = geometry->GetnDim();
@@ -243,8 +196,6 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() {
/*--- Initialize structures for hybrid-parallel mode. ---*/
HybridParallelInitialization(geometry);
- iElem_iDe = nullptr;
-
/*--- Initialize the value of the total objective function ---*/
Total_OFRefGeom = 0.0;
Total_OFRefNode = 0.0;
@@ -291,11 +242,24 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() {
/*--- If dynamic, we also need to communicate the old solution ---*/
- if(dynamic) {
+ if (dynamic) {
InitiateComms(geometry, config, SOLUTION_FEA_OLD);
CompleteComms(geometry, config, SOLUTION_FEA_OLD);
}
+ if (size != SINGLE_NODE) {
+ vector essentialMarkers;
+ for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ const auto kindBnd = config->GetMarker_All_KindBC(iMarker);
+ if ((kindBnd == CLAMPED_BOUNDARY) ||
+ (kindBnd == DISP_DIR_BOUNDARY) ||
+ (kindBnd == DISPLACEMENT_BOUNDARY)) {
+ essentialMarkers.push_back(iMarker);
+ }
+ }
+ Set_VertexEliminationSchedule(geometry, essentialMarkers);
+ }
+
/*--- Add the solver name (max 8 characters) ---*/
SolverName = "FEA";
}
@@ -312,15 +276,15 @@ CFEASolver::~CFEASolver(void) {
delete [] element_container;
}
- if (element_properties != nullptr){
+ if (element_properties != nullptr) {
for (unsigned long iElem = 0; iElem < nElement; iElem++)
- if (element_properties[iElem] != nullptr) delete element_properties[iElem];
+ delete element_properties[iElem];
delete [] element_properties;
}
- if (iElem_iDe != nullptr) delete [] iElem_iDe;
+ delete [] iElem_iDe;
- if (nodes != nullptr) delete nodes;
+ delete nodes;
if (LockStrategy) {
for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++)
@@ -755,29 +719,66 @@ void CFEASolver::Set_ReferenceGeometry(CGeometry *geometry, CConfig *config) {
}
+void CFEASolver::Set_VertexEliminationSchedule(CGeometry *geometry, const vector& markers) {
-void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, CNumerics **numerics,
- unsigned short iMesh, unsigned long Iteration, unsigned short RunTime_EqSystem, bool Output) {
+ /*--- Store global point indices of essential BC markers. ---*/
+ vector myPoints;
- bool dynamic = config->GetTime_Domain();
- bool first_iter = (config->GetInnerIter() == 0);
+ for (auto iMarker : markers) {
+ for (auto iVertex = 0ul; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+ auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+ myPoints.push_back(geometry->node[iPoint]->GetGlobalIndex());
+ }
+ }
- /*--- Initial calculation, different logic for restarted simulations. ---*/
- bool initial_calc = false;
- if (config->GetRestart())
- initial_calc = (config->GetTimeIter() == config->GetRestart_Iter()) && first_iter;
- else
- initial_calc = (config->GetTimeIter() == 0) && first_iter;
+ const unordered_set markerPoints(myPoints.begin(), myPoints.end());
- bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
+ vector numPoints(size);
+ unsigned long num = myPoints.size();
+ SU2_MPI::Allgather(&num, 1, MPI_UNSIGNED_LONG, numPoints.data(), 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+
+ /*--- Global to local map for the halo points of the rank (not covered by the CGeometry map). ---*/
+ unordered_map Global2Local;
+ for (auto iPoint = nPointDomain; iPoint < nPoint; ++iPoint) {
+ Global2Local[geometry->node[iPoint]->GetGlobalIndex()] = iPoint;
+ }
- bool body_forces = config->GetDeadLoad();
+ /*--- Populate elimination list. ---*/
+ ExtraVerticesToEliminate.clear();
- bool fsi = config->GetFSI_Simulation();
- bool consistent_interpolation = (!config->GetConservativeInterpolation() ||
- (config->GetKindInterpolation() == WEIGHTED_AVERAGE));
+ for (int i = 0; i < size; ++i) {
+ /*--- Send our point list. ---*/
+ if (rank == i) {
+ SU2_MPI::Bcast(myPoints.data(), numPoints[i], MPI_UNSIGNED_LONG, rank, MPI_COMM_WORLD);
+ continue;
+ }
- bool topology_mode = config->GetTopology_Optimization();
+ /*--- Receive point list. ---*/
+ vector theirPoints(numPoints[i]);
+ SU2_MPI::Bcast(theirPoints.data(), numPoints[i], MPI_UNSIGNED_LONG, i, MPI_COMM_WORLD);
+
+ for (auto iPointGlobal : theirPoints) {
+ /*--- Check if the rank has the point. ---*/
+ auto it = Global2Local.find(iPointGlobal);
+ if (it == Global2Local.end()) continue;
+
+ /*--- If the point is not covered by this rank's markers, mark it for elimination. ---*/
+ if (markerPoints.count(iPointGlobal) == 0)
+ ExtraVerticesToEliminate.push_back(it->second);
+ }
+ }
+
+}
+
+void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, CNumerics **numerics,
+ unsigned short iMesh, unsigned long Iteration, unsigned short RunTime_EqSystem, bool Output) {
+
+ const bool dynamic = config->GetTime_Domain();
+ const bool first_iter = (config->GetInnerIter() == 0);
+ const bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
+ const bool body_forces = config->GetDeadLoad();
+ const bool fsi = config->GetFSI_Simulation();
+ const bool topology_mode = config->GetTopology_Optimization();
/*
* For topology optimization we apply a filter on the design density field to avoid
@@ -789,7 +790,7 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container,
*/
if (topology_mode && !topol_filter_applied) {
geometry->SetElemVolume(config);
- FilterElementDensities(geometry,config);
+ FilterElementDensities(geometry, config);
topol_filter_applied = true;
}
@@ -810,7 +811,7 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container,
*
* Only initialized once, at the first iteration of the first time step.
*/
- if (body_forces && initial_calc)
+ if (body_forces && (initial_calc || disc_adj_fem))
Compute_DeadLoad(geometry, numerics, config);
/*--- Clear the linear system solution. ---*/
@@ -825,7 +826,10 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container,
/*
* FSI loads (computed upstream) need to be integrated if a nonconservative interpolation scheme is in use
*/
- if (fsi && first_iter && consistent_interpolation) Integrate_FSI_Loads(geometry,config);
+ if (fsi && first_iter) Integrate_FSI_Loads(geometry, config);
+
+ /*--- Next call to Preprocessing will not be "initial_calc" and linear operations will not be repeated. ---*/
+ initial_calc = false;
}
@@ -2075,7 +2079,7 @@ void CFEASolver::BC_Damper(CGeometry *geometry, CNumerics *numerics, CConfig *co
unsigned short iNode, iDim;
unsigned long indexNode[4] = {0};
- su2double nodeCoord[4][3] = {0.0};
+ su2double nodeCoord[4][3] = {{0.0}};
bool quad = (geometry->bound[val_marker][iElem]->GetVTK_Type() == QUADRILATERAL);
unsigned short nNodes = quad? 4 : nDim;
@@ -2143,46 +2147,43 @@ void CFEASolver::BC_Deforming(CGeometry *geometry, CNumerics *numerics, CConfig
}
-void CFEASolver::Integrate_FSI_Loads(CGeometry *geometry, CConfig *config) {
+void CFEASolver::Integrate_FSI_Loads(CGeometry *geometry, const CConfig *config) {
+
+ /*--- The conservative approach transfers forces directly, no integration needed. ---*/
+ if (config->GetConservativeInterpolation()) return;
- unsigned short iDim, iNode, nNode;
- unsigned long iPoint, iElem, nElem;
+ const auto nMarker = config->GetnMarker_All();
+ const auto nMarkerInt = config->GetMarker_n_ZoneInterface()/2u;
- unsigned short iMarkerInt, nMarkerInt = config->GetMarker_n_ZoneInterface()/2,
- iMarker, nMarker = config->GetnMarker_All();
+ unordered_map vertexArea;
- /*--- Temporary storage to store the forces on the element faces ---*/
- vector forces;
+ /*--- Compute current area associated with each vertex. ---*/
- /*--- Loop through the FSI interface pairs ---*/
- /*--- 1st pass to compute forces ---*/
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; ++iMarkerInt) {
- /*--- Find the marker index associated with the pair ---*/
+ for (auto iMarkerInt = 1u; iMarkerInt <= nMarkerInt; ++iMarkerInt) {
+ /*--- Find the marker index associated with the pair. ---*/
+ unsigned short iMarker;
for (iMarker = 0; iMarker < nMarker; ++iMarker)
if (config->GetMarker_All_ZoneInterface(iMarker) == iMarkerInt)
break;
- /*--- The current mpi rank may not have this marker ---*/
+ /*--- The current mpi rank may not have this marker. ---*/
if (iMarker == nMarker) continue;
- nElem = geometry->GetnElem_Bound(iMarker);
-
- for (iElem = 0; iElem < nElem; ++iElem) {
- /*--- Define the boundary element ---*/
- unsigned long nodeList[4];
- su2double coords[4][3];
+ for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); ++iElem) {
+ /*--- Define the boundary element. ---*/
+ unsigned long nodeList[4] = {0};
+ su2double coords[4][3] = {{0.0}};
bool quad = geometry->bound[iMarker][iElem]->GetVTK_Type() == QUADRILATERAL;
- nNode = quad? 4 : nDim;
+ auto nNode = quad? 4u : nDim;
- for (iNode = 0; iNode < nNode; ++iNode) {
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
nodeList[iNode] = geometry->bound[iMarker][iElem]->GetNode(iNode);
- for (iDim = 0; iDim < nDim; ++iDim)
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
coords[iNode][iDim] = geometry->node[nodeList[iNode]]->GetCoord(iDim)+
nodes->GetSolution(nodeList[iNode],iDim);
}
- /*--- Compute the area ---*/
-
- su2double normal[3] = {0.0, 0.0, 0.0};
+ /*--- Compute the area contribution to each node. ---*/
+ su2double normal[3] = {0.0};
switch (nNode) {
case 2: LineNormal(coords, normal); break;
@@ -2190,125 +2191,30 @@ void CFEASolver::Integrate_FSI_Loads(CGeometry *geometry, CConfig *config) {
case 4: QuadrilateralNormal(coords, normal); break;
}
- su2double area = sqrt(pow(normal[0],2) + pow(normal[1],2) + pow(normal[2],2));
-
- /*--- Integrate ---*/
- passivedouble weight = 1.0/nNode;
- su2double force[3] = {0.0, 0.0, 0.0};
-
- for (iNode = 0; iNode < nNode; ++iNode)
- for (iDim = 0; iDim < nDim; ++iDim)
- force[iDim] += weight*area*nodes->Get_FlowTraction(nodeList[iNode],iDim);
-
- for (iDim = 0; iDim < nDim; ++iDim) forces.push_back(force[iDim]);
- }
- }
-
- /*--- 2nd pass to set values. This is to account for overlap in the markers. ---*/
- /*--- By putting the integrated values back into the nodes no changes have to be made elsewhere. ---*/
- nodes->Clear_FlowTraction();
+ su2double area = sqrt(pow(normal[0],2) + pow(normal[1],2) + pow(normal[2],2)) / nNode;
- vector::iterator force_it = forces.begin();
-
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; ++iMarkerInt) {
- /*--- Find the marker index associated with the pair ---*/
- for (iMarker = 0; iMarker < nMarker; ++iMarker)
- if (config->GetMarker_All_ZoneInterface(iMarker) == iMarkerInt)
- break;
- /*--- The current mpi rank may not have this marker ---*/
- if (iMarker == nMarker) continue;
-
- nElem = geometry->GetnElem_Bound(iMarker);
-
- for (iElem = 0; iElem < nElem; ++iElem) {
- bool quad = geometry->bound[iMarker][iElem]->GetVTK_Type() == QUADRILATERAL;
- nNode = quad? 4 : nDim;
- passivedouble weight = 1.0/nNode;
-
- su2double force[3];
- for (iDim = 0; iDim < nDim; ++iDim) force[iDim] = *(force_it++)*weight;
-
- for (iNode = 0; iNode < nNode; ++iNode) {
- iPoint = geometry->bound[iMarker][iElem]->GetNode(iNode);
- nodes->Add_FlowTraction(iPoint,force);
+ /*--- Update area of nodes. ---*/
+ for (auto iNode = 0u; iNode < nNode; ++iNode) {
+ auto iPoint = nodeList[iNode];
+ if (vertexArea.count(iPoint) == 0)
+ vertexArea[iPoint] = area;
+ else
+ vertexArea[iPoint] += area;
}
}
}
-#ifdef HAVE_MPI
- /*--- Perform a global reduction, every rank will get the nodal values of all halo elements ---*/
- /*--- This should be cheaper than the "normal" way, since very few points are both halo and interface ---*/
- vector halo_point_loc, halo_point_glb;
- vector halo_force;
+ /*--- Integrate tractions. ---*/
- for (iMarkerInt = 1; iMarkerInt <= nMarkerInt; ++iMarkerInt) {
- /*--- Find the marker index associated with the pair ---*/
- for (iMarker = 0; iMarker < nMarker; ++iMarker)
- if (config->GetMarker_All_ZoneInterface(iMarker) == iMarkerInt)
- break;
- /*--- The current mpi rank may not have this marker ---*/
- if (iMarker == nMarker) continue;
-
- nElem = geometry->GetnElem_Bound(iMarker);
-
- for (iElem = 0; iElem < nElem; ++iElem) {
- bool quad = geometry->bound[iMarker][iElem]->GetVTK_Type() == QUADRILATERAL;
- nNode = quad? 4 : nDim;
-
- /*--- If this is an halo element we share the nodal forces ---*/
- for (iNode = 0; iNode < nNode; ++iNode)
- if (!geometry->node[geometry->bound[iMarker][iElem]->GetNode(iNode)]->GetDomain())
- break;
-
- if (iNode < nNode) {
- for (iNode = 0; iNode < nNode; ++iNode) {
- iPoint = geometry->bound[iMarker][iElem]->GetNode(iNode);
- /*--- local is for when later we update the values in this rank ---*/
- halo_point_loc.push_back(iPoint);
- halo_point_glb.push_back(geometry->node[iPoint]->GetGlobalIndex());
- for (iDim = 0; iDim < nDim; ++iDim)
- halo_force.push_back(nodes->Get_FlowTraction(iPoint,iDim));
- }
- }
- }
- }
- /*--- Determine the size of the arrays we need ---*/
- unsigned long nHaloLoc = halo_point_loc.size();
- unsigned long nHaloMax;
- MPI_Allreduce(&nHaloLoc,&nHaloMax,1,MPI_UNSIGNED_LONG,MPI_MAX,MPI_COMM_WORLD);
-
- /*--- Shared arrays, all the: number of halo points; halo point global indices; respective forces ---*/
- unsigned long *halo_point_num = new unsigned long[size];
- unsigned long *halo_point_all = new unsigned long[size*nHaloMax];
- su2double *halo_force_all = new su2double[size*nHaloMax*nDim];
-
- /*--- Make "allgathers" extra safe by resizing all vectors to the same size (some
- issues observed when nHaloLoc = 0, especially with the discrete adjoint. ---*/
- halo_point_glb.resize(nHaloMax,0);
- halo_force.resize(nHaloMax*nDim,0.0);
-
- MPI_Allgather(&nHaloLoc,1,MPI_UNSIGNED_LONG,halo_point_num,1,MPI_UNSIGNED_LONG,MPI_COMM_WORLD);
- MPI_Allgather(halo_point_glb.data(),nHaloMax,MPI_UNSIGNED_LONG,halo_point_all,nHaloMax,MPI_UNSIGNED_LONG,MPI_COMM_WORLD);
- SU2_MPI::Allgather(halo_force.data(),nHaloMax*nDim,MPI_DOUBLE,halo_force_all,nHaloMax*nDim,MPI_DOUBLE,MPI_COMM_WORLD);
-
- /*--- Find shared points with other ranks and update our values ---*/
- for (int proc = 0; proc < size; ++proc)
- if (proc != rank) {
- unsigned long offset = proc*nHaloMax;
- for (iPoint = 0; iPoint < halo_point_num[proc]; ++iPoint) {
- unsigned long iPoint_glb = halo_point_all[offset+iPoint];
- ptrdiff_t pos = find(halo_point_glb.begin(),halo_point_glb.end(),iPoint_glb)-halo_point_glb.begin();
- if (pos < long(halo_point_glb.size())) {
- unsigned long iPoint_loc = halo_point_loc[pos];
- nodes->Add_FlowTraction(iPoint_loc,&halo_force_all[(offset+iPoint)*nDim]);
- }
- }
+ for (auto it = vertexArea.begin(); it != vertexArea.end(); ++it) {
+ auto iPoint = it->first;
+ su2double area = it->second;
+ su2double force[3] = {0.0};
+ for (auto iDim = 0u; iDim < nDim; ++iDim)
+ force[iDim] = nodes->Get_FlowTraction(iPoint,iDim)*area;
+ nodes->Set_FlowTraction(iPoint, force);
}
- delete [] halo_point_num;
- delete [] halo_point_all;
- delete [] halo_force_all;
-#endif
}
su2double CFEASolver::Compute_LoadCoefficient(su2double CurrentTime, su2double RampTime, CConfig *config){
@@ -2781,21 +2687,21 @@ void CFEASolver::GeneralizedAlpha_UpdateLoads(CGeometry *geometry, CSolver **sol
void CFEASolver::Solve_System(CGeometry *geometry, CConfig *config) {
- SU2_OMP_PARALLEL
- {
- /*--- Initialize residual and solution at the ghost points ---*/
+ /*--- Enforce solution at some halo points possibly not covered by essential BC markers. ---*/
- SU2_OMP(sections)
- {
- SU2_OMP(section)
- for (auto iPoint = nPointDomain; iPoint < nPoint; iPoint++)
- LinSysRes.SetBlock_Zero(iPoint);
+ Jacobian.InitiateComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
+ Jacobian.CompleteComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
- SU2_OMP(section)
- for (auto iPoint = nPointDomain; iPoint < nPoint; iPoint++)
- LinSysSol.SetBlock_Zero(iPoint);
+ for (auto iPoint : ExtraVerticesToEliminate) {
+ Jacobian.EnforceSolutionAtNode(iPoint, LinSysSol.GetBlock(iPoint), LinSysRes);
}
+ SU2_OMP_PARALLEL
+ {
+ /*--- This is required for the discrete adjoint. ---*/
+ SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
+ for (auto i = nPointDomain*nVar; i < nPoint*nVar; ++i) LinSysRes[i] = 0.0;
+
/*--- Solve or smooth the linear system. ---*/
auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config);
@@ -2804,9 +2710,9 @@ void CFEASolver::Solve_System(CGeometry *geometry, CConfig *config) {
SetIterLinSolver(iter);
SetResLinSolver(System.GetResidual());
}
- SU2_OMP_BARRIER
-
+ //SU2_OMP_BARRIER
} // end SU2_OMP_PARALLEL
+
}
diff --git a/SU2_CFD/src/solvers/CIncEulerSolver.cpp b/SU2_CFD/src/solvers/CIncEulerSolver.cpp
index 16e6eb4c43d6..03c25ef36e15 100644
--- a/SU2_CFD/src/solvers/CIncEulerSolver.cpp
+++ b/SU2_CFD/src/solvers/CIncEulerSolver.cpp
@@ -5830,24 +5830,18 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
unsigned short iDim, iVar, iMesh, iMeshFine;
unsigned long iPoint, index, iChildren, Point_Fine;
unsigned short turb_model = config->GetKind_Turb_Model();
- su2double Area_Children, Area_Parent, *Coord, *Solution_Fine;
- bool static_fsi = ((config->GetTime_Marching() == STEADY) &&
- (config->GetFSI_Simulation()));
+ su2double Area_Children, Area_Parent, Coord[3] = {0.0}, *Solution_Fine;
+ bool static_fsi = ((config->GetTime_Marching() == STEADY) && config->GetFSI_Simulation());
bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) ||
(config->GetTime_Marching() == DT_STEPPING_2ND));
bool steady_restart = config->GetSteadyRestart();
- bool turbulent = (config->GetKind_Solver() == INC_RANS) || (config->GetKind_Solver() == DISC_ADJ_INC_RANS);
+ bool turbulent = (config->GetKind_Solver() == INC_RANS) || (config->GetKind_Solver() == DISC_ADJ_INC_RANS);
string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter);
- Coord = new su2double [nDim];
- for (iDim = 0; iDim < nDim; iDim++)
- Coord[iDim] = 0.0;
-
int counter = 0;
long iPoint_Local = 0; unsigned long iPoint_Global = 0;
unsigned long iPoint_Global_Local = 0;
- unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0;
/*--- Skip coordinates ---*/
@@ -5910,13 +5904,12 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- If we are restarting the solution from a previously computed static calculation (no grid movement) ---*/
/*--- the grid velocities are set to 0. This is useful for FSI computations ---*/
+ /*--- Rewind the index to retrieve the Coords. ---*/
+ index = counter*Restart_Vars[1];
+ for (iDim = 0; iDim < nDim; iDim++) { Coord[iDim] = Restart_Data[index+iDim]; }
+
su2double GridVel[3] = {0.0,0.0,0.0};
if (!steady_restart) {
-
- /*--- Rewind the index to retrieve the Coords. ---*/
- index = counter*Restart_Vars[1];
- for (iDim = 0; iDim < nDim; iDim++) { Coord[iDim] = Restart_Data[index+iDim]; }
-
/*--- Move the index forward to get the grid velocities. ---*/
index = counter*Restart_Vars[1] + skipVars + nVar_Restart + turbVars;
for (iDim = 0; iDim < nDim; iDim++) { GridVel[iDim] = Restart_Data[index+iDim]; }
@@ -5928,7 +5921,6 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
}
}
-
/*--- For static FSI problems, grid_movement is 0 but we need to read in and store the
grid coordinates for each node (but not the grid velocities, as there are none). ---*/
@@ -5950,14 +5942,7 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- Detect a wrong solution file ---*/
- if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; }
-
-#ifndef HAVE_MPI
- rbuf_NotMatching = sbuf_NotMatching;
-#else
- SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD);
-#endif
- if (rbuf_NotMatching != 0) {
+ if (iPoint_Global_Local < nPointDomain) {
SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
}
@@ -6060,8 +6045,6 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
}
}
- delete [] Coord;
-
/*--- Delete the class memory that is used to load the restart. ---*/
if (Restart_Vars != NULL) delete [] Restart_Vars;
diff --git a/SU2_CFD/src/solvers/CMeshSolver.cpp b/SU2_CFD/src/solvers/CMeshSolver.cpp
index 64dfdf7c1361..8fcd4392e01c 100644
--- a/SU2_CFD/src/solvers/CMeshSolver.cpp
+++ b/SU2_CFD/src/solvers/CMeshSolver.cpp
@@ -25,11 +25,13 @@
* License along with SU2. If not, see .
*/
-
#include "../../../Common/include/adt_structure.hpp"
#include "../../../Common/include/omp_structure.hpp"
#include "../../include/solvers/CMeshSolver.hpp"
#include "../../include/variables/CMeshBoundVariable.hpp"
+#include "../../../Common/include/toolboxes/geometry_toolbox.hpp"
+
+using namespace GeometryToolbox;
CMeshSolver::CMeshSolver(CGeometry *geometry, CConfig *config) : CFEASolver(true) {
@@ -101,6 +103,7 @@ CMeshSolver::CMeshSolver(CGeometry *geometry, CConfig *config) : CFEASolver(true
LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0);
LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0);
Jacobian.Initialize(nPoint, nPointDomain, nVar, nVar, false, geometry, config);
+ System.SetToleranceType(LinearToleranceType::ABSOLUTE);
/*--- Initialize structures for hybrid-parallel mode. ---*/
@@ -157,6 +160,19 @@ CMeshSolver::CMeshSolver(CGeometry *geometry, CConfig *config) : CFEASolver(true
/*--- Compute the wall distance using the reference coordinates ---*/
SetWallDistance(geometry, config);
+ if (size != SINGLE_NODE) {
+ vector essentialMarkers;
+ /*--- Markers types covered in SetBoundaryDisplacements. ---*/
+ for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (((config->GetMarker_All_KindBC(iMarker) != SEND_RECEIVE) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) ||
+ (config->GetMarker_All_Deform_Mesh(iMarker) == YES) ||
+ (config->GetMarker_All_Moving(iMarker) == YES)) {
+ essentialMarkers.push_back(iMarker);
+ }
+ }
+ Set_VertexEliminationSchedule(geometry, essentialMarkers);
+ }
}
void CMeshSolver::SetMinMaxVolume(CGeometry *geometry, CConfig *config, bool updated) {
@@ -388,6 +404,8 @@ void CMeshSolver::SetWallDistance(CGeometry *geometry, CConfig *config) {
void CMeshSolver::SetMesh_Stiffness(CGeometry **geometry, CNumerics **numerics, CConfig *config){
+ if (stiffness_set) return;
+
/*--- Use the config option as an upper bound on elasticity modulus.
* For RANS meshes the range of element volume or wall distance is
* very large and leads to an ill-conditioned stiffness matrix.
@@ -396,31 +414,46 @@ void CMeshSolver::SetMesh_Stiffness(CGeometry **geometry, CNumerics **numerics,
* boundary conditions are essential (Dirichlet). ---*/
const su2double maxE = config->GetDeform_ElasticityMod();
- if (!stiffness_set) {
- /*--- All threads must execute the entire loop (no worksharing),
- * each sets the stiffnesses for its numerics instance. ---*/
- SU2_OMP_PARALLEL
- {
- CNumerics* myNumerics = numerics[FEA_TERM + omp_get_thread_num()*MAX_TERMS];
-
- for (unsigned long iElem = 0; iElem < nElement; iElem++) {
-
- su2double E = 1.0;
+ /*--- All threads must execute the entire loop (no worksharing),
+ * each sets the stiffnesses for its numerics instance. ---*/
+ SU2_OMP_PARALLEL
+ {
+ CNumerics* myNumerics = numerics[FEA_TERM + omp_get_thread_num()*MAX_TERMS];
- switch (config->GetDeform_Stiffness_Type()) {
- /*--- Stiffness inverse of the volume of the element ---*/
- case INVERSE_VOLUME: E = 1.0 / element[iElem].GetRef_Volume(); break;
+ switch (config->GetDeform_Stiffness_Type()) {
- /*--- Stiffness inverse of the distance of the element to the closest wall ---*/
- case SOLID_WALL_DISTANCE: E = 1.0 / element[iElem].GetWallDistance(); break;
+ /*--- Stiffness inverse of the volume of the element. ---*/
+ case INVERSE_VOLUME:
+ for (unsigned long iElem = 0; iElem < nElement; iElem++) {
+ su2double E = 1.0 / element[iElem].GetRef_Volume();
+ myNumerics->SetMeshElasticProperties(iElem, min(E,maxE));
}
+ break;
- /*--- Set the element elastic properties in the numerics container ---*/
- myNumerics->SetMeshElasticProperties(iElem, min(E,maxE));
- }
+ /*--- Stiffness inverse of the distance of the element to the closest wall. ---*/
+ case SOLID_WALL_DISTANCE: {
+ const su2double offset = config->GetDeform_StiffLayerSize();
+ if (fabs(offset) > 0.0) {
+ /*--- With prescribed layer of maximum stiffness (reaches max and holds). ---*/
+ su2double d0 = offset / MaxDistance;
+ su2double dmin = 1.0 / maxE;
+ su2double scale = 1.0 / (1.0 - d0);
+ for (unsigned long iElem = 0; iElem < nElement; iElem++) {
+ su2double E = 1.0 / max(dmin, (element[iElem].GetWallDistance() - d0)*scale);
+ myNumerics->SetMeshElasticProperties(iElem, E);
+ }
+ } else {
+ /*--- Without prescribed layer of maximum stiffness (may not reach max). ---*/
+ for (unsigned long iElem = 0; iElem < nElement; iElem++) {
+ su2double E = 1.0 / element[iElem].GetWallDistance();
+ myNumerics->SetMeshElasticProperties(iElem, min(E,maxE));
+ }
+ }
}
- stiffness_set = true;
+ break;
}
+ }
+ stiffness_set = true;
}
@@ -431,10 +464,9 @@ void CMeshSolver::DeformMesh(CGeometry **geometry, CNumerics **numerics, CConfig
/*--- Compute the stiffness matrix. ---*/
Compute_StiffMatrix(geometry[MESH_0], numerics, config);
- /*--- Initialize vectors and clean residual. ---*/
+ /*--- Clean residual, we do not want an incremental solution. ---*/
SU2_OMP_PARALLEL
{
- LinSysSol.SetValZero();
LinSysRes.SetValZero();
}
@@ -549,8 +581,8 @@ void CMeshSolver::ComputeGridVelocity(CGeometry *geometry, CConfig *config){
if (config->GetTime_Marching() == DT_STEPPING_1ST)
GridVel = ( Disp_nP1[iDim] - Disp_n[iDim] ) / TimeStep;
if (config->GetTime_Marching() == DT_STEPPING_2ND)
- GridVel = ( 3.0*Disp_nP1[iDim] - 4.0*Disp_n[iDim]
- + 1.0*Disp_nM1[iDim] ) / (2.0*TimeStep);
+ GridVel = ( 3.0*Disp_nP1[iDim] - 4.0*Disp_n[iDim] +
+ 1.0*Disp_nM1[iDim] ) / (2.0*TimeStep);
/*--- Store grid velocity for this point ---*/
@@ -586,12 +618,29 @@ void CMeshSolver::UpdateMultiGrid(CGeometry **geometry, CConfig *config){
void CMeshSolver::SetBoundaryDisplacements(CGeometry *geometry, CNumerics *numerics, CConfig *config){
+ /* Surface motions are not applied during discrete adjoint runs as the corresponding
+ * boundary displacements are computed when loading the primal solution, and it
+ * would be complex to account for the incremental nature of these motions.
+ * The derivatives are still correct since the motion does not depend on the solution,
+ * but this means that (for now) we cannot get derivatives w.r.t. motion parameters. */
+
+ if (config->GetSurface_Movement(DEFORMING) && !config->GetDiscrete_Adjoint()) {
+ if (rank == MASTER_NODE)
+ cout << endl << " Updating surface positions." << endl;
+
+ Surface_Translating(geometry, config, config->GetTimeIter());
+ Surface_Plunging(geometry, config, config->GetTimeIter());
+ Surface_Pitching(geometry, config, config->GetTimeIter());
+ Surface_Rotating(geometry, config, config->GetTimeIter());
+ }
+
unsigned short iMarker;
/*--- Impose zero displacements of all non-moving surfaces (also at nodes in multiple moving/non-moving boundaries). ---*/
/*--- Exceptions: symmetry plane, the receive boundaries and periodic boundaries should get a different treatment. ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
if ((config->GetMarker_All_Deform_Mesh(iMarker) == NO) &&
+ (config->GetMarker_All_Moving(iMarker) == NO) &&
(config->GetMarker_All_KindBC(iMarker) != SYMMETRY_PLANE) &&
(config->GetMarker_All_KindBC(iMarker) != SEND_RECEIVE) &&
(config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
@@ -600,9 +649,10 @@ void CMeshSolver::SetBoundaryDisplacements(CGeometry *geometry, CNumerics *numer
}
}
- /*--- Symmetry plane is, for now, clamped. ---*/
+ /*--- Symmetry plane is clamped, for now. ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
if ((config->GetMarker_All_Deform_Mesh(iMarker) == NO) &&
+ (config->GetMarker_All_Moving(iMarker) == NO) &&
(config->GetMarker_All_KindBC(iMarker) == SYMMETRY_PLANE)) {
BC_Clamped(geometry, numerics, config, iMarker);
@@ -611,7 +661,8 @@ void CMeshSolver::SetBoundaryDisplacements(CGeometry *geometry, CNumerics *numer
/*--- Impose displacement boundary conditions. ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if (config->GetMarker_All_Deform_Mesh(iMarker) == YES) {
+ if ((config->GetMarker_All_Deform_Mesh(iMarker) == YES) ||
+ (config->GetMarker_All_Moving(iMarker) == YES)) {
BC_Deforming(geometry, numerics, config, iMarker);
}
@@ -689,6 +740,13 @@ void CMeshSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *
geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
+ /*--- Init the linear system solution. ---*/
+ for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) {
+ for (unsigned short iDim = 0; iDim < nDim; ++iDim) {
+ LinSysSol(iPoint, iDim) = nodes->GetSolution(iPoint, iDim);
+ }
+ }
+
/*--- Recompute the edges and dual mesh control volumes in the
domain and on the boundaries. ---*/
UpdateDualGrid(geometry[MESH_0], config);
@@ -711,7 +769,8 @@ void CMeshSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *
for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- if (config->GetMarker_All_Deform_Mesh(iMarker) == YES) {
+ if ((config->GetMarker_All_Deform_Mesh(iMarker) == YES) ||
+ (config->GetMarker_All_Moving(iMarker) == YES)) {
for (unsigned long iVertex = 0; iVertex < geometry[MESH_0]->nVertex[iMarker]; iVertex++) {
@@ -762,15 +821,8 @@ void CMeshSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
if (rank == MASTER_NODE) cout << "Requested mesh restart filename is negative. Setting known solution" << endl;
/*--- Set loaded solution into correct previous time containers. ---*/
- unsigned long iPoint;
- for (iPoint = 0; iPoint < nPoint; iPoint++ ) {
- for (unsigned short iDim = 0; iDim < nDim; iDim++){
- if(iStep==1)
- nodes->Set_Solution_time_n(iPoint, iDim, nodes->GetSolution(iPoint, iDim));
- else
- nodes->Set_Solution_time_n1(iPoint, iDim, nodes->GetSolution_time_n(iPoint, iDim));
- }
- }
+ if(iStep==1) nodes->Set_Solution_time_n();
+ else nodes->Set_Solution_time_n1();
}
else {
string filename_n = config->GetUnsteady_FileName(filename, Unst_RestartIter, "");
@@ -837,492 +889,394 @@ void CMeshSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
}
-void CMeshSolver::Surface_Pitching(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
-
- su2double deltaT, time_new, time_old, Lref, *Coord;
- su2double Center[3], VarCoord[3], Omega[3], Ampl[3], Phase[3];
- su2double VarCoordAbs[3] = {0.0, 0.0, 0.0};
- su2double rotCoord[3], r[3] = {0.0,0.0,0.0};
- su2double rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
- su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
- su2double cosPhi, sinPhi, cosPsi, sinPsi;
- su2double DEG2RAD = PI_NUMBER/180.0;
- unsigned short iMarker, jMarker, Moving, iDim, nDim = geometry->GetnDim();
+void CMeshSolver::Surface_Pitching(CGeometry *geometry, CConfig *config, unsigned long iter) {
+
+ su2double deltaT, time_new, time_old, Lref;
+ const su2double* Coord = nullptr;
+ su2double Center[3] = {0.0}, VarCoord[3] = {0.0}, Omega[3] = {0.0}, Ampl[3] = {0.0}, Phase[3] = {0.0};
+ su2double VarCoordAbs[3] = {0.0};
+ su2double rotCoord[3] = {0.0}, r[3] = {0.0};
+ su2double rotMatrix[3][3] = {{0.0}};
+ su2double dtheta, dphi, dpsi;
+ const su2double DEG2RAD = PI_NUMBER/180.0;
+ unsigned short iMarker, jMarker, iDim;
unsigned long iPoint, iVertex;
string Marker_Tag, Moving_Tag;
-
- CSolver *solver = NULL;
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
-
/*--- Retrieve values from the config file ---*/
-
+
deltaT = config->GetDelta_UnstTimeND();
Lref = config->GetLength_Ref();
-
+
/*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
+
+ time_new = iter*deltaT;
+ if (iter == 0) time_old = time_new;
+ else time_old = (iter-1)*deltaT;
/*--- Store displacement of each node on the pitching surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to pitch ---*/
+ /*--- Loop over markers and find the particular marker(s) (surface) to pitch ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Pitching origin, frequency, and amplitude from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Ampl[iDim] = config->GetMarkerPitching_Ampl(jMarker, iDim)*DEG2RAD;
- Omega[iDim] = config->GetMarkerPitching_Omega(jMarker, iDim)/config->GetOmega_Ref();
- Phase[iDim] = config->GetMarkerPitching_Phase(jMarker, iDim)*DEG2RAD;
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing pitching displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Pitching frequency: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
- cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
- cout << " Pitching amplitude about origin: (" << Ampl[0]/DEG2RAD;
- cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- cout << " Pitching phase lag about origin: (" << Phase[0]/DEG2RAD;
- cout << ", " << Phase[1]/DEG2RAD <<", "<< Phase[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- }
- }
-
- /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
-
- dtheta = -Ampl[0]*(sin(Omega[0]*time_new + Phase[0])
- - sin(Omega[0]*time_old + Phase[0]));
- dphi = -Ampl[1]*(sin(Omega[1]*time_new + Phase[1])
- - sin(Omega[1]*time_old + Phase[1]));
- dpsi = -Ampl[2]*(sin(Omega[2]*time_new + Phase[2])
- - sin(Omega[2]*time_old + Phase[2]));
-
- /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
-
- cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
- sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
-
- /*--- Compute the rotation matrix. Note that the implicit
- ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
-
- rotMatrix[0][0] = cosPhi*cosPsi;
- rotMatrix[1][0] = cosPhi*sinPsi;
- rotMatrix[2][0] = -sinPhi;
-
- rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
- rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
- rotMatrix[2][1] = sinTheta*cosPhi;
-
- rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
- rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
- rotMatrix[2][2] = cosTheta*cosPhi;
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Index and coordinates of the current point ---*/
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- Coord = geometry->node[iPoint]->GetCoord();
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- // /*--- Set node displacement for volume deformation ---*/
- // geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- for (iDim = 0; iDim < 3; iDim++){
- VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
- }
-
- nodes->SetBound_Disp(iPoint, VarCoordAbs);
- }
+ if (config->GetMarker_All_Moving(iMarker) != YES) continue;
+
+ Marker_Tag = config->GetMarker_All_TagBound(iMarker);
+
+ for (jMarker = 0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
+ Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
+
+ if ((Marker_Tag != Moving_Tag) || (config->GetKind_SurfaceMovement(jMarker) != DEFORMING)) {
+ continue;
+ }
+
+ /*--- Pitching origin, frequency, and amplitude from config. ---*/
+
+ for (iDim = 0; iDim < 3; iDim++){
+ Ampl[iDim] = config->GetMarkerPitching_Ampl(jMarker, iDim)*DEG2RAD;
+ Omega[iDim] = config->GetMarkerPitching_Omega(jMarker, iDim)/config->GetOmega_Ref();
+ Phase[iDim] = config->GetMarkerPitching_Phase(jMarker, iDim)*DEG2RAD;
+ Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
+ }
+ /*--- Print some information to the console. Be verbose at the first
+ iteration only (mostly for debugging purposes). ---*/
+ // Note that the MASTER_NODE might not contain all the markers being moved.
+
+ if (rank == MASTER_NODE) {
+ cout << " Storing pitching displacement for marker: ";
+ cout << Marker_Tag << "." << endl;
+ if (iter == 0) {
+ cout << " Pitching frequency: (" << Omega[0] << ", " << Omega[1];
+ cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
+ cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
+ cout << " Pitching amplitude about origin: (" << Ampl[0]/DEG2RAD;
+ cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
+ cout << ") degrees."<< endl;
+ cout << " Pitching phase lag about origin: (" << Phase[0]/DEG2RAD;
+ cout << ", " << Phase[1]/DEG2RAD <<", "<< Phase[2]/DEG2RAD;
+ cout << ") degrees."<< endl;
}
}
+
+ /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
+
+ dtheta = -Ampl[0]*(sin(Omega[0]*time_new + Phase[0])
+ - sin(Omega[0]*time_old + Phase[0]));
+ dphi = -Ampl[1]*(sin(Omega[1]*time_new + Phase[1])
+ - sin(Omega[1]*time_old + Phase[1]));
+ dpsi = -Ampl[2]*(sin(Omega[2]*time_new + Phase[2])
+ - sin(Omega[2]*time_old + Phase[2]));
+
+ /*--- Compute rotation matrix. ---*/
+
+ RotationMatrix(dtheta, dphi, dpsi, rotMatrix);
+
+ /*--- Apply rotation to the vertices. ---*/
+
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Index and coordinates of the current point ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+ Coord = geometry->node[iPoint]->GetCoord();
+
+ /*--- Calculate non-dim. position from rotation center ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
+
+ /*--- Compute transformed point coordinates ---*/
+
+ Rotate(rotMatrix, Center, r, rotCoord);
+
+ /*--- Calculate delta change in the x, y, & z directions ---*/
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
+
+ /*--- Set node displacement for volume deformation ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
+
+ nodes->SetBound_Disp(iPoint, VarCoordAbs);
+ }
}
}
/*--- For pitching we don't update the motion origin and moment reference origin. ---*/
-
+
}
-void CMeshSolver::Surface_Rotating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
- su2double deltaT, time_new, time_old, Lref, *Coord;
- su2double VarCoordAbs[3] = {0.0, 0.0, 0.0};
- su2double Center[3] = {0.0,0.0,0.0}, VarCoord[3] = {0.0,0.0,0.0}, Omega[3] = {0.0,0.0,0.0},
- rotCoord[3] = {0.0,0.0,0.0}, r[3] = {0.0,0.0,0.0}, Center_Aux[3] = {0.0,0.0,0.0};
- su2double rotMatrix[3][3] = {{0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0}};
- su2double dtheta, dphi, dpsi, cosTheta, sinTheta;
- su2double cosPhi, sinPhi, cosPsi, sinPsi;
- unsigned short iMarker, jMarker, Moving, iDim, nDim = geometry->GetnDim();
+void CMeshSolver::Surface_Rotating(CGeometry *geometry, CConfig *config, unsigned long iter) {
+
+ su2double deltaT, time_new, time_old, Lref;
+ const su2double* Coord = nullptr;
+ su2double VarCoordAbs[3] = {0.0};
+ su2double Center[3] = {0.0}, VarCoord[3] = {0.0}, Omega[3] = {0.0},
+ rotCoord[3] = {0.0}, r[3] = {0.0}, Center_Aux[3] = {0.0};
+ su2double rotMatrix[3][3] = {{0.0}};
+ su2double dtheta, dphi, dpsi;
+ unsigned short iMarker, jMarker, iDim;
unsigned long iPoint, iVertex;
string Marker_Tag, Moving_Tag;
-
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
-
+
/*--- Retrieve values from the config file ---*/
-
+
deltaT = config->GetDelta_UnstTimeND();
Lref = config->GetLength_Ref();
-
+
/*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
-
+
+ time_new = iter*deltaT;
+ if (iter == 0) time_old = time_new;
+ else time_old = (iter-1)*deltaT;
+
/*--- Store displacement of each node on the rotating surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to rotate ---*/
+ /*--- Loop over markers and find the particular marker(s) (surface) to rotate ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Rotation origin and angular velocity from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Omega[iDim] = config->GetMarkerRotationRate(jMarker, iDim)/config->GetOmega_Ref();
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing rotating displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Angular velocity: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
- cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
- }
- }
-
- /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
-
- dtheta = Omega[0]*(time_new-time_old);
- dphi = Omega[1]*(time_new-time_old);
- dpsi = Omega[2]*(time_new-time_old);
-
- /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
-
- cosTheta = cos(dtheta); cosPhi = cos(dphi); cosPsi = cos(dpsi);
- sinTheta = sin(dtheta); sinPhi = sin(dphi); sinPsi = sin(dpsi);
-
- /*--- Compute the rotation matrix. Note that the implicit
- ordering is rotation about the x-axis, y-axis, then z-axis. ---*/
-
- rotMatrix[0][0] = cosPhi*cosPsi;
- rotMatrix[1][0] = cosPhi*sinPsi;
- rotMatrix[2][0] = -sinPhi;
-
- rotMatrix[0][1] = sinTheta*sinPhi*cosPsi - cosTheta*sinPsi;
- rotMatrix[1][1] = sinTheta*sinPhi*sinPsi + cosTheta*cosPsi;
- rotMatrix[2][1] = sinTheta*cosPhi;
-
- rotMatrix[0][2] = cosTheta*sinPhi*cosPsi + sinTheta*sinPsi;
- rotMatrix[1][2] = cosTheta*sinPhi*sinPsi - sinTheta*cosPsi;
- rotMatrix[2][2] = cosTheta*cosPhi;
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- /*--- Index and coordinates of the current point ---*/
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
- Coord = geometry->node[iPoint]->GetCoord();
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- // /*--- Set node displacement for volume deformation ---*/
- // geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- for (iDim = 0; iDim < 3; iDim++){
- VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
- }
-
- nodes->SetBound_Disp(iPoint, VarCoordAbs);
- }
+ if (config->GetMarker_All_Moving(iMarker) != YES) continue;
+
+ Marker_Tag = config->GetMarker_All_TagBound(iMarker);
+
+ for (jMarker = 0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
+ Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
+
+ if ((Marker_Tag != Moving_Tag) || (config->GetKind_SurfaceMovement(jMarker) != DEFORMING)) {
+ continue;
+ }
+
+ /*--- Rotation origin and angular velocity from config. ---*/
+
+ for (iDim = 0; iDim < 3; iDim++){
+ Omega[iDim] = config->GetMarkerRotationRate(jMarker, iDim)/config->GetOmega_Ref();
+ Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
+ }
+
+ /*--- Print some information to the console. Be verbose at the first
+ iteration only (mostly for debugging purposes). ---*/
+ // Note that the MASTER_NODE might not contain all the markers being moved.
+
+ if (rank == MASTER_NODE) {
+ cout << " Storing rotating displacement for marker: ";
+ cout << Marker_Tag << "." << endl;
+ if (iter == 0) {
+ cout << " Angular velocity: (" << Omega[0] << ", " << Omega[1];
+ cout << ", " << Omega[2] << ") rad/s about origin: (" << Center[0];
+ cout << ", " << Center[1] << ", " << Center[2] << ")." << endl;
}
}
+
+ /*--- Compute delta change in the angle about the x, y, & z axes. ---*/
+
+ dtheta = Omega[0]*(time_new-time_old);
+ dphi = Omega[1]*(time_new-time_old);
+ dpsi = Omega[2]*(time_new-time_old);
+
+ /*--- Compute rotation matrix. ---*/
+
+ RotationMatrix(dtheta, dphi, dpsi, rotMatrix);
+
+ /*--- Apply rotation to the vertices. ---*/
+
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Index and coordinates of the current point ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+ Coord = geometry->node[iPoint]->GetCoord();
+
+ /*--- Calculate non-dim. position from rotation center ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ r[iDim] = (Coord[iDim]-Center[iDim])/Lref;
+
+ /*--- Compute transformed point coordinates ---*/
+
+ Rotate(rotMatrix, Center, r, rotCoord);
+
+ /*--- Calculate delta change in the x, y, & z directions ---*/
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoord[iDim] = (rotCoord[iDim]-Coord[iDim])/Lref;
+
+ /*--- Set node displacement for volume deformation ---*/
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
+
+ nodes->SetBound_Disp(iPoint, VarCoordAbs);
+ }
}
}
-
+
/*--- When updating the origins it is assumed that all markers have the
same rotation movement, because we use the last markers rotation matrix and center ---*/
-
+
/*--- Set the mesh motion center to the new location after
incrementing the position with the rotation. This new
location will be used for subsequent mesh motion for the given marker.---*/
-
- for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
-
+
+ for (jMarker=0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
/*-- Check if we want to update the motion origin for the given marker ---*/
-
- if (config->GetMoveMotion_Origin(jMarker) == YES) {
-
- for (iDim = 0; iDim < 3; iDim++){
- Center_Aux[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
-
- /*--- Calculate non-dim. position from rotation center ---*/
-
- for (iDim = 0; iDim < nDim; iDim++)
- r[iDim] = (Center_Aux[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
- /*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
- /*--- Calculate delta change in the x, y, & z directions ---*/
- for (iDim = 0; iDim < nDim; iDim++)
- VarCoord[iDim] = (rotCoord[iDim]-Center_Aux[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
- for (iDim = 0; iDim < 3; iDim++){
- Center_Aux[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center_Aux, jMarker);
- }
+
+ if (config->GetMoveMotion_Origin(jMarker) != YES) continue;
+
+ for (iDim = 0; iDim < 3; iDim++)
+ Center_Aux[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
+
+ /*--- Calculate non-dim. position from rotation center ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ r[iDim] = (Center_Aux[iDim]-Center[iDim])/Lref;
+
+ /*--- Compute transformed point coordinates ---*/
+
+ Rotate(rotMatrix, Center, r, rotCoord);
+
+ /*--- Calculate delta change in the x, y, & z directions ---*/
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoord[iDim] = (rotCoord[iDim]-Center_Aux[iDim])/Lref;
+
+ for (iDim = 0; iDim < 3; iDim++)
+ Center_Aux[iDim] += VarCoord[iDim];
+
+ config->SetMarkerMotion_Origin(Center_Aux, jMarker);
}
/*--- Set the moment computation center to the new location after
incrementing the position with the rotation. ---*/
-
+
for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
-
+
Center_Aux[0] = config->GetRefOriginMoment_X(jMarker);
Center_Aux[1] = config->GetRefOriginMoment_Y(jMarker);
Center_Aux[2] = config->GetRefOriginMoment_Z(jMarker);
/*--- Calculate non-dim. position from rotation center ---*/
-
+
for (iDim = 0; iDim < nDim; iDim++)
r[iDim] = (Center_Aux[iDim]-Center[iDim])/Lref;
- if (nDim == 2) r[nDim] = 0.0;
-
+
/*--- Compute transformed point coordinates ---*/
-
- rotCoord[0] = rotMatrix[0][0]*r[0]
- + rotMatrix[0][1]*r[1]
- + rotMatrix[0][2]*r[2] + Center[0];
-
- rotCoord[1] = rotMatrix[1][0]*r[0]
- + rotMatrix[1][1]*r[1]
- + rotMatrix[1][2]*r[2] + Center[1];
-
- rotCoord[2] = rotMatrix[2][0]*r[0]
- + rotMatrix[2][1]*r[1]
- + rotMatrix[2][2]*r[2] + Center[2];
-
+
+ Rotate(rotMatrix, Center, r, rotCoord);
+
/*--- Calculate delta change in the x, y, & z directions ---*/
for (iDim = 0; iDim < nDim; iDim++)
VarCoord[iDim] = (rotCoord[iDim]-Center_Aux[iDim])/Lref;
- if (nDim == 2) VarCoord[nDim] = 0.0;
-
+
config->SetRefOriginMoment_X(jMarker, Center_Aux[0]+VarCoord[0]);
config->SetRefOriginMoment_Y(jMarker, Center_Aux[1]+VarCoord[1]);
config->SetRefOriginMoment_Z(jMarker, Center_Aux[2]+VarCoord[2]);
}
}
-void CMeshSolver::Surface_Plunging(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+void CMeshSolver::Surface_Plunging(CGeometry *geometry, CConfig *config, unsigned long iter) {
+
su2double deltaT, time_new, time_old, Lref;
- su2double Center[3] = {0.0, 0.0, 0.0}, VarCoord[3], Omega[3], Ampl[3];
- su2double VarCoordAbs[3] = {0.0, 0.0, 0.0};
- su2double DEG2RAD = PI_NUMBER/180.0;
- unsigned short iMarker, jMarker, Moving;
+ su2double Center[3] = {0.0}, VarCoord[3] = {0.0}, Omega[3] = {0.0}, Ampl[3] = {0.0};
+ su2double VarCoordAbs[3] = {0.0};
+ const su2double DEG2RAD = PI_NUMBER/180.0;
+ unsigned short iMarker, jMarker;
unsigned long iPoint, iVertex;
string Marker_Tag, Moving_Tag;
unsigned short iDim;
-
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
-
+
/*--- Retrieve values from the config file ---*/
-
+
deltaT = config->GetDelta_UnstTimeND();
Lref = config->GetLength_Ref();
-
+
/*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
-
+
+ time_new = iter*deltaT;
+ if (iter == 0) time_old = time_new;
+ else time_old = (iter-1)*deltaT;
+
/*--- Store displacement of each node on the plunging surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to plunge ---*/
-
+ /*--- Loop over markers and find the particular marker(s) (surface) to plunge ---*/
+
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- /*--- Plunging frequency and amplitude from config. ---*/
-
- for (iDim = 0; iDim < 3; iDim++){
- Ampl[iDim] = config->GetMarkerPlunging_Ampl(jMarker, iDim)/Lref;
- Omega[iDim] = config->GetMarkerPlunging_Omega(jMarker, iDim)/config->GetOmega_Ref();
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing plunging displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Plunging frequency: (" << Omega[0] << ", " << Omega[1];
- cout << ", " << Omega[2] << ") rad/s." << endl;
- cout << " Plunging amplitude: (" << Ampl[0]/DEG2RAD;
- cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
- cout << ") degrees."<< endl;
- }
- }
-
- /*--- Compute delta change in the position in the x, y, & z directions. ---*/
-
- VarCoord[0] = -Ampl[0]*(sin(Omega[0]*time_new) - sin(Omega[0]*time_old));
- VarCoord[1] = -Ampl[1]*(sin(Omega[1]*time_new) - sin(Omega[1]*time_old));
- VarCoord[2] = -Ampl[2]*(sin(Omega[2]*time_new) - sin(Omega[2]*time_old));
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- // /*--- Set node displacement for volume deformation ---*/
- // geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
-
- for (iDim = 0; iDim < 3; iDim++){
- VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
- }
-
- nodes->SetBound_Disp(iPoint, VarCoordAbs);
-
- }
+ if (config->GetMarker_All_Moving(iMarker) != YES) continue;
+
+ Marker_Tag = config->GetMarker_All_TagBound(iMarker);
+
+ for (jMarker = 0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
+ Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
+
+ if ((Marker_Tag != Moving_Tag) || (config->GetKind_SurfaceMovement(jMarker) != DEFORMING)) {
+ continue;
+ }
+
+ /*--- Plunging frequency and amplitude from config. ---*/
+
+ for (iDim = 0; iDim < 3; iDim++){
+ Ampl[iDim] = config->GetMarkerPlunging_Ampl(jMarker, iDim)/Lref;
+ Omega[iDim] = config->GetMarkerPlunging_Omega(jMarker, iDim)/config->GetOmega_Ref();
+ Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
+ }
+
+ /*--- Print some information to the console. Be verbose at the first
+ iteration only (mostly for debugging purposes). ---*/
+ // Note that the MASTER_NODE might not contain all the markers being moved.
+
+ if (rank == MASTER_NODE) {
+ cout << " Storing plunging displacement for marker: ";
+ cout << Marker_Tag << "." << endl;
+ if (iter == 0) {
+ cout << " Plunging frequency: (" << Omega[0] << ", " << Omega[1];
+ cout << ", " << Omega[2] << ") rad/s." << endl;
+ cout << " Plunging amplitude: (" << Ampl[0]/DEG2RAD;
+ cout << ", " << Ampl[1]/DEG2RAD << ", " << Ampl[2]/DEG2RAD;
+ cout << ") degrees."<< endl;
}
}
+
+ /*--- Compute delta change in the position in the x, y, & z directions. ---*/
+
+ VarCoord[0] = -Ampl[0]*(sin(Omega[0]*time_new) - sin(Omega[0]*time_old));
+ VarCoord[1] = -Ampl[1]*(sin(Omega[1]*time_new) - sin(Omega[1]*time_old));
+ VarCoord[2] = -Ampl[2]*(sin(Omega[2]*time_new) - sin(Omega[2]*time_old));
+
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Set node displacement for volume deformation ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
+
+ nodes->SetBound_Disp(iPoint, VarCoordAbs);
+
+ }
}
}
-
+
/*--- When updating the origins it is assumed that all markers have the
same plunging movement, because we use the last VarCoord set ---*/
-
+
/*--- Set the mesh motion center to the new location after
incrementing the position with the translation. This new
location will be used for subsequent mesh motion for the given marker.---*/
-
+
for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
-
+
/*-- Check if we want to update the motion origin for the given marker ---*/
-
+
if (config->GetMoveMotion_Origin(jMarker) == YES) {
- for (iDim = 0; iDim < 3; iDim++){
+ for (iDim = 0; iDim < 3; iDim++)
Center[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center, jMarker);
+
+ config->SetMarkerMotion_Origin(Center, jMarker);
}
}
-
+
/*--- Set the moment computation center to the new location after
incrementing the position with the plunging. ---*/
-
- for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
+
+ for (jMarker=0; jMarker < config->GetnMarker_Monitoring(); jMarker++) {
Center[0] = config->GetRefOriginMoment_X(jMarker) + VarCoord[0];
Center[1] = config->GetRefOriginMoment_Y(jMarker) + VarCoord[1];
Center[2] = config->GetRefOriginMoment_Z(jMarker) + VarCoord[2];
@@ -1332,112 +1286,106 @@ void CMeshSolver::Surface_Plunging(CGeometry *geometry, CConfig *config,
}
}
-void CMeshSolver::Surface_Translating(CGeometry *geometry, CConfig *config,
- unsigned long iter, unsigned short iZone) {
+void CMeshSolver::Surface_Translating(CGeometry *geometry, CConfig *config, unsigned long iter) {
+
su2double deltaT, time_new, time_old;
- su2double Center[3] = {0.0,0.0,0.0}, VarCoord[3] = {0.0,0.0,0.0};
- su2double VarCoordAbs[3] = {0.0, 0.0, 0.0};
- su2double xDot[3] = {0.0,0.0,0.0};
- unsigned short iMarker, jMarker, Moving;
+ su2double Center[3] = {0.0}, VarCoord[3] = {0.0};
+ su2double VarCoordAbs[3] = {0.0};
+ su2double xDot[3] = {0.0};
+ unsigned short iMarker, jMarker;
unsigned long iPoint, iVertex;
string Marker_Tag, Moving_Tag;
unsigned short iDim;
-
- /*--- Initialize the delta variation in coordinates ---*/
- VarCoord[0] = 0.0; VarCoord[1] = 0.0; VarCoord[2] = 0.0;
-
+
/*--- Retrieve values from the config file ---*/
-
+
deltaT = config->GetDelta_UnstTimeND();
-
+
/*--- Compute delta time based on physical time step ---*/
- time_new = static_cast(iter)*deltaT;
- if (iter == 0) {
- time_old = time_new;
- } else {
- time_old = static_cast(iter-1)*deltaT;
- }
-
+
+ time_new = iter*deltaT;
+ if (iter == 0) time_old = time_new;
+ else time_old = (iter-1)*deltaT;
+
/*--- Store displacement of each node on the translating surface ---*/
- /*--- Loop over markers and find the particular marker(s) (surface) to translate ---*/
-
+ /*--- Loop over markers and find the particular marker(s) (surface) to translate ---*/
+
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
- Moving = config->GetMarker_All_Moving(iMarker);
- if (Moving == YES) {
- for (jMarker = 0; jMarkerGetnMarker_Moving(); jMarker++) {
-
- Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
- Marker_Tag = config->GetMarker_All_TagBound(iMarker);
-
- if (Marker_Tag == Moving_Tag && (config->GetKind_SurfaceMovement(jMarker) == DEFORMING)) {
-
- for (iDim = 0; iDim < 3; iDim++){
- xDot[iDim] = config->GetMarkerTranslationRate(jMarker, iDim);
- Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
- }
-
- /*--- Print some information to the console. Be verbose at the first
- iteration only (mostly for debugging purposes). ---*/
- // Note that the MASTER_NODE might not contain all the markers being moved.
-
- if (rank == MASTER_NODE) {
- cout << " Storing translating displacement for marker: ";
- cout << Marker_Tag << "." << endl;
- if (iter == 0) {
- cout << " Translational velocity: (" << xDot[0]*config->GetVelocity_Ref() << ", " << xDot[1]*config->GetVelocity_Ref();
- cout << ", " << xDot[2]*config->GetVelocity_Ref();
- if (config->GetSystemMeasurements() == SI) cout << ") m/s." << endl;
- else cout << ") ft/s." << endl;
- }
- }
-
- /*--- Compute delta change in the position in the x, y, & z directions. ---*/
-
- VarCoord[0] = xDot[0]*(time_new-time_old);
- VarCoord[1] = xDot[1]*(time_new-time_old);
- VarCoord[2] = xDot[2]*(time_new-time_old);
-
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
-
- // /*--- Set node displacement for volume deformation ---*/
- // geometry->vertex[iMarker][iVertex]->SetVarCoord(VarCoord);
-
- iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
-
- for (iDim = 0; iDim < 3; iDim++){
- VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
- }
-
- nodes->SetBound_Disp(iPoint, VarCoordAbs);
- }
+ if (config->GetMarker_All_Moving(iMarker) != YES) continue;
+
+ Marker_Tag = config->GetMarker_All_TagBound(iMarker);
+
+ for (jMarker = 0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
+ Moving_Tag = config->GetMarker_Moving_TagBound(jMarker);
+
+ if ((Marker_Tag != Moving_Tag) || (config->GetKind_SurfaceMovement(jMarker) != DEFORMING)) {
+ continue;
+ }
+
+ for (iDim = 0; iDim < 3; iDim++) {
+ xDot[iDim] = config->GetMarkerTranslationRate(jMarker, iDim);
+ Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim);
+ }
+
+ /*--- Print some information to the console. Be verbose at the first
+ iteration only (mostly for debugging purposes). ---*/
+ // Note that the MASTER_NODE might not contain all the markers being moved.
+
+ if (rank == MASTER_NODE) {
+ cout << " Storing translating displacement for marker: ";
+ cout << Marker_Tag << "." << endl;
+ if (iter == 0) {
+ cout << " Translational velocity: (" << xDot[0]*config->GetVelocity_Ref() << ", " << xDot[1]*config->GetVelocity_Ref();
+ cout << ", " << xDot[2]*config->GetVelocity_Ref();
+ if (config->GetSystemMeasurements() == SI) cout << ") m/s." << endl;
+ else cout << ") ft/s." << endl;
}
}
+
+ /*--- Compute delta change in the position in the x, y, & z directions. ---*/
+
+ VarCoord[0] = xDot[0]*(time_new-time_old);
+ VarCoord[1] = xDot[1]*(time_new-time_old);
+ VarCoord[2] = xDot[2]*(time_new-time_old);
+
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Set node displacement for volume deformation ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+
+ for (iDim = 0; iDim < nDim; iDim++)
+ VarCoordAbs[iDim] = nodes->GetBound_Disp(iPoint, iDim) + VarCoord[iDim];
+
+ nodes->SetBound_Disp(iPoint, VarCoordAbs);
+ }
}
}
-
+
/*--- When updating the origins it is assumed that all markers have the
same translational velocity, because we use the last VarCoord set ---*/
-
+
/*--- Set the mesh motion center to the new location after
incrementing the position with the translation. This new
location will be used for subsequent mesh motion for the given marker.---*/
-
- for (jMarker=0; jMarkerGetnMarker_Moving(); jMarker++) {
-
+
+ for (jMarker=0; jMarker < config->GetnMarker_Moving(); jMarker++) {
+
/*-- Check if we want to update the motion origin for the given marker ---*/
-
+
if (config->GetMoveMotion_Origin(jMarker) == YES) {
- for (iDim = 0; iDim < 3; iDim++){
+ for (iDim = 0; iDim < 3; iDim++)
Center[iDim] += VarCoord[iDim];
- }
- config->SetMarkerMotion_Origin(Center, jMarker);
+
+ config->SetMarkerMotion_Origin(Center, jMarker);
}
}
-
+
/*--- Set the moment computation center to the new location after
incrementing the position with the translation. ---*/
-
- for (jMarker=0; jMarkerGetnMarker_Monitoring(); jMarker++) {
+
+ for (jMarker=0; jMarker < config->GetnMarker_Monitoring(); jMarker++) {
Center[0] = config->GetRefOriginMoment_X(jMarker) + VarCoord[0];
Center[1] = config->GetRefOriginMoment_Y(jMarker) + VarCoord[1];
Center[2] = config->GetRefOriginMoment_Z(jMarker) + VarCoord[2];
diff --git a/SU2_CFD/src/solvers/CSolver.cpp b/SU2_CFD/src/solvers/CSolver.cpp
index 66b2c2f31fa1..92f9b81a4e60 100644
--- a/SU2_CFD/src/solvers/CSolver.cpp
+++ b/SU2_CFD/src/solvers/CSolver.cpp
@@ -3439,7 +3439,6 @@ void CSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
string text_line;
long iPoint_Local;
unsigned long iPoint_Global_Local = 0, iPoint_Global = 0;
- unsigned short rbuf_NotMatching, sbuf_NotMatching;
/*--- First, we load the restart file for time n ---*/
@@ -3491,13 +3490,7 @@ void CSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
/*--- Detect a wrong solution file ---*/
- rbuf_NotMatching = 0; sbuf_NotMatching = 0;
-
- if (iPoint_Global_Local < geometry->GetnPointDomain()) { sbuf_NotMatching = 1; }
-
- SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD);
-
- if (rbuf_NotMatching != 0) {
+ if (iPoint_Global_Local < geometry->GetnPointDomain()) {
SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") +
string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
}
@@ -3565,13 +3558,7 @@ void CSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
/*--- Detect a wrong solution file ---*/
- rbuf_NotMatching = 0; sbuf_NotMatching = 0;
-
- if (iPoint_Global_Local < geometry->GetnPointDomain()) { sbuf_NotMatching = 1; }
-
- SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD);
-
- if (rbuf_NotMatching != 0) {
+ if (iPoint_Global_Local < geometry->GetnPointDomain()) {
SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") +
string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
}
@@ -4749,28 +4736,22 @@ void CSolver::ComputeResidual_Multizone(CGeometry *geometry, CConfig *config){
su2double residual;
/*--- Set Residuals to zero ---*/
-
for (iVar = 0; iVar < nVar; iVar++){
SetRes_BGS(iVar,0.0);
SetRes_Max_BGS(iVar,0.0,0);
}
- /*--- Set the residuals ---*/
- for (iPoint = 0; iPoint < nPointDomain; iPoint++){
- for (iVar = 0; iVar < nVar; iVar++){
- residual = base_nodes->GetSolution(iPoint,iVar) - base_nodes->Get_BGSSolution_k(iPoint,iVar);
- AddRes_BGS(iVar,residual*residual);
- AddRes_Max_BGS(iVar,fabs(residual),geometry->node[iPoint]->GetGlobalIndex(),geometry->node[iPoint]->GetCoord());
+ /*--- Set the residuals and BGSSolution_k to solution for next multizone outer iteration. ---*/
+ for (iPoint = 0; iPoint < nPoint; iPoint++) {
+ const su2double domain = (iPoint < nPointDomain);
+ for (iVar = 0; iVar < nVar; iVar++) {
+ residual = (base_nodes->Get_BGSSolution(iPoint,iVar) - base_nodes->Get_BGSSolution_k(iPoint,iVar))*domain;
+ base_nodes->Set_BGSSolution_k(iPoint,iVar, base_nodes->Get_BGSSolution(iPoint,iVar));
+ AddRes_BGS(iVar, residual*residual);
+ AddRes_Max_BGS(iVar, fabs(residual), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord());
}
}
SetResidual_BGS(geometry, config);
}
-
-
-void CSolver::UpdateSolution_BGS(CGeometry *geometry, CConfig *config){
-
- /*--- To nPoint: The solution must be communicated beforehand ---*/
- base_nodes->Set_BGSSolution_k();
-}
diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp
index 80038a1b7f99..bc7122dafa70 100644
--- a/SU2_CFD/src/solvers/CTurbSASolver.cpp
+++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp
@@ -225,9 +225,9 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor
SetImplicitPeriodic(true);
- /* Store the initial CFL number for all grid points. */
+ /*--- Store the initial CFL number for all grid points. ---*/
- const su2double CFL = config->GetCFL(MGLevel);
+ const su2double CFL = config->GetCFL(MGLevel)*config->GetCFLRedCoeff_Turb();
for (iPoint = 0; iPoint < nPoint; iPoint++) {
nodes->SetLocalCFL(iPoint, CFL);
}
diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp
index db9a7af1236d..5033340b5f2e 100644
--- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp
+++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp
@@ -226,9 +226,9 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh
SetImplicitPeriodic(true);
- /* Store the initial CFL number for all grid points. */
+ /*--- Store the initial CFL number for all grid points. ---*/
- const su2double CFL = config->GetCFL(MGLevel);
+ const su2double CFL = config->GetCFL(MGLevel)*config->GetCFLRedCoeff_Turb();
for (iPoint = 0; iPoint < nPoint; iPoint++) {
nodes->SetLocalCFL(iPoint, CFL);
}
diff --git a/SU2_CFD/src/variables/CDiscAdjFEAVariable.cpp b/SU2_CFD/src/variables/CDiscAdjFEAVariable.cpp
index 7d18ec94d241..1fe4bd72edf2 100644
--- a/SU2_CFD/src/variables/CDiscAdjFEAVariable.cpp
+++ b/SU2_CFD/src/variables/CDiscAdjFEAVariable.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -32,8 +32,6 @@
CDiscAdjFEAVariable::CDiscAdjFEAVariable(const su2double *disp, const su2double *vel, const su2double *accel, unsigned long npoint,
unsigned long ndim, unsigned long nvar, bool unsteady, CConfig *config) : CVariable(npoint, ndim, nvar, config) {
- bool fsi = config->GetFSI_Simulation();
-
Solution_Direct.resize(nPoint,nVar);
Sensitivity.resize(nPoint,nDim) = su2double(0.0);
@@ -42,14 +40,7 @@ CDiscAdjFEAVariable::CDiscAdjFEAVariable(const su2double *disp, const su2double
for (unsigned long iVar = 0; iVar < nVar; iVar++)
Solution(iPoint,iVar) = disp[iVar];
- if (fsi) {
- Cross_Term_Derivative.resize(nPoint,nDim) = su2double(0.0);
- Geometry_CrossTerm_Derivative.resize(nPoint,nDim) = su2double(0.0);
-
- Solution_BGS.resize(nPoint,nDim) = su2double(0.0);
- }
-
- if (config->GetMultizone_Problem()) {
+ if (config->GetMultizone_Problem() && config->GetDiscrete_Adjoint()) {
External.resize(nPoint,nVar) = su2double(0.0);
}
diff --git a/SU2_CFD/src/variables/CDiscAdjMeshBoundVariable.cpp b/SU2_CFD/src/variables/CDiscAdjMeshBoundVariable.cpp
index 6e232a06264d..29851b845afe 100644
--- a/SU2_CFD/src/variables/CDiscAdjMeshBoundVariable.cpp
+++ b/SU2_CFD/src/variables/CDiscAdjMeshBoundVariable.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -29,11 +29,15 @@
#include "../../include/variables/CDiscAdjMeshBoundVariable.hpp"
-CDiscAdjMeshBoundVariable::CDiscAdjMeshBoundVariable(unsigned long npoint, unsigned long ndim, CConfig *config) :
- CVariable(npoint, ndim, config) {
+CDiscAdjMeshBoundVariable::CDiscAdjMeshBoundVariable(unsigned long npoint, unsigned long ndim, CConfig *config) {
+ nPoint = npoint;
+ nVar = ndim;
nDim = ndim;
+ /*--- Allocate the solution array. ---*/
+ Solution.resize(nPoint,nVar) = su2double(0.0);
+
VertexMap.Reset(nPoint);
}
@@ -63,3 +67,7 @@ void CDiscAdjMeshBoundVariable::AllocateBoundaryVariables(CConfig *config) {
void CDiscAdjMeshBoundVariable::Set_BGSSolution_k() {
Solution_BGS_k = Bound_Disp_Sens;
}
+
+void CDiscAdjMeshBoundVariable::Restore_BGSSolution_k() {
+ Bound_Disp_Sens = Solution_BGS_k;
+}
diff --git a/SU2_CFD/src/variables/CDiscAdjVariable.cpp b/SU2_CFD/src/variables/CDiscAdjVariable.cpp
index 4730e4bc3695..9244aa1a49b3 100644
--- a/SU2_CFD/src/variables/CDiscAdjVariable.cpp
+++ b/SU2_CFD/src/variables/CDiscAdjVariable.cpp
@@ -6,7 +6,7 @@
*
* SU2 Project Website: https://su2code.github.io
*
- * The SU2 Project is maintained by the SU2 Foundation
+ * The SU2 Project is maintained by the SU2 Foundation
* (http://su2foundation.org)
*
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
@@ -56,17 +56,12 @@ CDiscAdjVariable::CDiscAdjVariable(const su2double* sol, unsigned long npoint, u
Geometry_Direct.resize(nPoint,nDim) = su2double(0.0);
Solution_Geometry.resize(nPoint,nDim) = su2double(1e-16);
Solution_Geometry_Old.resize(nPoint,nDim) = su2double(0.0);
- Cross_Term_Derivative.resize(nPoint,nVar) = su2double(0.0);
- Geometry_CrossTerm_Derivative.resize(nPoint,nDim) = su2double(0.0);
- Geometry_CrossTerm_Derivative_Flow.resize(nPoint,nDim) = su2double(0.0);
- Solution_BGS.resize(nPoint,nVar) = su2double(0.0);
Solution_Geometry_BGS_k.resize(nPoint,nDim) = su2double(0.0);
}
- if (config->GetMultizone_Problem()) {
+ if (config->GetMultizone_Problem() && config->GetDiscrete_Adjoint()) {
External.resize(nPoint,nVar) = su2double(0.0);
- Solution_BGS.resize(nPoint,nVar) = su2double(0.0);
}
}
diff --git a/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform.cfg b/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform.cfg
index 2387eaa95368..cd2eda32fb8e 100644
--- a/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform.cfg
+++ b/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform.cfg
@@ -14,9 +14,6 @@ UNST_RESTART_ITER= 5
UNST_ADJOINT_ITER= 5
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
-DEFORM_MESH= YES
-MARKER_DEFORM_MESH= (airfoil)
-
SURFACE_MOVEMENT= DEFORMING
MARKER_MOVING= ( airfoil )
SURFACE_MOTION_ORIGIN= (0.248 0.0 0.0)
@@ -101,6 +98,7 @@ DEFORM_NONLINEAR_ITER= 1
DEFORM_CONSOLE_OUTPUT= YES
DEFORM_LINEAR_SOLVER_ERROR= 0.000000001
DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
+DEFORM_POISSONS_RATIO= 1e6
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
CONV_CRITERIA= RESIDUAL
diff --git a/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform_ad.cfg b/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform_ad.cfg
index c07290c332fa..ec65eb46b12e 100644
--- a/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform_ad.cfg
+++ b/TestCases/disc_adj_euler/naca0012_pitching_def/inv_NACA0012_pitching_deform_ad.cfg
@@ -14,9 +14,6 @@ UNST_RESTART_ITER= 5
UNST_ADJOINT_ITER= 5
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
-DEFORM_MESH= YES
-MARKER_DEFORM_MESH= (airfoil)
-
SURFACE_MOVEMENT= DEFORMING
MARKER_MOVING= ( airfoil )
SURFACE_MOTION_ORIGIN= (0.248 0.0 0.0)
@@ -101,6 +98,7 @@ DEFORM_NONLINEAR_ITER= 1
DEFORM_CONSOLE_OUTPUT= YES
DEFORM_LINEAR_SOLVER_ERROR= 0.000000001
DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
+DEFORM_POISSONS_RATIO= 1e6
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
CONV_CRITERIA= RESIDUAL
diff --git a/TestCases/disc_adj_fsi/Airfoil_2d/configFEA.cfg b/TestCases/disc_adj_fsi/Airfoil_2d/configFEA.cfg
index 61069f8b033e..65d6aa959100 100755
--- a/TestCases/disc_adj_fsi/Airfoil_2d/configFEA.cfg
+++ b/TestCases/disc_adj_fsi/Airfoil_2d/configFEA.cfg
@@ -15,10 +15,6 @@ POISSON_RATIO= 0.35
MATERIAL_DENSITY= 2700.0
%
% Boundary conditions -------------------------------------------------- %
-% interface
-% this needs to appear before the normal load marker
-CONSERVATIVE_INTERPOLATION= NO
-% solid
MARKER_CLAMPED= ( clamped )
MARKER_FLUID_LOAD= ( pressure_side_s, suction_side_s )
%
@@ -40,8 +36,6 @@ BGS_RELAXATION= FIXED_PARAMETER
STAT_RELAX_PARAMETER= 1.0
% solid
INNER_ITER= 11
-% grid deformation
-DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
%
% In\Out --------------------------------------------------------------- %
MESH_FILENAME= mesh.su2
diff --git a/TestCases/disc_adj_fsi/Airfoil_2d/configFlow.cfg b/TestCases/disc_adj_fsi/Airfoil_2d/configFlow.cfg
index 917ebb6ec744..498b75828333 100755
--- a/TestCases/disc_adj_fsi/Airfoil_2d/configFlow.cfg
+++ b/TestCases/disc_adj_fsi/Airfoil_2d/configFlow.cfg
@@ -21,14 +21,7 @@ GAS_CONSTANT= 287.87
VISCOSITY_MODEL= CONSTANT_VISCOSITY
MU_CONSTANT= 1.716E-5
%
-% Solid properties ----------------------------------------------------- %
-MATERIAL_MODEL= NEO_HOOKEAN
-ELASTICITY_MODULUS= 7E9
-POISSON_RATIO= 0.35
-MATERIAL_DENSITY= 2700.0
-%
% Boundary conditions -------------------------------------------------- %
-% fluid
MARKER_FAR= ( farfield )
MARKER_EULER= ( leading_edge, pressure_side, suction_side)
MARKER_DEFORM_MESH= ( leading_edge, pressure_side, suction_side )
@@ -74,6 +67,8 @@ DEFORM_LINEAR_SOLVER= CONJUGATE_GRADIENT
DEFORM_LINEAR_SOLVER_PREC= ILU
DEFORM_LINEAR_SOLVER_ERROR= 1e-8
DEFORM_LINEAR_SOLVER_ITER= 1000
+DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
+DEFORM_POISSONS_RATIO= 1e6
%
% Convergence criteria ------------------------------------------------- %
% interaction
@@ -85,8 +80,6 @@ INNER_ITER= 51
CONV_CRITERIA= RESIDUAL
CONV_STARTITER= 0
CONV_RESIDUAL_MINVAL= -9
-% grid deformation
-DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
%
% In\Out --------------------------------------------------------------- %
MESH_FILENAME= mesh.su2
diff --git a/TestCases/disc_adj_fsi/config.cfg b/TestCases/disc_adj_fsi/config.cfg
index 97bc1d1a159f..35cf049125dd 100644
--- a/TestCases/disc_adj_fsi/config.cfg
+++ b/TestCases/disc_adj_fsi/config.cfg
@@ -4,8 +4,11 @@ CONFIG_LIST=(configFlow.cfg, configFEA.cfg)
MARKER_ZONE_INTERFACE = (UpperWall, UpperWallS, LowerWall, LowerWallS)
-ADJ_FSI= YES
-OUTER_ITER= 4
+OUTER_ITER= 7
MESH_FILENAME= mesh.su2
OBJECTIVE_FUNCTION = REFERENCE_GEOMETRY
+
+SCREEN_OUTPUT= OUTER_ITER, AVG_BGS_RES[0], RMS_ADJ_DENSITY[0], SENS_E[1], SENS_NU[1]
+
+%WRT_ZONE_CONV= YES
diff --git a/TestCases/disc_adj_fsi/configFEA.cfg b/TestCases/disc_adj_fsi/configFEA.cfg
index fcf4e2702a7a..8f94b025665d 100644
--- a/TestCases/disc_adj_fsi/configFEA.cfg
+++ b/TestCases/disc_adj_fsi/configFEA.cfg
@@ -45,7 +45,6 @@ NONLINEAR_FEM_SOLUTION_METHOD = NEWTON_RAPHSON
INNER_ITER= 5
MARKER_CLAMPED = ( Clamped_Right, Clamped_Left )
-MARKER_PRESSURE= ( LowerWallS, 0, UpperWallS, 0)
MARKER_FLUID_LOAD= ( LowerWallS, UpperWallS)
WRT_CON_FREQ= 1
diff --git a/TestCases/disc_adj_fsi/configFlow.cfg b/TestCases/disc_adj_fsi/configFlow.cfg
index 66554b755b7a..c05d1b748ee1 100644
--- a/TestCases/disc_adj_fsi/configFlow.cfg
+++ b/TestCases/disc_adj_fsi/configFlow.cfg
@@ -45,7 +45,9 @@ MARKER_HEATFLUX= ( Wall, 0.0, UpperWall, 0.0, LowerWall, 0.0)
MARKER_FAR = ( Farfield )
MARKER_PLOTTING= ( UpperWall, LowerWall, Wall)
MARKER_MONITORING= ( UpperWall, LowerWall, Wall)
-SURFACE_MOVEMENT= FLUID_STRUCTURE_STATIC
+
+DEFORM_MESH= YES
+MARKER_DEFORM_MESH= ( UpperWall, LowerWall )
WRT_CON_FREQ= 1
WRT_CON_FREQ_DUALTIME= 1
@@ -53,34 +55,32 @@ WRT_SOL_FREQ= 1
WRT_SOL_FREQ_DUALTIME= 5
DEFORM_STIFFNESS_TYPE = INVERSE_VOLUME
+DEFORM_POISSONS_RATIO = 1e6
DEFORM_LINEAR_SOLVER = CONJUGATE_GRADIENT
-
-DEFORM_LINEAR_SOLVER_PREC = JACOBI
-DEFORM_LINEAR_SOLVER_ERROR = 1E-5
-DEFORM_LINEAR_SOLVER_ITER = 5000
+DEFORM_LINEAR_SOLVER_PREC = ILU
+DEFORM_LINEAR_SOLVER_ERROR = 1E-8
+DEFORM_LINEAR_SOLVER_ITER = 1000
NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES
-CFL_NUMBER= 1.0
-RK_ALPHA_COEFF= ( 0.66667, 0.66667, 1.000000 )
+CFL_NUMBER= 100.0
LINEAR_SOLVER= FGMRES
LINEAR_SOLVER_PREC= LU_SGS
-LINEAR_SOLVER_ERROR= 1E-6
-LINEAR_SOLVER_ITER= 2
+LINEAR_SOLVER_ERROR= 1E-3
+LINEAR_SOLVER_ITER= 20
DISCADJ_LIN_SOLVER= FGMRES
-DISCADJ_LIN_PREC= JACOBI
+DISCADJ_LIN_PREC= ILU
CONV_NUM_METHOD_FLOW= ROE
MUSCL_FLOW= YES
SLOPE_LIMITER_FLOW= VENKATAKRISHNAN
VENKAT_LIMITER_COEFF= 1.0
-JST_SENSOR_COEFF=( 0.5, 0.02 )
TIME_DISCRE_FLOW= EULER_IMPLICIT
CONV_CRITERIA= RESIDUAL
CONV_RESIDUAL_MINVAL= -10
-CONV_STARTITER= 10
+CONV_STARTITER= 0
CONV_CAUCHY_ELEMS= 100
CONV_CAUCHY_EPS= 1E-5
diff --git a/TestCases/disc_adj_rans/naca0012/naca0012.cfg b/TestCases/disc_adj_rans/naca0012/naca0012.cfg
index 121f6adc3a08..dd94734aa705 100644
--- a/TestCases/disc_adj_rans/naca0012/naca0012.cfg
+++ b/TestCases/disc_adj_rans/naca0012/naca0012.cfg
@@ -5,7 +5,7 @@
% Author: Steffen Schotthöfer %
% Institution: TU Kaiserslautern %
% Date: Mar 16, 2017 %
-% File Version 7.0.2 "Blackbird" %
+% File Version 7.0.3 "Blackbird" %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg b/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg
index b78895338f5f..8c2c470dcb61 100644
--- a/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg
+++ b/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg
@@ -277,9 +277,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.1
-%
-% Relaxation coefficient
+CFL_REDUCTION_TURB= 1.0
%
%
% ----------------------- DESIGN VARIABLE PARAMETERS --------------------------%
diff --git a/TestCases/fea_fsi/Airfoil_RBF/config.cfg b/TestCases/fea_fsi/Airfoil_RBF/config.cfg
index 437ca3394f55..ddcf42c9b8e4 100755
--- a/TestCases/fea_fsi/Airfoil_RBF/config.cfg
+++ b/TestCases/fea_fsi/Airfoil_RBF/config.cfg
@@ -3,7 +3,7 @@
% Case description: 2D airfoil FSI with radial basis function interp. %
% Institution: Imperial College London %
% Date: 2015.08.12 %
-% File Version 6.2 "Falcon" %
+% File Version 7.0.2 "Blackbird" %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SOLVER = MULTIPHYSICS
diff --git a/TestCases/fea_fsi/Airfoil_RBF/configFEA.cfg b/TestCases/fea_fsi/Airfoil_RBF/configFEA.cfg
index 9817cd7ee435..8b1d3cd568b3 100644
--- a/TestCases/fea_fsi/Airfoil_RBF/configFEA.cfg
+++ b/TestCases/fea_fsi/Airfoil_RBF/configFEA.cfg
@@ -2,7 +2,7 @@
% SU2 configuration file %
% Case description: 2D airfoil FSI with radial basis function interp. %
% Institution: Imperial College London %
-% File Version 7.0.3 "Blackbird" %
+% File Version 7.0.3 "Blackbird" %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Interface options ---------------------------------------------------- %
@@ -12,6 +12,7 @@ CONSERVATIVE_INTERPOLATION = YES
KIND_RADIAL_BASIS_FUNCTION = WENDLAND_C2
RADIAL_BASIS_FUNCTION_PARAMETER = 0.015
RADIAL_BASIS_FUNCTION_POLYNOMIAL_TERM = YES
+RADIAL_BASIS_FUNCTION_PRUNE_TOLERANCE = 0
%
% Physics -------------------------------------------------------------- %
SOLVER= ELASTICITY
@@ -24,7 +25,6 @@ POISSON_RATIO= 0.35
MATERIAL_DENSITY= 2700.0
%
% Boundary conditions -------------------------------------------------- %
-MARKER_PRESSURE= ( pressure_side_s,0.0, suction_side_s,0.0 )
MARKER_FLUID_LOAD= ( pressure_side_s, suction_side_s, clamped )
MARKER_CLAMPED= ( clamped )
%
diff --git a/TestCases/fea_fsi/Airfoil_RBF/configFlow.cfg b/TestCases/fea_fsi/Airfoil_RBF/configFlow.cfg
index ee7ee68509f4..92fadd9fe108 100644
--- a/TestCases/fea_fsi/Airfoil_RBF/configFlow.cfg
+++ b/TestCases/fea_fsi/Airfoil_RBF/configFlow.cfg
@@ -2,7 +2,7 @@
% SU2 configuration file %
% Case description: 2D airfoil FSI with radial basis function interp. %
% Institution: Imperial College London %
-% File Version 7.0.3 "Blackbird" %
+% File Version 7.0.3 "Blackbird" %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Interface options ---------------------------------------------------- %
@@ -20,16 +20,20 @@ KIND_INTERPOLATION = RADIAL_BASIS_FUNCTION
% orders) and you have issues, break up the interface or use "NO" for
% consistent interpolation.
CONSERVATIVE_INTERPOLATION = YES
-% Wendland provides good results and produces a nice diagonally dominant
-% interpolation kernel, other options:
+% Wendland is usually the best option due to sparser and better
+% conditioned interpolation kernel, other options:
% INV_MULTI_QUADRIC; GAUSSIAN; THIN_PLATE_SPLINE; MULTI_QUADRIC
KIND_RADIAL_BASIS_FUNCTION = WENDLAND_C2
% The radius in meters, 2 times the largest cell size on the interface is
% a good compromise between accuracy and condition number of the kernel.
RADIAL_BASIS_FUNCTION_PARAMETER = 0.015
-% Recommended as it recovers rigid body motion, only requires a few more
-% matrix products... feel free to explore though!
+% Polynomial terms to recover rigid body motion, this requires slightly
+% more computation and reduces the sparsity of the interpolation matrix.
RADIAL_BASIS_FUNCTION_POLYNOMIAL_TERM = YES
+% The number of donor points per target point is reduced by prunning away
+% small interpolation coefficients (making the interp. matrix sparse).
+% This tolerance is relative to the maximum absolute coefficient.
+RADIAL_BASIS_FUNCTION_PRUNE_TOLERANCE = 0
%
% Physics -------------------------------------------------------------- %
SOLVER= EULER
@@ -82,10 +86,11 @@ MG_DAMP_RESTRICTION= 0.75
MG_DAMP_PROLONGATION= 0.75
%
% Grid deformation ----------------------------------------------------- %
-SURFACE_MOVEMENT= FLUID_STRUCTURE_STATIC
-MARKER_MOVING= ( leading_edge, pressure_side, suction_side )
+DEFORM_MESH= YES
+MARKER_DEFORM_MESH= ( leading_edge, pressure_side, suction_side )
DEFORM_NONLINEAR_ITER= 1
DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
+DEFORM_POISSONS_RATIO= 1e6
DEFORM_CONSOLE_OUTPUT= NO
%
% Linear solvers ------------------------------------------------------- %
diff --git a/TestCases/fea_fsi/WallChannel_2d/configFSI_2D.cfg b/TestCases/fea_fsi/WallChannel_2d/configFSI_2D.cfg
deleted file mode 100644
index 9d1cd59e1af1..000000000000
--- a/TestCases/fea_fsi/WallChannel_2d/configFSI_2D.cfg
+++ /dev/null
@@ -1,108 +0,0 @@
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% SU2 configuration file %
-% Case description: Fluid Structure Interaction - Wall in channel %
-% Author: R.Sanchez %
-% Institution: Imperial College London %
-% Date: 2016.02.01 %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-MULTIZONE=YES
-TIME_ITER=3
-TIME_STEP= 0.005
-RESTART_ITER=2
-
-
-SURFACE_MOVEMENT=FLUID_STRUCTURE
-SOLVER= FLUID_STRUCTURE_INTERACTION
-FSI_FLUID_PROBLEM = NAVIER_STOKES
-FSI_STRUCTURAL_PROBLEM = ELASTICITY
-MATH_PROBLEM= DIRECT
-RESTART_SOL= YES
-WRT_BINARY_RESTART= NO
-READ_BINARY_RESTART= NO
-RESTART_ITER= 2
-FSI_ITER= 5
-MARKER_ZONE_INTERFACE = (wallUpwF, wallUpwS, wallUpperF, wallUpperS, wallDownF, wallDownS)
-CONSERVATIVE_INTERPOLATION = YES
-BGS_RELAXATION = FIXED_PARAMETER
-STAT_RELAX_PARAMETER= 0.5
-CONV_RESIDUAL_MINVAL_FSI= -8
-TIME_MARCHING= DUAL_TIME_STEPPING-2ND_ORDER
-MAX_TIME= 4.01
-INNER_ITER= 50
-KIND_TURB_MODEL= NONE
-AOA= 0.0
-SIDESLIP_ANGLE= 0.0
-REYNOLDS_NUMBER= 10
-MACH_NUMBER = 0.2
-MACH_MOTION = 0.2
-INIT_OPTION = TD_CONDITIONS
-FREESTREAM_OPTION = DENSITY_FS
-FREESTREAM_DENSITY = 1.0
-FREESTREAM_PRESSURE = 17.85714286
-FREESTREAM_TEMPERATURE = 0.062207438
-VISCOSITY_MODEL = CONSTANT_VISCOSITY
-MU_CONSTANT = 1.6E-3
-REF_ORIGIN_MOMENT_X = 0.00
-REF_ORIGIN_MOMENT_Y = 0.00
-REF_ORIGIN_MOMENT_Z = 0.00
-REF_LENGTH= 0.016
-REF_AREA= 0.016
-REYNOLDS_LENGTH=0.016
-MARKER_HEATFLUX= ( wallUpwF, 0.0, wallDownF, 0.0, wallUpperF, 0.0)
-MARKER_INLET= ( inlet, 0.062207438, 18.36216288, 1.0, 0.0, 0.0 )
-MARKER_OUTLET= ( outlet, 17.85714286)
-MARKER_EULER= ( upper, lower )
-MARKER_PLOTTING= ( wallUpwF, wallDownF, wallUpperF )
-MARKER_MONITORING= ( wallUpwF, wallDownF, wallUpperF )
-NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES
-RK_ALPHA_COEFF= ( 0.66667, 0.66667, 1.000000 )
-LINEAR_SOLVER= FGMRES
-LINEAR_SOLVER_PREC= LU_SGS
-LINEAR_SOLVER_ERROR= 1E-6
-LINEAR_SOLVER_ITER= 2
-CONV_NUM_METHOD_FLOW= ROE
-MUSCL_FLOW= YES
-VENKAT_LIMITER_COEFF= 1.0
-JST_SENSOR_COEFF= ( 0.5, 0.02 )
-TIME_DISCRE_FLOW= EULER_IMPLICIT
-CONV_CRITERIA= RESIDUAL
-CONV_RESIDUAL_MINVAL= -10
-CONV_STARTITER= 10
-CONV_CAUCHY_ELEMS= 100
-CONV_CAUCHY_EPS= 1E-5
-ELASTICITY_MODULUS=5E4
-MATERIAL_DENSITY=50
-FORMULATION_ELASTICITY_2D = PLANE_STRESS
-POISSON_RATIO=0.3
-DYNAMIC_ANALYSIS= YES
-DYN_TIME= 4.01
-TIME_DISCRE_FEA= NEWMARK_IMPLICIT
-NEWMARK_BETA=0.36
-NEWMARK_GAMMA=0.7
-GEOMETRIC_CONDITIONS= LARGE_DEFORMATIONS
-MATERIAL_MODEL= NEO_HOOKEAN
-NONLINEAR_FEM_INT_ITER = 10
-FSI_LINEAR_SOLVER_PREC_STRUC= LU_SGS
-FSI_LINEAR_SOLVER_ITER_STRUC = 1000
-MARKER_CLAMPED = ( clamped )
-MARKER_PRESSURE= ( wallDownS, 0.0, wallUpperS, 0.0, wallUpwS, 0.0)
-MESH_FILENAME= meshFSI_2D.su2
-DEFORM_NONLINEAR_ITER= 1
-DEFORM_LINEAR_SOLVER= FGMRES
-DEFORM_LINEAR_SOLVER_PREC= LU_SGS
-DEFORM_LINEAR_SOLVER_ITER= 500
-DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME
-MESH_FORMAT= SU2
-TABULAR_FORMAT= CSV
-WRT_CON_FREQ= 100
-WRT_CON_FREQ_DUALTIME= 100
-WRT_SOL_FREQ= 100
-WRT_SOL_FREQ_DUALTIME= 100
-VOLUME_FILENAME= results_flow
-RESTART_FILENAME= restart_flow.dat
-SOLUTION_FILENAME= solution_flow.dat
-VOLUME_STRUCTURE_FILENAME= results_wall
-RESTART_STRUCTURE_FILENAME= restart_wall.dat
-SOLUTION_STRUCTURE_FILENAME= solution_wall.dat
-WRT_SRF_SOL = NO
-WRT_CSV_SOL = NO
diff --git a/TestCases/fea_fsi/WallChannel_2d/configFlow.cfg b/TestCases/fea_fsi/WallChannel_2d/configFlow.cfg
index 82578ee2194c..2a5372db08f5 100644
--- a/TestCases/fea_fsi/WallChannel_2d/configFlow.cfg
+++ b/TestCases/fea_fsi/WallChannel_2d/configFlow.cfg
@@ -7,8 +7,8 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SOLVER= NAVIER_STOKES
-SURFACE_MOVEMENT = FLUID_STRUCTURE
-MARKER_MOVING=(wallUpwF, wallDownF, wallUpperF)
+DEFORM_MESH= YES
+MARKER_DEFORM_MESH= (wallUpwF, wallDownF, wallUpperF)
INNER_ITER=50
%SCREEN_OUTPUT=(TIME_ITER, OUTER_ITER, INNER_ITER, BGS_DENSITY, BGS_ENERGY)
@@ -70,6 +70,7 @@ DEFORM_LINEAR_SOLVER= FGMRES
DEFORM_LINEAR_SOLVER_PREC= LU_SGS
DEFORM_LINEAR_SOLVER_ITER= 500
DEFORM_STIFFNESS_TYPE= WALL_DISTANCE
+DEFORM_POISSONS_RATIO= 1e6
MESH_FORMAT= SU2
TABULAR_FORMAT= CSV
diff --git a/TestCases/harmonic_balance/hb_rans_preconditioning/davis.cfg b/TestCases/harmonic_balance/hb_rans_preconditioning/davis.cfg
index bff8e69fe862..e0c9e56e3e98 100644
--- a/TestCases/harmonic_balance/hb_rans_preconditioning/davis.cfg
+++ b/TestCases/harmonic_balance/hb_rans_preconditioning/davis.cfg
@@ -193,7 +193,7 @@ MUSCL_TURB= NO
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.4
+CFL_REDUCTION_TURB= 1.0
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
% Convergence criteria (CAUCHY, RESIDUAL)
diff --git a/TestCases/optimization_rans/pitching_naca64a010/turb_NACA64A010.cfg b/TestCases/optimization_rans/pitching_naca64a010/turb_NACA64A010.cfg
index 059c3b40aa07..a19a32213007 100644
--- a/TestCases/optimization_rans/pitching_naca64a010/turb_NACA64A010.cfg
+++ b/TestCases/optimization_rans/pitching_naca64a010/turb_NACA64A010.cfg
@@ -47,7 +47,7 @@ INNER_ITER= 2000
% Direct iteration number at which to begin unsteady adjoint
UNST_ADJOINT_ITER= 251
%
-% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION, FLUID_STRUCTURE)
+% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION)
GRID_MOVEMENT= RIGID_MOTION
%
% Mach number (non-dimensional, based on the mesh velocity and freestream vals.)
diff --git a/TestCases/optimization_rans/pitching_oneram6/turb_ONERAM6.cfg b/TestCases/optimization_rans/pitching_oneram6/turb_ONERAM6.cfg
index 9496fa6b29f5..ff80aa7d5421 100644
--- a/TestCases/optimization_rans/pitching_oneram6/turb_ONERAM6.cfg
+++ b/TestCases/optimization_rans/pitching_oneram6/turb_ONERAM6.cfg
@@ -68,7 +68,7 @@ UNST_ADJOINT_ITER= 176
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
% Type of dynamic mesh (NONE, RIGID_MOTION, DEFORMING, ROTATING_FRAME,
-% MOVING_WALL, FLUID_STRUCTURE, AEROELASTIC, EXTERNAL)
+% MOVING_WALL, AEROELASTIC, EXTERNAL)
GRID_MOVEMENT= RIGID_MOTION
%
% Motion mach number (non-dimensional). Used for intitializing a viscous flow
diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py
index 46b4bf50cb4b..ab735293c8aa 100644
--- a/TestCases/parallel_regression.py
+++ b/TestCases/parallel_regression.py
@@ -834,7 +834,7 @@ def main():
Jones_tc.cfg_dir = "turbomachinery/APU_turbocharger"
Jones_tc.cfg_file = "Jones.cfg"
Jones_tc.test_iter = 5
- Jones_tc.test_vals = [-5.300315, 0.365966, 44.731500, 2.271371] #last 4 columns
+ Jones_tc.test_vals = [-5.280323, 0.379654, 44.725390, 2.271597] #last 4 columns
Jones_tc.su2_exec = "parallel_computation.py -f"
Jones_tc.timeout = 1600
Jones_tc.new_output = False
@@ -846,7 +846,7 @@ def main():
Jones_tc_rst.cfg_dir = "turbomachinery/APU_turbocharger"
Jones_tc_rst.cfg_file = "Jones_rst.cfg"
Jones_tc_rst.test_iter = 5
- Jones_tc_rst.test_vals = [-4.626438, -1.570818, 34.014660, 10.187090] #last 4 columns
+ Jones_tc_rst.test_vals = [-4.625216, -1.569511, 34.013520, 10.187670] #last 4 columns
Jones_tc_rst.su2_exec = "parallel_computation.py -f"
Jones_tc_rst.timeout = 1600
Jones_tc_rst.new_output = False
@@ -1039,7 +1039,7 @@ def main():
fsi2d.cfg_dir = "fea_fsi/WallChannel_2d"
fsi2d.cfg_file = "configFSI.cfg"
fsi2d.test_iter = 4
- fsi2d.test_vals = [4.000000, 0.000000, -3.801272, -4.123968] #last 4 columns
+ fsi2d.test_vals = [4, 0, -3.764076, -4.081142] #last 4 columns
fsi2d.su2_exec = "parallel_computation_fsi.py -f"
fsi2d.timeout = 1600
fsi2d.multizone= True
@@ -1052,7 +1052,7 @@ def main():
stat_fsi.cfg_dir = "fea_fsi/stat_fsi"
stat_fsi.cfg_file = "config.cfg"
stat_fsi.test_iter = 7
- stat_fsi.test_vals = [-3.313322, -4.963786, 0.000000, 46.000000] #last 5 columns
+ stat_fsi.test_vals = [-3.313612, -4.957573, 0.000000, 7.000000] #last 4 columns
stat_fsi.su2_exec = "mpirun -n 2 SU2_CFD"
stat_fsi.multizone = True
stat_fsi.timeout = 1600
@@ -1064,7 +1064,7 @@ def main():
dyn_fsi.cfg_dir = "fea_fsi/dyn_fsi"
dyn_fsi.cfg_file = "config.cfg"
dyn_fsi.test_iter = 4
- dyn_fsi.test_vals = [-4.389734, -4.060117, 0.000000, 64.000000] #last 5 columns
+ dyn_fsi.test_vals = [-4.379832, -4.005999, 0.000000, 0.000000] #last 4 columns
dyn_fsi.multizone = True
dyn_fsi.unsteady = True
dyn_fsi.su2_exec = "mpirun -n 2 SU2_CFD"
@@ -1077,7 +1077,7 @@ def main():
stat_fsi_restart.cfg_dir = "fea_fsi/stat_fsi"
stat_fsi_restart.cfg_file = "config_restart.cfg"
stat_fsi_restart.test_iter = 1
- stat_fsi_restart.test_vals = [-3.422307, -4.212725, 0.000000, 46.000000] #last 5 columns
+ stat_fsi_restart.test_vals = [-3.422425, -4.289201, 0.000000, 27.000000] #last 4 columns
stat_fsi_restart.su2_exec = "mpirun -n 2 SU2_CFD"
stat_fsi_restart.multizone = True
stat_fsi_restart.timeout = 1600
@@ -1196,7 +1196,7 @@ def main():
pywrapper_fsi2d.cfg_dir = "fea_fsi/WallChannel_2d"
pywrapper_fsi2d.cfg_file = "configFSI.cfg"
pywrapper_fsi2d.test_iter = 4
- pywrapper_fsi2d.test_vals = [4.000000, 0.000000, -3.801272, -4.123968] #last 4 columns
+ pywrapper_fsi2d.test_vals = [4, 0, -3.764076, -4.081142] #last 4 columns
pywrapper_fsi2d.su2_exec = "mpirun -np 2 SU2_CFD.py --nZone 2 --fsi True --parallel -f"
pywrapper_fsi2d.timeout = 1600
pywrapper_fsi2d.unsteady = True
diff --git a/TestCases/parallel_regression_AD.py b/TestCases/parallel_regression_AD.py
index d4f45d6d12f2..7b13db9c3fb1 100644
--- a/TestCases/parallel_regression_AD.py
+++ b/TestCases/parallel_regression_AD.py
@@ -290,8 +290,8 @@ def main():
discadj_fsi = TestCase('discadj_fsi')
discadj_fsi.cfg_dir = "disc_adj_fsi"
discadj_fsi.cfg_file = "config.cfg"
- discadj_fsi.test_iter = 3000
- discadj_fsi.test_vals = [0.958848,-0.157601,2.726147,1.798362] #last 4 columns
+ discadj_fsi.test_iter = 6
+ discadj_fsi.test_vals = [6, -1.563852, -3.075167, 4.3991e-04, -1.0631] #last 5 columns
discadj_fsi.su2_exec = "mpirun -n 2 SU2_CFD_AD"
discadj_fsi.timeout = 1600
discadj_fsi.tol = 0.00001
@@ -302,7 +302,7 @@ def main():
discadj_fsi2.cfg_dir = "disc_adj_fsi/Airfoil_2d"
discadj_fsi2.cfg_file = "config.cfg"
discadj_fsi2.test_iter = 8
- discadj_fsi2.test_vals = [-5.070991, -2.5239e-13] #last 2 columns
+ discadj_fsi2.test_vals = [-5.071028, -2.5253e-13] #last 2 columns
discadj_fsi2.su2_exec = "mpirun -n 2 SU2_CFD_AD"
discadj_fsi2.timeout = 1600
discadj_fsi2.tol = 1e-16
diff --git a/TestCases/py_wrapper/disc_adj_flow/mesh_disp_sens/configAD_flow.cfg b/TestCases/py_wrapper/disc_adj_flow/mesh_disp_sens/configAD_flow.cfg
index 6f8f5a69fecb..4d48d3472619 100644
--- a/TestCases/py_wrapper/disc_adj_flow/mesh_disp_sens/configAD_flow.cfg
+++ b/TestCases/py_wrapper/disc_adj_flow/mesh_disp_sens/configAD_flow.cfg
@@ -155,6 +155,7 @@ WRT_CON_FREQ_DUALTIME= 1
DEFORM_MESH = YES
DEFORM_STIFFNESS_TYPE = WALL_DISTANCE
+DEFORM_POISSONS_RATIO = 1E6
DEFORM_LINEAR_SOLVER = CONJUGATE_GRADIENT
DEFORM_LINEAR_SOLVER_PREC = ILU
diff --git a/TestCases/rotating/caradonna_tung/rot_caradonna_tung.cfg b/TestCases/rotating/caradonna_tung/rot_caradonna_tung.cfg
index a3ffdc5846f9..f05f99a3a2d1 100644
--- a/TestCases/rotating/caradonna_tung/rot_caradonna_tung.cfg
+++ b/TestCases/rotating/caradonna_tung/rot_caradonna_tung.cfg
@@ -55,7 +55,7 @@ REF_AREA= 1.0
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
%
% Type of dynamic mesh (NONE, RIGID_MOTION, DEFORMING, ROTATING_FRAME,
-% MOVING_WALL, FLUID_STRUCTURE, AEROELASTIC, EXTERNAL)
+% MOVING_WALL, AEROELASTIC, EXTERNAL)
GRID_MOVEMENT= ROTATING_FRAME
%
% Motion mach number (non-dimensional). Used for intitializing a viscous flow
diff --git a/TestCases/rotating/naca0012/rot_NACA0012.cfg b/TestCases/rotating/naca0012/rot_NACA0012.cfg
index cc41bb495bcc..bd0c3e67e78c 100644
--- a/TestCases/rotating/naca0012/rot_NACA0012.cfg
+++ b/TestCases/rotating/naca0012/rot_NACA0012.cfg
@@ -55,7 +55,7 @@ REF_AREA= 1.0
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
%
% Type of dynamic mesh (NONE, RIGID_MOTION, DEFORMING, ROTATING_FRAME,
-% MOVING_WALL, FLUID_STRUCTURE, AEROELASTIC, EXTERNAL)
+% MOVING_WALL, AEROELASTIC, EXTERNAL)
GRID_MOVEMENT= ROTATING_FRAME
%
% Motion mach number (non-dimensional). Used for intitializing a viscous flow
diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py
index 86a705ca84c1..9faba6f1c4b9 100644
--- a/TestCases/serial_regression.py
+++ b/TestCases/serial_regression.py
@@ -995,7 +995,7 @@ def main():
Jones_tc.cfg_dir = "turbomachinery/APU_turbocharger"
Jones_tc.cfg_file = "Jones.cfg"
Jones_tc.test_iter = 5
- Jones_tc.test_vals = [-5.300315, 0.365965, 44.731520, 2.271338] #last 4 columns
+ Jones_tc.test_vals = [-5.280323, 0.379653, 44.725410, 2.271564] #last 4 columns
Jones_tc.su2_exec = "SU2_CFD"
Jones_tc.new_output = False
Jones_tc.timeout = 1600
@@ -1007,7 +1007,7 @@ def main():
Jones_tc_rst.cfg_dir = "turbomachinery/APU_turbocharger"
Jones_tc_rst.cfg_file = "Jones_rst.cfg"
Jones_tc_rst.test_iter = 5
- Jones_tc_rst.test_vals = [-4.626481, -1.570875, 34.015260, 10.187090] #last 4 columns
+ Jones_tc_rst.test_vals = [-4.625262, -1.569571, 34.014130, 10.187660] #last 4 columns
Jones_tc_rst.su2_exec = "SU2_CFD"
Jones_tc_rst.new_output = False
Jones_tc_rst.timeout = 1600
@@ -1230,7 +1230,7 @@ def main():
fsi2d.cfg_dir = "fea_fsi/WallChannel_2d"
fsi2d.cfg_file = "configFSI.cfg"
fsi2d.test_iter = 4
- fsi2d.test_vals = [4.000000, 0.000000, -3.801272, -4.123970] #last 4 columns
+ fsi2d.test_vals = [4, 0, -3.764077, -4.081143] #last 4 columns
fsi2d.su2_exec = "SU2_CFD"
fsi2d.timeout = 1600
fsi2d.multizone = True
@@ -1243,7 +1243,7 @@ def main():
stat_fsi.cfg_dir = "fea_fsi/stat_fsi"
stat_fsi.cfg_file = "config.cfg"
stat_fsi.test_iter = 7
- stat_fsi.test_vals = [-3.323551, -4.982863, 0.000000, 47.000000] #last 5 columns
+ stat_fsi.test_vals = [-3.326934, -4.981505, 0.000000, 7.000000] #last 5 columns
stat_fsi.su2_exec = "SU2_CFD"
stat_fsi.timeout = 1600
stat_fsi.multizone = True
@@ -1255,7 +1255,7 @@ def main():
stat_fsi_restart.cfg_dir = "fea_fsi/stat_fsi"
stat_fsi_restart.cfg_file = "config_restart.cfg"
stat_fsi_restart.test_iter = 1
- stat_fsi_restart.test_vals = [-3.407098, -4.248366, 0.000000, 47.000000] #last 5 columns
+ stat_fsi_restart.test_vals = [-3.407486, -4.339837, 0.000000, 27.000000] #last 5 columns
stat_fsi_restart.multizone = True
stat_fsi_restart.su2_exec = "SU2_CFD"
stat_fsi_restart.timeout = 1600
@@ -1267,7 +1267,7 @@ def main():
dyn_fsi.cfg_dir = "fea_fsi/dyn_fsi"
dyn_fsi.cfg_file = "config.cfg"
dyn_fsi.test_iter = 4
- dyn_fsi.test_vals = [-4.389732, -4.060110, 0.000000, 59.000000] #last 5 columns
+ dyn_fsi.test_vals = [-4.379829, -4.005994, 0.000000, 0.000000] #last 5 columns
dyn_fsi.multizone = True
dyn_fsi.unsteady = True
dyn_fsi.su2_exec = "SU2_CFD"
@@ -1280,7 +1280,7 @@ def main():
airfoilRBF.cfg_dir = "fea_fsi/Airfoil_RBF"
airfoilRBF.cfg_file = "config.cfg"
airfoilRBF.test_iter = 1
- airfoilRBF.test_vals = [1.000000, -2.980686, -4.866015]
+ airfoilRBF.test_vals = [1.000000, -2.791154, -4.961536]
airfoilRBF.su2_exec = "SU2_CFD"
airfoilRBF.timeout = 1600
airfoilRBF.multizone = True
@@ -1772,7 +1772,7 @@ def main():
pywrapper_fsi2d.cfg_dir = "fea_fsi/WallChannel_2d"
pywrapper_fsi2d.cfg_file = "configFSI.cfg"
pywrapper_fsi2d.test_iter = 4
- pywrapper_fsi2d.test_vals = [4.000000, 0.000000, -3.801272, -4.123970] #last 4 columns
+ pywrapper_fsi2d.test_vals = [4, 0, -3.764077, -4.081143] #last 4 columns
pywrapper_fsi2d.su2_exec = "SU2_CFD.py --nZone 2 --fsi True -f"
pywrapper_fsi2d.new_output = True
pywrapper_fsi2d.unsteady = True
diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py
index 6b752bd27c1e..a6f3749bd66c 100644
--- a/TestCases/serial_regression_AD.py
+++ b/TestCases/serial_regression_AD.py
@@ -270,8 +270,8 @@ def main():
discadj_fsi = TestCase('discadj_fsi')
discadj_fsi.cfg_dir = "disc_adj_fsi"
discadj_fsi.cfg_file = "config.cfg"
- discadj_fsi.test_iter = 3000
- discadj_fsi.test_vals = [0.958848,-0.157601,2.726147,1.798362] #last 4 columns
+ discadj_fsi.test_iter = 6
+ discadj_fsi.test_vals = [6, -1.572702, -3.084381, 4.3990e-04, -1.0631] #last 5 columns
discadj_fsi.su2_exec = "SU2_CFD_AD"
discadj_fsi.timeout = 1600
discadj_fsi.tol = 0.00001
diff --git a/TestCases/sliding_interface/bars_SST_2D/bars.cfg b/TestCases/sliding_interface/bars_SST_2D/bars.cfg
index 3d1403d9049d..0dcd5df09109 100644
--- a/TestCases/sliding_interface/bars_SST_2D/bars.cfg
+++ b/TestCases/sliding_interface/bars_SST_2D/bars.cfg
@@ -252,7 +252,7 @@ SLOPE_LIMITER_TURB= NONE
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.10
+CFL_REDUCTION_TURB= 1.0
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
%
diff --git a/TestCases/sliding_interface/single_stage/single_stage_NN.cfg b/TestCases/sliding_interface/single_stage/single_stage_NN.cfg
index e8bc15224ebd..1abaa6406bdf 100644
--- a/TestCases/sliding_interface/single_stage/single_stage_NN.cfg
+++ b/TestCases/sliding_interface/single_stage/single_stage_NN.cfg
@@ -217,12 +217,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.01
-%
-% Relaxation coefficient
-%
-%
-%
+CFL_REDUCTION_TURB= 1.0
%
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
% Convergence criteria (CAUCHY, RESIDUAL)
diff --git a/TestCases/sliding_interface/single_stage/single_stage_WA.cfg b/TestCases/sliding_interface/single_stage/single_stage_WA.cfg
index 69d11c02dfdf..97bb4f23ef55 100644
--- a/TestCases/sliding_interface/single_stage/single_stage_WA.cfg
+++ b/TestCases/sliding_interface/single_stage/single_stage_WA.cfg
@@ -194,9 +194,6 @@ SLOPE_LIMITER_FLOW= NONE
% Time discretization (RUNGE-KUTTA_EXPLICIT, EULER_IMPLICIT, EULER_EXPLICIT)
TIME_DISCRE_FLOW= EULER_IMPLICIT
%
-% Relaxation coefficient
-%
-%
%
%
% -------------------- TURBULENT NUMERICAL METHOD DEFINITION ------------------%
@@ -215,10 +212,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.01
-%
-% Relaxation coefficient
-%
+CFL_REDUCTION_TURB= 1.0
%
%
%
diff --git a/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg b/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
index dc86b6875204..4cedf5e074f3 100755
--- a/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
+++ b/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
@@ -260,9 +260,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.5
-%
-% Relaxation coefficient
+CFL_REDUCTION_TURB= 1.0
%
%
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
diff --git a/TestCases/turbomachinery/centrifugal_blade/centrifugal_blade.cfg b/TestCases/turbomachinery/centrifugal_blade/centrifugal_blade.cfg
index ce87e1e5f692..c853f7b86215 100755
--- a/TestCases/turbomachinery/centrifugal_blade/centrifugal_blade.cfg
+++ b/TestCases/turbomachinery/centrifugal_blade/centrifugal_blade.cfg
@@ -295,10 +295,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.01
-%
-% Relaxation coefficient
-%
+CFL_REDUCTION_TURB= 1.0
%
%
%
diff --git a/TestCases/turbomachinery/centrifugal_stage/centrifugal_stage.cfg b/TestCases/turbomachinery/centrifugal_stage/centrifugal_stage.cfg
index e650e733a9f1..459b20d83c31 100755
--- a/TestCases/turbomachinery/centrifugal_stage/centrifugal_stage.cfg
+++ b/TestCases/turbomachinery/centrifugal_stage/centrifugal_stage.cfg
@@ -303,10 +303,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.01
-%
-% Relaxation coefficient
-%
+CFL_REDUCTION_TURB= 1.0
%
%
%
diff --git a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
index dc3a5cbd334b..bb6a6c7c7896 100644
--- a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
+++ b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
@@ -268,9 +268,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.1
-%
-% Relaxation coefficient
+CFL_REDUCTION_TURB= 1.0
%
%
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
diff --git a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
index f0d310451960..726b79cc58a7 100644
--- a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
+++ b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
@@ -273,9 +273,7 @@ SLOPE_LIMITER_TURB= VENKATAKRISHNAN
TIME_DISCRE_TURB= EULER_IMPLICIT
%
% Reduction factor of the CFL coefficient in the turbulence problem
-CFL_REDUCTION_TURB= 0.1
-%
-% Relaxation coefficient
+CFL_REDUCTION_TURB= 1.0
%
%
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
diff --git a/TestCases/unsteady/pitching_naca64a010_euler/pitching_NACA64A010.cfg b/TestCases/unsteady/pitching_naca64a010_euler/pitching_NACA64A010.cfg
index 905d243d3ea2..a204e3fec6de 100644
--- a/TestCases/unsteady/pitching_naca64a010_euler/pitching_NACA64A010.cfg
+++ b/TestCases/unsteady/pitching_naca64a010_euler/pitching_NACA64A010.cfg
@@ -47,7 +47,7 @@ INNER_ITER= 110
UNST_ADJOINT_ITER= 251
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
-% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION, FLUID_STRUCTURE)
+% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION)
%GRID_MOVEMENT= RIGID_MOTION
%
SURFACE_MOVEMENT= DEFORMING
diff --git a/TestCases/unsteady/pitching_naca64a010_rans/turb_NACA64A010.cfg b/TestCases/unsteady/pitching_naca64a010_rans/turb_NACA64A010.cfg
index 88396845b588..5d8b61115771 100644
--- a/TestCases/unsteady/pitching_naca64a010_rans/turb_NACA64A010.cfg
+++ b/TestCases/unsteady/pitching_naca64a010_rans/turb_NACA64A010.cfg
@@ -47,7 +47,7 @@ INNER_ITER= 2000
% Direct iteration number at which to begin unsteady adjoint
UNST_ADJOINT_ITER= 251
%
-% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION, FLUID_STRUCTURE)
+% Type of mesh motion (NONE, FLUTTER, RIGID_MOTION)
GRID_MOVEMENT= RIGID_MOTION
%
% Mach number (non-dimensional, based on the mesh velocity and freestream vals.)