diff --git a/Common/include/config_structure.hpp b/Common/include/config_structure.hpp
index f33d0e72bed1..c6c71f3382ce 100644
--- a/Common/include/config_structure.hpp
+++ b/Common/include/config_structure.hpp
@@ -1076,8 +1076,8 @@ class CConfig {
bool Compute_Entropy; /*!< \brief Whether or not to compute the entropy in the fluid model. */
bool Use_Lumped_MassMatrix_DGFEM; /*!< \brief Whether or not to use the lumped mass matrix for DGFEM. */
bool Jacobian_Spatial_Discretization_Only; /*!< \brief Flag to know if only the exact Jacobian of the spatial discretization must be computed. */
- bool Compute_Average; /*!< \brief Whether or not to compute averages for unsteady simulations in FV or DG solver. */
-
+ bool Compute_Average; /*!< \brief Whether or not to compute averages for unsteady simulations in FV or DG solver. */
+ unsigned short Comm_Level; /*!< \brief Level of MPI communications to be performed. */
ofstream *ConvHistFile; /*!< \brief Store the pointer to each history file */
bool Time_Domain; /*!< \brief Determines if the multizone problem is solved in time-domain */
@@ -1399,7 +1399,7 @@ class CConfig {
/*!
* \brief Constructor of the class which reads the input file.
*/
- CConfig(char case_filename[MAX_STRING_SIZE], unsigned short val_software, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_nDim, unsigned short verb_level);
+ CConfig(char case_filename[MAX_STRING_SIZE], unsigned short val_software, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_nDim, bool verb_high);
/*!
* \brief Constructor of the class which reads the input file.
@@ -1444,15 +1444,6 @@ class CConfig {
* \return Total number of domains in the grid file.
*/
static unsigned short GetnDim(string val_mesh_filename, unsigned short val_format);
-
- /*!
- * \brief Determine whether there are periodic BCs in the grid.
- * \param[in] val_mesh_filename - Name of the file with the grid information.
- * \param[in] val_format - Format of the file with the grid information.
- * \param[in] config - Definition of the particular problem.
- * \return Boolean for whether or not there are periodic BCs in the grid.
- */
- static bool GetPeriodic(string val_mesh_filename, unsigned short val_format, CConfig *config);
/*!
* \brief Initializes pointers to null
@@ -5985,7 +5976,7 @@ class CConfig {
* \return TRUE if there is a rotational frame; otherwise FALSE.
*/
bool GetAxisymmetric(void);
-
+
/*!
* \brief Get information about the axisymmetric frame.
* \return TRUE if there is a rotational frame; otherwise FALSE.
@@ -6560,7 +6551,7 @@ class CConfig {
* \param[in] translate - Pointer to a vector containing the coordinate of the center.
*/
void SetPeriodicTranslate(unsigned short val_index, su2double* translate);
-
+
/*!
* \brief Get the translation vector for a periodic transformation.
* \param[in] val_index - Index corresponding to the periodic transformation.
@@ -9140,6 +9131,12 @@ class CConfig {
su2double GetMax_Time(void);
/*!
+ * \brief Get the level of MPI communications to be performed.
+ * \return Level of MPI communications.
+ */
+ unsigned short GetComm_Level(void);
+
+ /*
* \brief Check if the mesh read supports multiple zones.
* \return YES if multiple zones can be contained in the mesh file.
*/
@@ -9168,6 +9165,7 @@ class CConfig {
* \return YES if the forces breakdown file is written.
*/
bool GetWrt_ForcesBreakdown(void);
+
};
#include "config_structure.inl"
diff --git a/Common/include/config_structure.inl b/Common/include/config_structure.inl
index c34f86d3b321..86bdc333a51a 100644
--- a/Common/include/config_structure.inl
+++ b/Common/include/config_structure.inl
@@ -2014,6 +2014,8 @@ inline ofstream* CConfig::GetHistFile(void) { return ConvHistFile; }
inline void CConfig::SetHistFile(ofstream *HistFile) { ConvHistFile = HistFile; }
+inline unsigned short CConfig::GetComm_Level(void) { return Comm_Level; }
+
inline bool CConfig::GetTopology_Optimization(void) const { return topology_optimization; }
inline string CConfig::GetTopology_Optim_FileName(void) const { return top_optim_output_file; }
diff --git a/Common/include/dual_grid_structure.hpp b/Common/include/dual_grid_structure.hpp
index 2f6a3348d2ab..b840e41436f6 100644
--- a/Common/include/dual_grid_structure.hpp
+++ b/Common/include/dual_grid_structure.hpp
@@ -147,10 +147,12 @@ class CPoint : public CDualGrid {
vector Point; /*!< \brief Points surrounding the central node of the control volume. */
vector Edge; /*!< \brief Edges that set up a control volume. */
su2double *Volume; /*!< \brief Volume or Area of the control volume in 3D and 2D. */
+ su2double Periodic_Volume; /*!< \brief Missing component of volume or area of a control volume on a periodic marker in 3D and 2D. */
bool Domain, /*!< \brief Indicates if a point must be computed or belong to another boundary */
Boundary, /*!< \brief To see if a point belong to the boundary (including MPI). */
PhysicalBoundary, /*!< \brief To see if a point belong to the physical boundary (without includin MPI). */
- SolidBoundary; /*!< \brief To see if a point belong to the physical boundary (without includin MPI). */
+ SolidBoundary, /*!< \brief To see if a point belong to the physical boundary (without includin MPI). */
+ PeriodicBoundary; /*!< \brief To see if a point belongs to a periodic boundary (without including MPI). */
long *Vertex; /*!< \brief Index of the vertex that correspond which the control volume (we need one for each marker in the same node). */
su2double *Coord, /*!< \brief vector with the coordinates of the node. */
*Coord_Old, /*!< \brief Old coordinates vector for geometry smoothing. */
@@ -403,6 +405,18 @@ class CPoint : public CDualGrid {
*/
su2double GetVolume(void);
+ /*!
+ * \brief Get the missing component of area or volume for a control volume on a periodic marker.
+ * \return Periodic component of area or volume for a control volume on a periodic marker.
+ */
+ su2double GetPeriodicVolume(void);
+
+ /*!
+ * \brief Set the missing component of area or volume for a control volume on a periodic marker.
+ * \param[in] val_volume - Value of the volume from the missing components of the CV on the periodic marker.
+ */
+ void SetPeriodicVolume(su2double val_volume);
+
/*!
* \brief Get the maximum cell-center to cell-center length.
* \return The maximum cell-center to cell-center length.
@@ -451,6 +465,12 @@ class CPoint : public CDualGrid {
*/
void SetSolidBoundary(bool val_boundary);
+ /*!
+ * \brief Set if a point belongs to a periodic boundary.
+ * \param[in] val_boundary - TRUE if the point belongs to a periodic boundary; otherwise FALSE.
+ */
+ void SetPeriodicBoundary(bool val_boundary);
+
/*!
* \brief Provides information about if a point belong to the physical boundaries (without MPI).
* \return TRUE if the point belong to the boundary; otherwise FALSE.
@@ -463,6 +483,12 @@ class CPoint : public CDualGrid {
*/
bool GetSolidBoundary(void);
+ /*!
+ * \brief Provides information about if a point belongs to a periodic boundary (without MPI).
+ * \return TRUE if the point belongs to a periodic boundary; otherwise FALSE.
+ */
+ bool GetPeriodicBoundary(void);
+
/*!
* \brief Set a color to the point that comes from the grid partitioning.
* \note Each domain has a different color.
diff --git a/Common/include/dual_grid_structure.inl b/Common/include/dual_grid_structure.inl
index ef9cc517199a..b8acefdcf32b 100644
--- a/Common/include/dual_grid_structure.inl
+++ b/Common/include/dual_grid_structure.inl
@@ -80,6 +80,10 @@ inline unsigned long CPoint::GetPoint(unsigned short val_point) { return Point[v
inline su2double CPoint::GetVolume (void) { return Volume[0]; }
+inline su2double CPoint::GetPeriodicVolume (void) { return Periodic_Volume; }
+
+inline void CPoint::SetPeriodicVolume (su2double val_volume) { Periodic_Volume = val_volume; }
+
inline su2double CPoint::GetMaxLength(void) {return MaxLength;}
inline bool CPoint::GetMove (void) { return Move; }
@@ -96,6 +100,10 @@ inline void CPoint::SetSolidBoundary(bool val_boundary) { SolidBoundary = val_bo
inline bool CPoint::GetSolidBoundary(void) { return SolidBoundary; }
+inline void CPoint::SetPeriodicBoundary(bool val_boundary) { PeriodicBoundary = val_boundary; }
+
+inline bool CPoint::GetPeriodicBoundary(void) { return PeriodicBoundary; }
+
inline void CPoint::AddVolume (su2double val_Volume) { Volume[0] += val_Volume; }
inline void CPoint::SetVolume (su2double val_Volume) { Volume[0] = val_Volume; }
diff --git a/Common/include/geometry_structure.hpp b/Common/include/geometry_structure.hpp
index 7a546284b32e..e22edd8f3f40 100644
--- a/Common/include/geometry_structure.hpp
+++ b/Common/include/geometry_structure.hpp
@@ -354,7 +354,6 @@ class CGeometry {
vector XCoordList; /*!< \brief Vector containing points appearing on a single plane */
CPrimalGrid*** newBound; /*!< \brief Boundary vector for new periodic elements (primal grid information). */
unsigned long *nNewElem_Bound; /*!< \brief Number of new periodic elements of the boundary. */
-
/*--- Partitioning-specific variables ---*/
map Global_to_Local_Elem;
@@ -371,6 +370,48 @@ class CGeometry {
#endif
#endif
+ /*--- Data structures for point-to-point MPI communications. ---*/
+
+ int countPerPoint; /*!< \brief Maximum number of pieces of data sent per vertex in point-to-point comms. */
+ int nP2PSend; /*!< \brief Number of sends during point-to-point comms. */
+ int nP2PRecv; /*!< \brief Number of receives during point-to-point comms. */
+ int *nPoint_P2PSend; /*!< \brief Data structure holding number of vertices for each send in point-to-point comms. */
+ int *nPoint_P2PRecv; /*!< \brief Data structure holding number of vertices for each recv in point-to-point comms. */
+ int *Neighbors_P2PSend; /*!< \brief Data structure holding the ranks of the neighbors for point-to-point send comms. */
+ int *Neighbors_P2PRecv; /*!< \brief Data structure holding the ranks of the neighbors for point-to-point recv comms. */
+ map P2PSend2Neighbor; /*!< \brief Data structure holding the reverse mapping of the ranks of the neighbors for point-to-point send comms. */
+ map P2PRecv2Neighbor; /*!< \brief Data structure holding the reverse mapping of the ranks of the neighbors for point-to-point recv comms. */
+ unsigned long *Local_Point_P2PSend; /*!< \brief Data structure holding the local index of all vertices to be sent in point-to-point comms. */
+ unsigned long *Local_Point_P2PRecv; /*!< \brief Data structure holding the local index of all vertices to be received in point-to-point comms. */
+ su2double *bufD_P2PRecv; /*!< \brief Data structure for su2double point-to-point receive. */
+ su2double *bufD_P2PSend; /*!< \brief Data structure for su2double point-to-point send. */
+ unsigned short *bufS_P2PRecv; /*!< \brief Data structure for unsigned long point-to-point receive. */
+ unsigned short *bufS_P2PSend; /*!< \brief Data structure for unsigned long point-to-point send. */
+ SU2_MPI::Request *req_P2PSend; /*!< \brief Data structure for point-to-point send requests. */
+ SU2_MPI::Request *req_P2PRecv; /*!< \brief Data structure for point-to-point recv requests. */
+
+ /*--- Data structures for periodic communications. ---*/
+
+ int countPerPeriodicPoint; /*!< \brief Maximum number of pieces of data sent per vertex in periodic comms. */
+ int nPeriodicSend; /*!< \brief Number of sends during periodic comms. */
+ int nPeriodicRecv; /*!< \brief Number of receives during periodic comms. */
+ int *nPoint_PeriodicSend; /*!< \brief Data structure holding number of vertices for each send in periodic comms. */
+ int *nPoint_PeriodicRecv; /*!< \brief Data structure holding number of vertices for each recv in periodic comms. */
+ int *Neighbors_PeriodicSend; /*!< \brief Data structure holding the ranks of the neighbors for periodic send comms. */
+ int *Neighbors_PeriodicRecv; /*!< \brief Data structure holding the ranks of the neighbors for periodic recv comms. */
+ map PeriodicSend2Neighbor; /*!< \brief Data structure holding the reverse mapping of the ranks of the neighbors for periodic send comms. */
+ map PeriodicRecv2Neighbor; /*!< \brief Data structure holding the reverse mapping of the ranks of the neighbors for periodic recv comms. */
+ unsigned long *Local_Point_PeriodicSend; /*!< \brief Data structure holding the local index of all vertices to be sent in periodic comms. */
+ unsigned long *Local_Point_PeriodicRecv; /*!< \brief Data structure holding the local index of all vertices to be received in periodic comms. */
+ unsigned long *Local_Marker_PeriodicSend; /*!< \brief Data structure holding the local index of the periodic marker for a particular vertex to be sent in periodic comms. */
+ unsigned long *Local_Marker_PeriodicRecv; /*!< \brief Data structure holding the local index of the periodic marker for a particular vertex to be received in periodic comms. */
+ su2double *bufD_PeriodicRecv; /*!< \brief Data structure for su2double periodic receive. */
+ su2double *bufD_PeriodicSend; /*!< \brief Data structure for su2double periodic send. */
+ unsigned short *bufS_PeriodicRecv; /*!< \brief Data structure for unsigned long periodic receive. */
+ unsigned short *bufS_PeriodicSend; /*!< \brief Data structure for unsigned long periodic send. */
+ SU2_MPI::Request *req_PeriodicSend; /*!< \brief Data structure for periodic send requests. */
+ SU2_MPI::Request *req_PeriodicRecv; /*!< \brief Data structure for periodic recv requests. */
+
/*!
* \brief Constructor of the class.
*/
@@ -380,7 +421,86 @@ class CGeometry {
* \brief Destructor of the class.
*/
virtual ~CGeometry(void);
+
+ /*!
+ * \brief Routine to launch non-blocking recvs only for all periodic communications. Note that this routine is called by any class that has loaded data into the generic communication buffers.
+ * \brief Routine to set up persistent data structures for point-to-point MPI communications.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void PreprocessP2PComms(CGeometry *geometry, CConfig *config);
+
+ /*!
+ * \brief Routine to allocate buffers for point-to-point MPI communications. Also called to dynamically reallocate if not enough memory is found for comms during runtime.
+ * \param[in] val_countPerPoint - Maximum count of the data type per vertex in point-to-point comms, e.g., nPrimvarGrad*nDim.
+ */
+ void AllocateP2PComms(unsigned short val_countPerPoint);
+
+ /*!
+ * \brief Routine to launch non-blocking recvs only for all point-to-point communication with neighboring partitions. Note that this routine is called by any class that has loaded data into the generic communication buffers.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ * \param[in] val_reverse - Boolean controlling forward or reverse communication between neighbors.
+ */
+ void PostP2PRecvs(CGeometry *geometry, CConfig *config, unsigned short commType, bool val_reverse);
+
+ /*!
+ * \brief Routine to launch a single non-blocking send once the buffer is loaded for a point-to-point commucation. Note that this routine is called by any class that has loaded data into the generic communication buffers.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ * \param[in] val_iMessage - Index of the message in the order they are stored.
+ * \param[in] val_reverse - Boolean controlling forward or reverse communication between neighbors.
+ */
+ void PostP2PSends(CGeometry *geometry, CConfig *config, unsigned short commType, int val_iMessage, bool val_reverse);
+
+ /*!
+ * \brief Routine to set up persistent data structures for periodic communications.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void PreprocessPeriodicComms(CGeometry *geometry, CConfig *config);
+
+ /*!
+ * \brief Routine to allocate buffers for periodic communications. Also called to dynamically reallocate if not enough memory is found for comms during runtime.
+ * \param[in] val_countPerPeriodicPoint - Maximum count of the data type per vertex in periodic comms, e.g., nPrimvarGrad*nDim.
+ */
+ void AllocatePeriodicComms(unsigned short val_countPerPeriodicPoint);
+ /*!
+ * \brief Routine to launch non-blocking recvs only for all periodic communication with neighboring partitions. Note that this routine is called by any class that has loaded data into the generic communication buffers.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ */
+ void PostPeriodicRecvs(CGeometry *geometry, CConfig *config, unsigned short commType);
+
+ /*!
+ * \brief Routine to launch a single non-blocking send once the buffer is loaded for a periodic commucation. Note that this routine is called by any class that has loaded data into the generic communication buffers.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ * \param[in] val_iMessage - Index of the message in the order they are stored.
+ */
+ void PostPeriodicSends(CGeometry *geometry, CConfig *config, unsigned short commType, int val_iMessage);
+
+ /*!
+ * \brief Routine to load a geometric quantity into the data structures for MPI point-to-point communication and to launch non-blocking sends and recvs for all point-to-point communication with neighboring partitions.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ */
+ void InitiateComms(CGeometry *geometry, CConfig *config, unsigned short commType);
+
+ /*!
+ * \brief Routine to complete the set of non-blocking communications launched by InitiateComms() and unpacking of the data into the geometry class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be unpacked.
+ */
+ void CompleteComms(CGeometry *geometry, CConfig *config, unsigned short commType);
+
/*!
* \brief Get number of coordinates.
* \return Number of coordinates.
@@ -715,6 +835,12 @@ class CGeometry {
*/
virtual void MatchInterface(CConfig *config);
+ /*!
+ * \brief A virtual member.
+ * \param[in] config - Definition of the particular problem.
+ */
+ virtual void MatchPeriodic(CConfig *config, unsigned short val_periodic);
+
/*!
* \brief A virtual member.
* \param[in] config - Definition of the particular problem.
@@ -1766,14 +1892,14 @@ class CPhysicalGeometry : public CGeometry {
* \param[in] sendReq - Array of MPI recv requests.
* \param[in] countPerElem - Pieces of data per element communicated.
*/
- void InitiateComms(void *bufSend,
- int *nElemSend,
- SU2_MPI::Request *sendReq,
- void *bufRecv,
- int *nElemRecv,
- SU2_MPI::Request *recvReq,
- unsigned short countPerElem,
- unsigned short commType);
+ void InitiateCommsAll(void *bufSend,
+ int *nElemSend,
+ SU2_MPI::Request *sendReq,
+ void *bufRecv,
+ int *nElemRecv,
+ SU2_MPI::Request *recvReq,
+ unsigned short countPerElem,
+ unsigned short commType);
/*!
* \brief Routine to complete the set of non-blocking communications launched with InitiateComms() with MPI_Waitany().
@@ -1782,10 +1908,10 @@ class CPhysicalGeometry : public CGeometry {
* \param[in] nRecvs - Number of receives to be completed.
* \param[in] sendReq - Array of MPI recv requests.
*/
- void CompleteComms(int nSends,
- SU2_MPI::Request *sendReq,
- int nRecvs,
- SU2_MPI::Request *recvReq);
+ void CompleteCommsAll(int nSends,
+ SU2_MPI::Request *sendReq,
+ int nRecvs,
+ SU2_MPI::Request *recvReq);
/*!
* \brief Set the send receive boundaries of the grid.
@@ -1986,6 +2112,13 @@ void UpdateTurboVertex(CConfig *config,unsigned short val_iZone, unsigned short
* \param[in] config - Definition of the particular problem.
*/
void MatchInterface(CConfig *config);
+
+ /*!
+ * \brief Mach the periodic boundary conditions.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] val_periodic - Index of the first periodic face in a pair.
+ */
+ void MatchPeriodic(CConfig *config, unsigned short val_periodic);
/*!
* \brief Set boundary vertex structure of the control volume.
@@ -2745,6 +2878,13 @@ class CMultiGridGeometry : public CGeometry {
*/
void MatchInterface(CConfig *config);
+ /*!
+ * \brief Mach the periodic boundary conditions.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] val_periodic - Index of the first periodic face in a pair.
+ */
+ void MatchPeriodic(CConfig *config, unsigned short val_periodic);
+
/*!
* \brief Set boundary vertex structure of the agglomerated control volume.
* \param[in] config - Definition of the particular problem.
diff --git a/Common/include/geometry_structure.inl b/Common/include/geometry_structure.inl
index a241b9097cd3..1bd420774a90 100644
--- a/Common/include/geometry_structure.inl
+++ b/Common/include/geometry_structure.inl
@@ -305,6 +305,8 @@ inline void CGeometry::MatchActuator_Disk(CConfig *config) { }
inline void CGeometry::MatchInterface(CConfig *config) { }
+inline void CGeometry::MatchPeriodic(CConfig *config, unsigned short val_periodic) { }
+
inline void CGeometry::SetBoundControlVolume(CConfig *config, unsigned short action) { }
inline void CGeometry::SetBoundControlVolume(CConfig *config, CGeometry *geometry, unsigned short action) { }
diff --git a/Common/include/linear_solvers_structure.hpp b/Common/include/linear_solvers_structure.hpp
index 8f6336ca979e..5a2273af99a6 100644
--- a/Common/include/linear_solvers_structure.hpp
+++ b/Common/include/linear_solvers_structure.hpp
@@ -191,10 +191,11 @@ class CSysSolve {
* \param[in] tol - tolerance with which to solve the system
* \param[in] m - maximum size of the search subspace
* \param[in] monitoring - turn on priting residuals from solver to screen.
+ * \param[in] config - Definition of the particular problem.
*/
unsigned long CG_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
CPreconditioner & precond, su2double tol,
- unsigned long m, su2double *residual, bool monitoring);
+ unsigned long m, su2double *residual, bool monitoring, CConfig *config);
/*!
* \brief Flexible Generalized Minimal Residual method
@@ -206,10 +207,11 @@ class CSysSolve {
* \param[in] m - maximum size of the search subspace
* \param[in] residual
* \param[in] monitoring - turn on priting residuals from solver to screen.
+ * \param[in] config - Definition of the particular problem.
*/
unsigned long FGMRES_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
CPreconditioner & precond, su2double tol,
- unsigned long m, su2double *residual, bool monitoring);
+ unsigned long m, su2double *residual, bool monitoring, CConfig *config);
/*!
* \brief Biconjugate Gradient Stabilized Method (BCGSTAB)
@@ -221,10 +223,11 @@ class CSysSolve {
* \param[in] m - maximum size of the search subspace
* \param[in] residual
* \param[in] monitoring - turn on priting residuals from solver to screen.
+ * \param[in] config - Definition of the particular problem.
*/
unsigned long BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
CPreconditioner & precond, su2double tol,
- unsigned long m, su2double *residual, bool monitoring);
+ unsigned long m, su2double *residual, bool monitoring, CConfig *config);
/*!
* \brief Solve the linear system using a Krylov subspace method
diff --git a/Common/include/matrix_structure.hpp b/Common/include/matrix_structure.hpp
index 14ca59ffdb25..756ec439daa2 100644
--- a/Common/include/matrix_structure.hpp
+++ b/Common/include/matrix_structure.hpp
@@ -158,6 +158,30 @@ class CSysMatrix {
*/
void SetValZero(void);
+ /*!
+ * \brief Routine to load a vector quantity into the data structures for MPI point-to-point communication and to launch non-blocking sends and recvs.
+ * \param[in] x - CSysVector holding the array of data.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ */
+ void InitiateComms(CSysVector & x,
+ CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType);
+
+ /*!
+ * \brief Routine to complete the set of non-blocking communications launched by InitiateComms() and unpacking of the data in the vector.
+ * \param[in] x - CSysVector holding the array of data.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be unpacked.
+ */
+ void CompleteComms(CSysVector & x,
+ CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType);
+
/*!
* \brief Copies the block (i, j) of the matrix-by-blocks structure in the internal variable *block.
* \param[in] block_i - Indexes of the block in the matrix-by-blocks structure.
@@ -273,7 +297,7 @@ class CSysMatrix {
* \param[in] i - Index of the row.
*/
void DeleteValsRowi(unsigned long i);
-
+
/*!
* \brief Recursive definition of determinate using expansion by minors. Written by Paul Bourke
* \param[in] a - Matrix to compute the determinant.
diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp
index aa6b761eb129..f8d3dba1b9c0 100644
--- a/Common/include/option_structure.hpp
+++ b/Common/include/option_structure.hpp
@@ -1950,6 +1950,73 @@ static const map Input_Ref_Map = CCreateMap Comm_Map = CCreateMap
+("NONE", COMM_NONE)
+("MINIMAL", COMM_MINIMAL)
+("FULL", COMM_FULL);
+
+/*
* \brief types of filter kernels, initially intended for structural topology optimization applications
*/
enum ENUM_FILTER_KERNEL {
diff --git a/Common/src/config_structure.cpp b/Common/src/config_structure.cpp
index 74cb2f7eb65d..4ca1b9ef0807 100644
--- a/Common/src/config_structure.cpp
+++ b/Common/src/config_structure.cpp
@@ -57,7 +57,7 @@ vector GEMM_Profile_MaxTime; /*!< \brief Maximum time spent for thi
#include "../include/ad_structure.hpp"
#include "../include/toolboxes/printing_toolbox.hpp"
-CConfig::CConfig(char case_filename[MAX_STRING_SIZE], unsigned short val_software, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_nDim, unsigned short verb_level) {
+CConfig::CConfig(char case_filename[MAX_STRING_SIZE], unsigned short val_software, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_nDim, bool verb_high) {
/*--- Store MPI rank and size ---*/
@@ -86,7 +86,7 @@ CConfig::CConfig(char case_filename[MAX_STRING_SIZE], unsigned short val_softwar
/*--- Configuration file output ---*/
- if ((rank == MASTER_NODE) && (verb_level == VERB_HIGH) && (val_iZone == 0))
+ if ((rank == MASTER_NODE) && verb_high && (val_iZone == 0))
SetOutput(val_software, val_iZone);
}
@@ -340,22 +340,6 @@ unsigned short CConfig::GetnDim(string val_mesh_filename, unsigned short val_for
return (unsigned short) nDim;
}
-
-bool CConfig::GetPeriodic(string val_mesh_filename,
- unsigned short val_format,
- CConfig *config) {
-
- bool isPeriodic = false;
-
- /*--- For now, assume that if we have periodic BCs in the config, that
- the user's intent is for there to be periodic BCs in the mesh too. ---*/
-
- if (config->GetnMarker_Periodic() > 0) isPeriodic = true;
-
- return isPeriodic;
-
-}
-
void CConfig::SetPointersNull(void) {
Marker_CfgFile_GeoEval = NULL; Marker_All_GeoEval = NULL;
@@ -436,18 +420,13 @@ void CConfig::SetPointersNull(void) {
Engine_Power = NULL; Engine_NetThrust = NULL; Engine_GrossThrust = NULL;
Engine_Area = NULL; EngineInflow_Target = NULL;
- Periodic_Translate = NULL; Periodic_Rotation = NULL; Periodic_Center = NULL;
- Periodic_Translation = NULL; Periodic_RotAngles = NULL; Periodic_RotCenter = NULL;
-
Dirichlet_Value = NULL; Exhaust_Temperature_Target = NULL; Exhaust_Temperature = NULL;
Exhaust_Pressure_Target = NULL; Inlet_Ttotal = NULL; Inlet_Ptotal = NULL;
Inlet_FlowDir = NULL; Inlet_Temperature = NULL; Inlet_Pressure = NULL;
Inlet_Velocity = NULL; Inflow_Mach = NULL; Inflow_Pressure = NULL;
Exhaust_Pressure = NULL; Outlet_Pressure = NULL; Isothermal_Temperature= NULL;
Heat_Flux = NULL; Displ_Value = NULL; Load_Value = NULL;
- FlowLoad_Value = NULL; Periodic_RotCenter = NULL; Periodic_RotAngles = NULL;
- Periodic_Translation = NULL; Periodic_Center = NULL; Periodic_Rotation = NULL;
- Periodic_Translate = NULL;
+ FlowLoad_Value = NULL;
ElasticityMod = NULL; PoissonRatio = NULL; MaterialDensity = NULL;
@@ -539,11 +518,14 @@ void CConfig::SetPointersNull(void) {
Plunging_Ampl_X = NULL; Plunging_Ampl_Y = NULL; Plunging_Ampl_Z = NULL;
RefOriginMoment_X = NULL; RefOriginMoment_Y = NULL; RefOriginMoment_Z = NULL;
MoveMotion_Origin = NULL;
+
+ /*--- Periodic BC pointers. ---*/
+
Periodic_Translate = NULL; Periodic_Rotation = NULL; Periodic_Center = NULL;
Periodic_Translation= NULL; Periodic_RotAngles = NULL; Periodic_RotCenter = NULL;
-
/* Harmonic Balance Frequency pointer */
+
Omega_HB = NULL;
/*--- Initialize some default arrays to NULL. ---*/
@@ -1696,7 +1678,9 @@ void CConfig::SetConfig_Options(unsigned short val_iZone, unsigned short val_nZo
/*!\brief CONSOLE_OUTPUT_VERBOSITY
* \n DESCRIPTION: Verbosity level for console output \ingroup Config*/
addEnumOption("CONSOLE_OUTPUT_VERBOSITY", Console_Output_Verb, Verb_Map, VERB_HIGH);
-
+ /*!\brief COMM_LEVEL
+ * \n DESCRIPTION: Level of MPI communications during runtime \ingroup Config*/
+ addEnumOption("COMM_LEVEL", Comm_Level, Comm_Map, COMM_FULL);
/*!\par CONFIG_CATEGORY: Dynamic mesh definition \ingroup Config*/
/*--- Options related to dynamic meshes ---*/
@@ -4300,6 +4284,27 @@ void CConfig::SetPostprocessing(unsigned short val_software, unsigned short val_
Wrt_Projected_Sensitivity = true;
}
+ /*--- Delay the output until exit for minimal communication mode. ---*/
+
+ if (Comm_Level != COMM_FULL) {
+
+ /*--- Disable the use of Comm_Level = NONE until we have properly
+ implemented it. ---*/
+
+ if (Comm_Level == COMM_NONE)
+ SU2_MPI::Error("COMM_LEVEL = NONE not yet implemented.", CURRENT_FUNCTION);
+
+ Wrt_Sol_Freq = nExtIter+1;
+ Wrt_Sol_Freq_DualTime = nExtIter+1;
+
+ /*--- Write only the restart. ---*/
+
+ Wrt_Slice = false;
+ Wrt_Vol_Sol = false;
+ Wrt_Srf_Sol = false;
+ Wrt_Csv_Sol = false;
+ }
+
/*--- Check the conductivity model. Deactivate the turbulent component
if we are not running RANS. ---*/
@@ -7196,7 +7201,7 @@ CConfig::~CConfig(void) {
if (Periodic_Center != NULL) delete[] Periodic_Center;
if (Periodic_Rotation != NULL) delete[] Periodic_Rotation;
if (Periodic_Translate != NULL) delete[] Periodic_Translate;
-
+
if (MG_CorrecSmooth != NULL) delete[] MG_CorrecSmooth;
if (PlaneTag != NULL) delete[] PlaneTag;
if (CFL != NULL) delete[] CFL;
diff --git a/Common/src/dual_grid_structure.cpp b/Common/src/dual_grid_structure.cpp
index 582497a30774..c550c58bca82 100644
--- a/Common/src/dual_grid_structure.cpp
+++ b/Common/src/dual_grid_structure.cpp
@@ -89,7 +89,7 @@ CPoint::CPoint(unsigned short val_nDim, unsigned long val_globalindex, CConfig *
Boundary = false;
SolidBoundary = false;
PhysicalBoundary = false;
-
+ PeriodicBoundary = false;
/*--- Set the global index in the parallel simulation ---*/
GlobalIndex = val_globalindex;
@@ -132,6 +132,9 @@ CPoint::CPoint(unsigned short val_nDim, unsigned long val_globalindex, CConfig *
/*--- Intialize the value of the curvature ---*/
Curvature = 0.0;
+ /*--- Intialize the value of the periodic volume. ---*/
+ Periodic_Volume = 0.0;
+
}
CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, unsigned long val_globalindex, CConfig *config) : CDualGrid(2) {
@@ -182,6 +185,7 @@ CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, unsigned long val_g
Boundary = false;
SolidBoundary = false;
PhysicalBoundary = false;
+ PeriodicBoundary = false;
/*--- Set the color for mesh partitioning ---*/
color = 0;
@@ -226,6 +230,9 @@ CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, unsigned long val_g
/*--- Intialize the value of the curvature ---*/
Curvature = 0.0;
+ /*--- Intialize the value of the periodic volume. ---*/
+ Periodic_Volume = 0.0;
+
}
CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, su2double val_coord_2, unsigned long val_globalindex, CConfig *config) : CDualGrid(3) {
@@ -276,7 +283,7 @@ CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, su2double val_coord
Boundary = false;
SolidBoundary = false;
PhysicalBoundary = false;
-
+ PeriodicBoundary = false;
/*--- Set the color for mesh partitioning ---*/
color = 0;
@@ -322,6 +329,9 @@ CPoint::CPoint(su2double val_coord_0, su2double val_coord_1, su2double val_coord
/*--- Intialize the value of the curvature ---*/
Curvature = 0.0;
+ /*--- Intialize the value of the periodic volume. ---*/
+ Periodic_Volume = 0.0;
+
}
CPoint::~CPoint() {
diff --git a/Common/src/geometry_structure.cpp b/Common/src/geometry_structure.cpp
index f7a34f24f9e8..94fb4e7c2287 100644
--- a/Common/src/geometry_structure.cpp
+++ b/Common/src/geometry_structure.cpp
@@ -111,6 +111,59 @@ CGeometry::CGeometry(void) {
CustomBoundaryHeatFlux = NULL; //Customized heat flux wall
CustomBoundaryTemperature = NULL; //Customized temperature wall
+ /*--- MPI point-to-point data structures ---*/
+
+ nP2PSend = 0;
+ nP2PRecv = 0;
+
+ countPerPoint = 0;
+
+ bufD_P2PSend = NULL;
+ bufD_P2PRecv = NULL;
+
+ bufS_P2PSend = NULL;
+ bufS_P2PRecv = NULL;
+
+ req_P2PSend = NULL;
+ req_P2PRecv = NULL;
+
+ nPoint_P2PSend = NULL;
+ nPoint_P2PRecv = NULL;
+
+ Neighbors_P2PSend = NULL;
+ Neighbors_P2PRecv = NULL;
+
+ Local_Point_P2PSend = NULL;
+ Local_Point_P2PRecv = NULL;
+
+ /*--- MPI periodic data structures ---*/
+
+ nPeriodicSend = 0;
+ nPeriodicRecv = 0;
+
+ countPerPeriodicPoint = 0;
+
+ bufD_PeriodicSend = NULL;
+ bufD_PeriodicRecv = NULL;
+
+ bufS_PeriodicSend = NULL;
+ bufS_PeriodicRecv = NULL;
+
+ req_PeriodicSend = NULL;
+ req_PeriodicRecv = NULL;
+
+ nPoint_PeriodicSend = NULL;
+ nPoint_PeriodicRecv = NULL;
+
+ Neighbors_PeriodicSend = NULL;
+ Neighbors_PeriodicRecv = NULL;
+
+ Local_Point_PeriodicSend = NULL;
+ Local_Point_PeriodicRecv = NULL;
+
+ Local_Marker_PeriodicSend = NULL;
+ Local_Marker_PeriodicRecv = NULL;
+
}
CGeometry::~CGeometry(void) {
@@ -190,14 +243,1284 @@ CGeometry::~CGeometry(void) {
}
delete [] CustomBoundaryHeatFlux;
}
-
- if(CustomBoundaryTemperature != NULL){
- for(iMarker=0; iMarker < nMarker; iMarker++){
- if(CustomBoundaryTemperature[iMarker] != NULL) delete [] CustomBoundaryTemperature[iMarker];
+
+ if(CustomBoundaryTemperature != NULL){
+ for(iMarker=0; iMarker < nMarker; iMarker++){
+ if(CustomBoundaryTemperature[iMarker] != NULL) delete [] CustomBoundaryTemperature[iMarker];
+ }
+ delete [] CustomBoundaryTemperature;
+ }
+
+ /*--- Delete structures for MPI point-to-point communication. ---*/
+
+ if (bufD_P2PRecv != NULL) delete [] bufD_P2PRecv;
+ if (bufD_P2PSend != NULL) delete [] bufD_P2PSend;
+
+ if (bufS_P2PRecv != NULL) delete [] bufS_P2PRecv;
+ if (bufS_P2PSend != NULL) delete [] bufS_P2PSend;
+
+ if (req_P2PSend != NULL) delete [] req_P2PSend;
+ if (req_P2PRecv != NULL) delete [] req_P2PRecv;
+
+ if (nPoint_P2PRecv != NULL) delete [] nPoint_P2PRecv;
+ if (nPoint_P2PSend != NULL) delete [] nPoint_P2PSend;
+
+ if (Neighbors_P2PSend != NULL) delete [] Neighbors_P2PSend;
+ if (Neighbors_P2PRecv != NULL) delete [] Neighbors_P2PRecv;
+
+ if (Local_Point_P2PSend != NULL) delete [] Local_Point_P2PSend;
+ if (Local_Point_P2PRecv != NULL) delete [] Local_Point_P2PRecv;
+
+ /*--- Delete structures for MPI periodic communication. ---*/
+
+ if (bufD_PeriodicRecv != NULL) delete [] bufD_PeriodicRecv;
+ if (bufD_PeriodicSend != NULL) delete [] bufD_PeriodicSend;
+
+ if (bufS_PeriodicRecv != NULL) delete [] bufS_PeriodicRecv;
+ if (bufS_PeriodicSend != NULL) delete [] bufS_PeriodicSend;
+
+ if (req_PeriodicSend != NULL) delete [] req_PeriodicSend;
+ if (req_PeriodicRecv != NULL) delete [] req_PeriodicRecv;
+
+ if (nPoint_PeriodicRecv != NULL) delete [] nPoint_PeriodicRecv;
+ if (nPoint_PeriodicSend != NULL) delete [] nPoint_PeriodicSend;
+
+ if (Neighbors_PeriodicSend != NULL) delete [] Neighbors_PeriodicSend;
+ if (Neighbors_PeriodicRecv != NULL) delete [] Neighbors_PeriodicRecv;
+
+ if (Local_Point_PeriodicSend != NULL) delete [] Local_Point_PeriodicSend;
+ if (Local_Point_PeriodicRecv != NULL) delete [] Local_Point_PeriodicRecv;
+
+ if (Local_Marker_PeriodicSend != NULL) delete [] Local_Marker_PeriodicSend;
+ if (Local_Marker_PeriodicRecv != NULL) delete [] Local_Marker_PeriodicRecv;
+
+}
+
+void CGeometry::PreprocessP2PComms(CGeometry *geometry,
+ CConfig *config) {
+
+ /*--- We start with the send and receive lists already available in
+ the form of SEND_RECEIVE boundary markers. We will loop through
+ these markers and establish the neighboring ranks and number of
+ send/recv points per pair. We will store this information and set
+ up persistent data structures so that we can reuse them throughout
+ the calculation for any point-to-point communications. The goal
+ is to break the non-blocking comms into InitiateComms() and
+ CompleteComms() in separate routines so that we can overlap the
+ communication and computation to hide the communication latency. ---*/
+
+ /*--- Local variables. ---*/
+
+ unsigned short iMarker;
+ unsigned long nVertexS, nVertexR, iVertex, MarkerS, MarkerR;
+
+ int iRank, iSend, iRecv, count;
+
+ /*--- Create some temporary structures for tracking sends/recvs. ---*/
+
+ int *nPoint_Send_All = new int[size+1]; nPoint_Send_All[0] = 0;
+ int *nPoint_Recv_All = new int[size+1]; nPoint_Recv_All[0] = 0;
+ int *nPoint_Flag = new int[size];
+
+ for (iRank = 0; iRank < size; iRank++) {
+ nPoint_Send_All[iRank] = 0; nPoint_Recv_All[iRank] = 0; nPoint_Flag[iRank]= -1;
+ }
+ nPoint_Send_All[size] = 0; nPoint_Recv_All[size] = 0;
+
+ /*--- Loop through all of our SEND_RECEIVE markers and track
+ our sends with each rank. ---*/
+
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) &&
+ (config->GetMarker_All_SendRecv(iMarker) > 0)) {
+
+ /*--- Get the destination rank and number of points to send. ---*/
+
+ iRank = config->GetMarker_All_SendRecv(iMarker)-1;
+ nVertexS = geometry->nVertex[iMarker];
+
+ /*--- If we have not visited this element yet, increment our
+ number of elements that must be sent to a particular proc. ---*/
+
+ if ((nPoint_Flag[iRank] != (int)iMarker)) {
+ nPoint_Flag[iRank] = (int)iMarker;
+ nPoint_Send_All[iRank+1] += nVertexS;
+ }
+
+ }
+ }
+
+ delete [] nPoint_Flag;
+
+ /*--- Communicate the number of points to be sent/recv'd amongst
+ all processors. After this communication, each proc knows how
+ many cells it will receive from each other processor. ---*/
+
+ SU2_MPI::Alltoall(&(nPoint_Send_All[1]), 1, MPI_INT,
+ &(nPoint_Recv_All[1]), 1, MPI_INT, MPI_COMM_WORLD);
+
+ /*--- Prepare to send connectivities. First check how many
+ messages we will be sending and receiving. Here we also put
+ the counters into cumulative storage format to make the
+ communications simpler. ---*/
+
+ nP2PSend = 0; nP2PRecv = 0;
+
+ for (iRank = 0; iRank < size; iRank++) {
+ if ((iRank != rank) && (nPoint_Send_All[iRank+1] > 0)) nP2PSend++;
+ if ((iRank != rank) && (nPoint_Recv_All[iRank+1] > 0)) nP2PRecv++;
+
+ nPoint_Send_All[iRank+1] += nPoint_Send_All[iRank];
+ nPoint_Recv_All[iRank+1] += nPoint_Recv_All[iRank];
+ }
+
+ /*--- Allocate only as much memory as we need for the P2P neighbors. ---*/
+
+ nPoint_P2PSend = new int[nP2PSend+1]; nPoint_P2PSend[0] = 0;
+ nPoint_P2PRecv = new int[nP2PRecv+1]; nPoint_P2PRecv[0] = 0;
+
+ Neighbors_P2PSend = new int[nP2PSend];
+ Neighbors_P2PRecv = new int[nP2PRecv];
+
+ iSend = 0; iRecv = 0;
+ for (iRank = 0; iRank < size; iRank++) {
+
+ if ((nPoint_Send_All[iRank+1] > nPoint_Send_All[iRank]) && (iRank != rank)) {
+ Neighbors_P2PSend[iSend] = iRank;
+ nPoint_P2PSend[iSend+1] = nPoint_Send_All[iRank+1];
+ iSend++;
+ }
+
+ if ((nPoint_Recv_All[iRank+1] > nPoint_Recv_All[iRank]) && (iRank != rank)) {
+ Neighbors_P2PRecv[iRecv] = iRank;
+ nPoint_P2PRecv[iRecv+1] = nPoint_Recv_All[iRank+1];
+ iRecv++;
+ }
+
+ }
+
+ /*--- Create a reverse mapping of the message to the rank so that we
+ can quickly access the correct data in the buffers when receiving
+ messages dynamically. ---*/
+
+ P2PSend2Neighbor.clear();
+ for (iSend = 0; iSend < nP2PSend; iSend++)
+ P2PSend2Neighbor[Neighbors_P2PSend[iSend]] = iSend;
+
+ P2PRecv2Neighbor.clear();
+ for (iRecv = 0; iRecv < nP2PRecv; iRecv++)
+ P2PRecv2Neighbor[Neighbors_P2PRecv[iRecv]] = iRecv;
+
+ delete [] nPoint_Send_All;
+ delete [] nPoint_Recv_All;
+
+ /*--- Allocate the memory that we need for receiving the conn
+ values and then cue up the non-blocking receives. Note that
+ we do not include our own rank in the communications. We will
+ directly copy our own data later. ---*/
+
+ Local_Point_P2PSend = NULL;
+ Local_Point_P2PSend = new unsigned long[nPoint_P2PSend[nP2PSend]];
+ for (iSend = 0; iSend < nPoint_P2PSend[nP2PSend]; iSend++)
+ Local_Point_P2PSend[iSend] = 0;
+
+ Local_Point_P2PRecv = NULL;
+ Local_Point_P2PRecv = new unsigned long[nPoint_P2PRecv[nP2PRecv]];
+ for (iRecv = 0; iRecv < nPoint_P2PRecv[nP2PRecv]; iRecv++)
+ Local_Point_P2PRecv[iRecv] = 0;
+
+ /*--- We allocate the memory for communicating values in a later step
+ once we know the maximum packet size that we need to communicate. This
+ memory is deallocated and reallocated automatically in the case that
+ the previously allocated memory is not sufficient. ---*/
+
+ bufD_P2PSend = NULL;
+ bufD_P2PRecv = NULL;
+
+ bufS_P2PSend = NULL;
+ bufS_P2PRecv = NULL;
+
+ /*--- Allocate memory for the MPI requests if we need to communicate. ---*/
+
+ if (nP2PSend > 0) {
+ req_P2PSend = new SU2_MPI::Request[nP2PSend];
+ }
+ if (nP2PRecv > 0) {
+ req_P2PRecv = new SU2_MPI::Request[nP2PRecv];
+ }
+
+ /*--- Build lists of local index values for send. ---*/
+
+ count = 0;
+ for (iSend = 0; iSend < nP2PSend; iSend++) {
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) &&
+ (config->GetMarker_All_SendRecv(iMarker) > 0)) {
+
+ MarkerS = iMarker;
+ nVertexS = geometry->nVertex[MarkerS];
+ iRank = config->GetMarker_All_SendRecv(MarkerS)-1;
+
+ if (iRank == Neighbors_P2PSend[iSend]) {
+ for (iVertex = 0; iVertex < nVertexS; iVertex++) {
+ Local_Point_P2PSend[count] = geometry->vertex[MarkerS][iVertex]->GetNode();
+ count++;
+ }
+ }
+
+ }
+ }
+ }
+
+ /*--- Build lists of local index values for receive. ---*/
+
+ count = 0;
+ for (iRecv = 0; iRecv < nP2PRecv; iRecv++) {
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) &&
+ (config->GetMarker_All_SendRecv(iMarker) > 0)) {
+
+ MarkerR = iMarker+1;
+ nVertexR = geometry->nVertex[MarkerR];
+ iRank = abs(config->GetMarker_All_SendRecv(MarkerR))-1;
+
+ if (iRank == Neighbors_P2PRecv[iRecv]) {
+ for (iVertex = 0; iVertex < nVertexR; iVertex++) {
+ Local_Point_P2PRecv[count] = geometry->vertex[MarkerR][iVertex]->GetNode();
+ count++;
+ }
+ }
+
+ }
+ }
+ }
+
+ /*--- In the future, some additional data structures could be created
+ here to separate the interior and boundary nodes in order to help
+ further overlap computation and communication. ---*/
+
+}
+
+void CGeometry::AllocateP2PComms(unsigned short val_countPerPoint) {
+
+ /*--- This routine is activated whenever we attempt to perform
+ a point-to-point MPI communication with our neighbors but the
+ memory buffer allocated is not large enough for the packet size.
+ Therefore, we deallocate the previously allocated space and
+ reallocate a large enough array. Note that after the first set
+ communications, this routine will not need to be called again. ---*/
+
+ int iSend, iRecv;
+
+ /*--- Store the larger packet size to the class data. ---*/
+
+ countPerPoint = val_countPerPoint;
+
+ /*-- Deallocate and reallocate our su2double cummunication memory. ---*/
+
+ if (bufD_P2PSend != NULL) delete [] bufD_P2PSend;
+
+ bufD_P2PSend = new su2double[countPerPoint*nPoint_P2PSend[nP2PSend]];
+ for (iSend = 0; iSend < countPerPoint*nPoint_P2PSend[nP2PSend]; iSend++)
+ bufD_P2PSend[iSend] = 0.0;
+
+ if (bufD_P2PRecv != NULL) delete [] bufD_P2PRecv;
+
+ bufD_P2PRecv = new su2double[countPerPoint*nPoint_P2PRecv[nP2PRecv]];
+ for (iRecv = 0; iRecv < countPerPoint*nPoint_P2PRecv[nP2PRecv]; iRecv++)
+ bufD_P2PRecv[iRecv] = 0.0;
+
+ if (bufS_P2PSend != NULL) delete [] bufS_P2PSend;
+
+ bufS_P2PSend = new unsigned short[countPerPoint*nPoint_P2PSend[nP2PSend]];
+ for (iSend = 0; iSend < countPerPoint*nPoint_P2PSend[nP2PSend]; iSend++)
+ bufS_P2PSend[iSend] = 0;
+
+ if (bufS_P2PRecv != NULL) delete [] bufS_P2PRecv;
+
+ bufS_P2PRecv = new unsigned short[countPerPoint*nPoint_P2PRecv[nP2PRecv]];
+ for (iRecv = 0; iRecv < countPerPoint*nPoint_P2PRecv[nP2PRecv]; iRecv++)
+ bufS_P2PRecv[iRecv] = 0;
+
+}
+
+void CGeometry::PostP2PRecvs(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType,
+ bool val_reverse) {
+
+ /*--- Local variables ---*/
+
+ int iMessage, iRecv, offset, nPointP2P, count, source, tag;
+
+ /*--- Launch the non-blocking recv's first. Note that we have stored
+ the counts and sources, so we can launch these before we even load
+ the data and send from the neighbor ranks. ---*/
+
+ iMessage = 0;
+ for (iRecv = 0; iRecv < nP2PRecv; iRecv++) {
+
+ /*--- In some instances related to the adjoint solver, we need
+ to reverse the direction of communications such that the normal
+ send nodes become the recv nodes and vice-versa. ---*/
+
+ if (val_reverse) {
+
+ /*--- Compute our location in the buffer using the send data
+ structure since we are reversing the comms. ---*/
+
+ offset = countPerPoint*nPoint_P2PSend[iRecv];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of elems that we need to recv. Note again that we select the send
+ points here as the recv points. ---*/
+
+ nPointP2P = nPoint_P2PSend[iRecv+1] - nPoint_P2PSend[iRecv];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPoint*nPointP2P;
+
+ /*--- Get the rank from which we receive the message. Note again
+ that we use the send rank as the source instead of the recv rank. ---*/
+
+ source = Neighbors_P2PSend[iRecv];
+ tag = source + 1;
+
+ /*--- Post non-blocking recv for this proc. Note that we use the
+ send buffer here too. This is important to make sure the arrays
+ are the correct size. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Irecv(&(bufD_P2PSend[offset]), count, MPI_DOUBLE,
+ source, tag, MPI_COMM_WORLD, &(req_P2PRecv[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Irecv(&(bufS_P2PSend[offset]), count, MPI_UNSIGNED_SHORT,
+ source, tag, MPI_COMM_WORLD, &(req_P2PRecv[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ } else {
+
+ /*--- Compute our location in the recv buffer. ---*/
+
+ offset = countPerPoint*nPoint_P2PRecv[iRecv];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of elems that we need to recv. ---*/
+
+ nPointP2P = nPoint_P2PRecv[iRecv+1] - nPoint_P2PRecv[iRecv];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPoint*nPointP2P;
+
+ /*--- Get the rank from which we receive the message. ---*/
+
+ source = Neighbors_P2PRecv[iRecv];
+ tag = source + 1;
+
+ /*--- Post non-blocking recv for this proc. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Irecv(&(bufD_P2PRecv[offset]), count, MPI_DOUBLE,
+ source, tag, MPI_COMM_WORLD, &(req_P2PRecv[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Irecv(&(bufS_P2PRecv[offset]), count, MPI_UNSIGNED_SHORT,
+ source, tag, MPI_COMM_WORLD, &(req_P2PRecv[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ }
+
+ /*--- Increment message counter. ---*/
+
+ iMessage++;
+
+ }
+
+}
+
+void CGeometry::PostP2PSends(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType,
+ int val_iSend,
+ bool val_reverse) {
+
+ /*--- Local variables ---*/
+
+ int iMessage, offset, nPointP2P, count, dest, tag;
+
+ /*--- Post the non-blocking send as soon as the buffer is loaded. ---*/
+
+ iMessage = val_iSend;
+
+ /*--- In some instances related to the adjoint solver, we need
+ to reverse the direction of communications such that the normal
+ send nodes become the recv nodes and vice-versa. ---*/
+
+ if (val_reverse) {
+
+ /*--- Compute our location in the buffer using the recv data
+ structure since we are reversing the comms. ---*/
+
+ offset = countPerPoint*nPoint_P2PRecv[val_iSend];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of points that we need to send. Note again that we select the recv
+ points here as the send points. ---*/
+
+ nPointP2P = nPoint_P2PRecv[val_iSend+1] - nPoint_P2PRecv[val_iSend];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPoint*nPointP2P;
+
+ /*--- Get the rank to which we send the message. Note again
+ that we use the recv rank as the dest instead of the send rank. ---*/
+
+ dest = Neighbors_P2PRecv[val_iSend];
+ tag = rank + 1;
+
+ /*--- Post non-blocking send for this proc. Note that we use the
+ send buffer here too. This is important to make sure the arrays
+ are the correct size. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Isend(&(bufD_P2PRecv[offset]), count, MPI_DOUBLE,
+ dest, tag, MPI_COMM_WORLD, &(req_P2PSend[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Isend(&(bufS_P2PRecv[offset]), count, MPI_UNSIGNED_SHORT,
+ dest, tag, MPI_COMM_WORLD, &(req_P2PSend[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ } else {
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = countPerPoint*nPoint_P2PSend[val_iSend];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of points that we need to send. ---*/
+
+ nPointP2P = nPoint_P2PSend[val_iSend+1] - nPoint_P2PSend[val_iSend];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPoint*nPointP2P;
+
+ /*--- Get the rank to which we send the message. ---*/
+
+ dest = Neighbors_P2PSend[val_iSend];
+ tag = rank + 1;
+
+ /*--- Post non-blocking send for this proc. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Isend(&(bufD_P2PSend[offset]), count, MPI_DOUBLE,
+ dest, tag, MPI_COMM_WORLD, &(req_P2PSend[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Isend(&(bufS_P2PSend[offset]), count, MPI_UNSIGNED_SHORT,
+ dest, tag, MPI_COMM_WORLD, &(req_P2PSend[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ }
+
+}
+
+void CGeometry::InitiateComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iDim;
+ unsigned short COUNT_PER_POINT = 0;
+ unsigned short MPI_TYPE = 0;
+
+ unsigned long iPoint, offset, buf_offset;
+
+ int iMessage, iSend, nSend;
+
+ /*--- Set the size of the data packet and type depending on quantity. ---*/
+
+ switch (commType) {
+ case COORDINATES:
+ COUNT_PER_POINT = nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case GRID_VELOCITY:
+ COUNT_PER_POINT = nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case COORDINATES_OLD:
+ if (config->GetUnsteady_Simulation() == DT_STEPPING_2ND)
+ COUNT_PER_POINT = nDim*2;
+ else
+ COUNT_PER_POINT = nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case MAX_LENGTH:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case NEIGHBORS:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_UNSIGNED_SHORT;
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ /*--- Check to make sure we have created a large enough buffer
+ for these comms during preprocessing. This is only for the su2double
+ buffer. It will be reallocated whenever we find a larger count
+ per point. After the first cycle of comms, this should be inactive. ---*/
+
+ if (COUNT_PER_POINT > geometry->countPerPoint) {
+ geometry->AllocateP2PComms(COUNT_PER_POINT);
+ }
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDSend = geometry->bufD_P2PSend;
+ unsigned short *bufSSend = geometry->bufS_P2PSend;
+
+ su2double *vector = NULL;
+
+ /*--- Load the specified quantity from the solver into the generic
+ communication buffer in the geometry class. ---*/
+
+ if (nP2PSend > 0) {
+
+ /*--- Post all non-blocking recvs first before sends. ---*/
+
+ geometry->PostP2PRecvs(geometry, config, MPI_TYPE, false);
+
+ for (iMessage = 0; iMessage < nP2PSend; iMessage++) {
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = nPoint_P2PSend[iMessage];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ nSend = (nPoint_P2PSend[iMessage+1] - nPoint_P2PSend[iMessage]);
+
+ for (iSend = 0; iSend < nSend; iSend++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PSend[offset + iSend];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iSend)*countPerPoint;
+
+ switch (commType) {
+ case COORDINATES:
+ vector = node[iPoint]->GetCoord();
+ for (iDim = 0; iDim < nDim; iDim++)
+ bufDSend[buf_offset+iDim] = vector[iDim];
+ break;
+ case GRID_VELOCITY:
+ vector = node[iPoint]->GetGridVel();
+ for (iDim = 0; iDim < nDim; iDim++)
+ bufDSend[buf_offset+iDim] = vector[iDim];
+ break;
+ case COORDINATES_OLD:
+ vector = node[iPoint]->GetCoord_n();
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset+iDim] = vector[iDim];
+ }
+ if (config->GetUnsteady_Simulation() == DT_STEPPING_2ND) {
+ vector = node[iPoint]->GetCoord_n1();
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset+nDim+iDim] = vector[iDim];
+ }
+ }
+ break;
+ case MAX_LENGTH:
+ bufDSend[buf_offset] = node[iPoint]->GetMaxLength();
+ break;
+ case NEIGHBORS:
+ bufSSend[buf_offset] = geometry->node[iPoint]->GetnPoint();
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+
+ /*--- Launch the point-to-point MPI send for this message. ---*/
+
+ geometry->PostP2PSends(geometry, config, MPI_TYPE, iMessage, false);
+
+ }
+ }
+
+}
+
+void CGeometry::CompleteComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iDim;
+ unsigned long iPoint, iRecv, nRecv, offset, buf_offset;
+
+ int ind, source, iMessage, jRecv;
+ SU2_MPI::Status status;
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDRecv = geometry->bufD_P2PRecv;
+ unsigned short *bufSRecv = geometry->bufS_P2PRecv;
+
+ /*--- Store the data that was communicated into the appropriate
+ location within the local class data structures. Note that we
+ recv and store the data in any order to take advantage of the
+ non-blocking comms. ---*/
+
+ if (nP2PRecv > 0) {
+
+ for (iMessage = 0; iMessage < nP2PRecv; iMessage++) {
+
+ /*--- For efficiency, recv the messages dynamically based on
+ the order they arrive. ---*/
+
+ SU2_MPI::Waitany(nP2PRecv, req_P2PRecv, &ind, &status);
+
+ /*--- Once we have recv'd a message, get the source rank. ---*/
+
+ source = status.MPI_SOURCE;
+
+ /*--- We know the offsets based on the source rank. ---*/
+
+ jRecv = P2PRecv2Neighbor[source];
+
+ /*--- Get the point offset for the start of this message. ---*/
+
+ offset = nPoint_P2PRecv[jRecv];
+
+ /*--- Get the number of packets to be received in this message. ---*/
+
+ nRecv = nPoint_P2PRecv[jRecv+1] - nPoint_P2PRecv[jRecv];
+
+ for (iRecv = 0; iRecv < nRecv; iRecv++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PRecv[offset + iRecv];
+
+ /*--- Compute the total offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iRecv)*countPerPoint;
+
+ /*--- Store the data correctly depending on the quantity. ---*/
+
+ switch (commType) {
+ case COORDINATES:
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetCoord(iDim, bufDRecv[buf_offset+iDim]);
+ break;
+ case GRID_VELOCITY:
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetGridVel(iDim, bufDRecv[buf_offset+iDim]);
+ break;
+ case COORDINATES_OLD:
+ node[iPoint]->SetCoord_n(&bufDRecv[buf_offset]);
+ if (config->GetUnsteady_Simulation() == DT_STEPPING_2ND)
+ node[iPoint]->SetCoord_n1(&bufDRecv[buf_offset+nDim]);
+ break;
+ case MAX_LENGTH:
+ node[iPoint]->SetMaxLength(bufDRecv[buf_offset]);
+ break;
+ case NEIGHBORS:
+ node[iPoint]->SetnNeighbor(bufSRecv[buf_offset]);
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+ }
+
+ /*--- Verify that all non-blocking point-to-point sends have finished.
+ Note that this should be satisfied, as we have received all of the
+ data in the loop above at this point. ---*/
+
+#ifdef HAVE_MPI
+ SU2_MPI::Waitall(nP2PSend, req_P2PSend, MPI_STATUS_IGNORE);
+#endif
+
+ }
+
+}
+
+void CGeometry::PreprocessPeriodicComms(CGeometry *geometry,
+ CConfig *config) {
+
+ /*--- We start with the send and receive lists already available in
+ the form of stored periodic point-donor pairs. We will loop through
+ these markers and establish the neighboring ranks and number of
+ send/recv points per pair. We will store this information and set
+ up persistent data structures so that we can reuse them throughout
+ the calculation for any periodic boundary communications. The goal
+ is to break the non-blocking comms into InitiatePeriodicComms() and
+ CompletePeriodicComms() in separate routines so that we can overlap the
+ communication and computation to hide the communication latency. ---*/
+
+ /*--- Local variables. ---*/
+
+ unsigned short iMarker;
+ unsigned long iPoint, iVertex, iPeriodic;
+
+ int iRank, iSend, iRecv, ii, jj;
+
+ /*--- Create some temporary structures for tracking sends/recvs. ---*/
+
+ int *nPoint_Send_All = new int[size+1]; nPoint_Send_All[0] = 0;
+ int *nPoint_Recv_All = new int[size+1]; nPoint_Recv_All[0] = 0;
+ int *nPoint_Flag = new int[size];
+
+ for (iRank = 0; iRank < size; iRank++) {
+ nPoint_Send_All[iRank] = 0;
+ nPoint_Recv_All[iRank] = 0;
+ nPoint_Flag[iRank]= -1;
+ }
+ nPoint_Send_All[size] = 0; nPoint_Recv_All[size] = 0;
+
+ /*--- Loop through all of our periodic markers and track
+ our sends with each rank. ---*/
+
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Get the current periodic point index. We only communicate
+ the owned nodes on a rank, as the MPI comms will take care of
+ the halos after completing the periodic comms. ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+
+ if (geometry->node[iPoint]->GetDomain()) {
+
+ /*--- Get the rank that holds the matching periodic point
+ on the other marker in the periodic pair. ---*/
+
+ iRank = (int)geometry->vertex[iMarker][iVertex]->GetDonorProcessor();
+
+ /*--- If we have not visited this point last, increment our
+ number of points that must be sent to a particular proc. ---*/
+
+ if ((nPoint_Flag[iRank] != (int)iPoint)) {
+ nPoint_Flag[iRank] = (int)iPoint;
+ nPoint_Send_All[iRank+1] += 1;
+ }
+
+ }
+ }
+ }
+ }
+
+ delete [] nPoint_Flag;
+
+ /*--- Communicate the number of points to be sent/recv'd amongst
+ all processors. After this communication, each proc knows how
+ many periodic points it will receive from each other processor. ---*/
+
+ SU2_MPI::Alltoall(&(nPoint_Send_All[1]), 1, MPI_INT,
+ &(nPoint_Recv_All[1]), 1, MPI_INT, MPI_COMM_WORLD);
+
+ /*--- Check how many messages we will be sending and receiving.
+ Here we also put the counters into cumulative storage format to
+ make the communications simpler. Note that we are allowing each
+ rank to communicate to themselves in these counters, although
+ it will not be done through MPI. ---*/
+
+ nPeriodicSend = 0; nPeriodicRecv = 0;
+
+ for (iRank = 0; iRank < size; iRank++) {
+ if ((nPoint_Send_All[iRank+1] > 0)) nPeriodicSend++;
+ if ((nPoint_Recv_All[iRank+1] > 0)) nPeriodicRecv++;
+
+ nPoint_Send_All[iRank+1] += nPoint_Send_All[iRank];
+ nPoint_Recv_All[iRank+1] += nPoint_Recv_All[iRank];
+ }
+
+ /*--- Allocate only as much memory as needed for the periodic neighbors. ---*/
+
+ nPoint_PeriodicSend = new int[nPeriodicSend+1]; nPoint_PeriodicSend[0] = 0;
+ nPoint_PeriodicRecv = new int[nPeriodicRecv+1]; nPoint_PeriodicRecv[0] = 0;
+
+ Neighbors_PeriodicSend = new int[nPeriodicSend];
+ Neighbors_PeriodicRecv = new int[nPeriodicRecv];
+
+ iSend = 0; iRecv = 0;
+ for (iRank = 0; iRank < size; iRank++) {
+ if ((nPoint_Send_All[iRank+1] > nPoint_Send_All[iRank])) {
+ Neighbors_PeriodicSend[iSend] = iRank;
+ nPoint_PeriodicSend[iSend+1] = nPoint_Send_All[iRank+1];
+ iSend++;
+ }
+ if ((nPoint_Recv_All[iRank+1] > nPoint_Recv_All[iRank])) {
+ Neighbors_PeriodicRecv[iRecv] = iRank;
+ nPoint_PeriodicRecv[iRecv+1] = nPoint_Recv_All[iRank+1];
+ iRecv++;
+ }
+ }
+
+ /*--- Create a reverse mapping of the message to the rank so that we
+ can quickly access the correct data in the buffers when receiving
+ messages dynamically later during the iterations. ---*/
+
+ PeriodicSend2Neighbor.clear();
+ for (iSend = 0; iSend < nPeriodicSend; iSend++)
+ PeriodicSend2Neighbor[Neighbors_PeriodicSend[iSend]] = iSend;
+
+ PeriodicRecv2Neighbor.clear();
+ for (iRecv = 0; iRecv < nPeriodicRecv; iRecv++)
+ PeriodicRecv2Neighbor[Neighbors_PeriodicRecv[iRecv]] = iRecv;
+
+ delete [] nPoint_Send_All;
+ delete [] nPoint_Recv_All;
+
+ /*--- Allocate the memory to store the local index values for both
+ the send and receive periodic points and periodic index. ---*/
+
+ Local_Point_PeriodicSend = NULL;
+ Local_Point_PeriodicSend = new unsigned long[nPoint_PeriodicSend[nPeriodicSend]];
+ for (iSend = 0; iSend < nPoint_PeriodicSend[nPeriodicSend]; iSend++)
+ Local_Point_PeriodicSend[iSend] = 0;
+
+ Local_Marker_PeriodicSend = NULL;
+ Local_Marker_PeriodicSend = new unsigned long[nPoint_PeriodicSend[nPeriodicSend]];
+ for (iSend = 0; iSend < nPoint_PeriodicSend[nPeriodicSend]; iSend++)
+ Local_Marker_PeriodicSend[iSend] = 0;
+
+ Local_Point_PeriodicRecv = NULL;
+ Local_Point_PeriodicRecv = new unsigned long[nPoint_PeriodicRecv[nPeriodicRecv]];
+ for (iRecv = 0; iRecv < nPoint_PeriodicRecv[nPeriodicRecv]; iRecv++)
+ Local_Point_PeriodicRecv[iRecv] = 0;
+
+ Local_Marker_PeriodicRecv = NULL;
+ Local_Marker_PeriodicRecv = new unsigned long[nPoint_PeriodicRecv[nPeriodicRecv]];
+ for (iRecv = 0; iRecv < nPoint_PeriodicRecv[nPeriodicRecv]; iRecv++)
+ Local_Marker_PeriodicRecv[iRecv] = 0;
+
+ /*--- We allocate the buffers for communicating values in a later step
+ once we know the maximum packet size that we need to communicate. This
+ memory is deallocated and reallocated automatically in the case that
+ the previously allocated memory is not sufficient. ---*/
+
+ bufD_PeriodicSend = NULL;
+ bufD_PeriodicRecv = NULL;
+
+ bufS_PeriodicSend = NULL;
+ bufS_PeriodicRecv = NULL;
+
+ /*--- Allocate memory for the MPI requests if we need to communicate. ---*/
+
+ if (nPeriodicSend > 0) {
+ req_PeriodicSend = new SU2_MPI::Request[nPeriodicSend];
+ }
+ if (nPeriodicRecv > 0) {
+ req_PeriodicRecv = new SU2_MPI::Request[nPeriodicRecv];
+ }
+
+ /*--- Allocate arrays for sending the periodic point index and marker
+ index to the recv rank so that it can store the local values. Therefore,
+ the recv rank can quickly loop through the buffers to unpack the data. ---*/
+
+ unsigned short nPackets = 2;
+ unsigned long *idSend = new unsigned long[nPoint_PeriodicSend[nPeriodicSend]*nPackets];
+ for (iSend = 0; iSend < nPoint_PeriodicSend[nPeriodicSend]*nPackets; iSend++)
+ idSend[iSend] = 0;
+
+ /*--- Build the lists of local index and periodic marker index values. ---*/
+
+ ii = 0; jj = 0;
+ for (iSend = 0; iSend < nPeriodicSend; iSend++) {
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+
+ /*--- Get the current periodic point index. We only communicate
+ the owned nodes on a rank, as the MPI comms will take care of
+ the halos after completing the periodic comms. ---*/
+
+ iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
+
+ if (geometry->node[iPoint]->GetDomain()) {
+
+ /*--- Get the rank that holds the matching periodic point
+ on the other marker in the periodic pair. ---*/
+
+ iRank = (int)geometry->vertex[iMarker][iVertex]->GetDonorProcessor();
+
+ /*--- If the rank for the current periodic point matches the
+ rank of the current send message, then store the local point
+ index on the matching periodic point and the periodic marker
+ index to be communicated to the recv rank. ---*/
+
+ if (iRank == Neighbors_PeriodicSend[iSend]) {
+ Local_Point_PeriodicSend[ii] = iPoint;
+ Local_Marker_PeriodicSend[ii] = (unsigned long)iMarker;
+ jj = ii*nPackets;
+ idSend[jj] = geometry->vertex[iMarker][iVertex]->GetDonorPoint();
+ jj++;
+ idSend[jj] = (unsigned long)iPeriodic;
+ ii++;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ /*--- Allocate arrays for receiving the periodic point index and marker
+ index to the recv rank so that it can store the local values. ---*/
+
+ unsigned long *idRecv = new unsigned long[nPoint_PeriodicRecv[nPeriodicRecv]*nPackets];
+ for (iRecv = 0; iRecv < nPoint_PeriodicRecv[nPeriodicRecv]*nPackets; iRecv++)
+ idRecv[iRecv] = 0;
+
+#ifdef HAVE_MPI
+
+ int iMessage, offset, count, source, dest, tag;
+
+ /*--- Launch the non-blocking recv's first. Note that we have stored
+ the counts and sources, so we can launch these before we even load
+ the data and send from the periodically matching ranks. ---*/
+
+ iMessage = 0;
+ for (iRecv = 0; iRecv < nPeriodicRecv; iRecv++) {
+
+ /*--- Compute our location in the recv buffer. ---*/
+
+ offset = nPackets*nPoint_PeriodicRecv[iRecv];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of elems that we need to recv. ---*/
+
+ count = nPackets*(nPoint_PeriodicRecv[iRecv+1] - nPoint_PeriodicRecv[iRecv]);
+
+ /*--- Get the rank from which we receive the message. ---*/
+
+ source = Neighbors_PeriodicRecv[iRecv];
+ tag = source + 1;
+
+ /*--- Post non-blocking recv for this proc. ---*/
+
+ SU2_MPI::Irecv(&(static_cast(idRecv)[offset]),
+ count, MPI_UNSIGNED_LONG, source, tag, MPI_COMM_WORLD,
+ &(req_PeriodicRecv[iMessage]));
+
+ /*--- Increment message counter. ---*/
+
+ iMessage++;
+
+ }
+
+ /*--- Post the non-blocking sends. ---*/
+
+ iMessage = 0;
+ for (iSend = 0; iSend < nPeriodicSend; iSend++) {
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = nPackets*nPoint_PeriodicSend[iSend];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of points that we need to send. ---*/
+
+ count = nPackets*(nPoint_PeriodicSend[iSend+1] - nPoint_PeriodicSend[iSend]);
+
+ /*--- Get the rank to which we send the message. ---*/
+
+ dest = Neighbors_PeriodicSend[iSend];
+ tag = rank + 1;
+
+ /*--- Post non-blocking send for this proc. ---*/
+
+ SU2_MPI::Isend(&(static_cast(idSend)[offset]),
+ count, MPI_UNSIGNED_LONG, dest, tag, MPI_COMM_WORLD,
+ &(req_PeriodicSend[iMessage]));
+
+ /*--- Increment message counter. ---*/
+
+ iMessage++;
+
+ }
+
+ /*--- Wait for the non-blocking comms to complete. ---*/
+
+ SU2_MPI::Waitall(nPeriodicSend, req_PeriodicSend, MPI_STATUS_IGNORE);
+ SU2_MPI::Waitall(nPeriodicRecv, req_PeriodicRecv, MPI_STATUS_IGNORE);
+
+#else
+
+ /*--- Copy my own rank's data into the recv buffer directly in serial. ---*/
+
+ int myStart, myFinal;
+ for (int val_iSend = 0; val_iSend < nPeriodicSend; val_iSend++) {
+ iRank = geometry->PeriodicRecv2Neighbor[rank];
+ iRecv = geometry->nPoint_PeriodicRecv[iRank]*nPackets;
+ myStart = nPoint_PeriodicSend[val_iSend]*nPackets;
+ myFinal = nPoint_PeriodicSend[val_iSend+1]*nPackets;
+ for (iSend = myStart; iSend < myFinal; iSend++) {
+ idRecv[iRecv] = idSend[iSend];
+ iRecv++;
+ }
+ }
+
+#endif
+
+ /*--- Store the local periodic point and marker index values in our
+ data structures so we can quickly unpack data during the iterations. ---*/
+
+ ii = 0;
+ for (iRecv = 0; iRecv < nPoint_PeriodicRecv[nPeriodicRecv]; iRecv++) {
+ Local_Point_PeriodicRecv[iRecv] = idRecv[ii]; ii++;
+ Local_Marker_PeriodicRecv[iRecv] = idRecv[ii]; ii++;
+ }
+
+ delete [] idSend;
+ delete [] idRecv;
+
+}
+
+void CGeometry::AllocatePeriodicComms(unsigned short val_countPerPeriodicPoint) {
+
+ /*--- This routine is activated whenever we attempt to perform
+ a periodic MPI communication with our neighbors but the
+ memory buffer allocated is not large enough for the packet size.
+ Therefore, we deallocate the previously allocated arrays and
+ reallocate a large enough array. Note that after the first set
+ communications, this routine will not need to be called again. ---*/
+
+ int iSend, iRecv, nSend, nRecv;
+
+ /*--- Store the larger packet size to the class data. ---*/
+
+ countPerPeriodicPoint = val_countPerPeriodicPoint;
+
+ /*--- Store the total size of the send/recv arrays for clarity. ---*/
+
+ nSend = countPerPeriodicPoint*nPoint_PeriodicSend[nPeriodicSend];
+ nRecv = countPerPeriodicPoint*nPoint_PeriodicRecv[nPeriodicRecv];
+
+ /*-- Deallocate and reallocate our cummunication memory. ---*/
+
+ if (bufD_PeriodicSend != NULL) delete [] bufD_PeriodicSend;
+
+ bufD_PeriodicSend = new su2double[nSend];
+ for (iSend = 0; iSend < nSend; iSend++)
+ bufD_PeriodicSend[iSend] = 0.0;
+
+ if (bufD_PeriodicRecv != NULL) delete [] bufD_PeriodicRecv;
+
+ bufD_PeriodicRecv = new su2double[nRecv];
+ for (iRecv = 0; iRecv < nRecv; iRecv++)
+ bufD_PeriodicRecv[iRecv] = 0.0;
+
+ if (bufS_PeriodicSend != NULL) delete [] bufS_PeriodicSend;
+
+ bufS_PeriodicSend = new unsigned short[nSend];
+ for (iSend = 0; iSend < nSend; iSend++)
+ bufS_PeriodicSend[iSend] = 0;
+
+ if (bufS_PeriodicRecv != NULL) delete [] bufS_PeriodicRecv;
+
+ bufS_PeriodicRecv = new unsigned short[nRecv];
+ for (iRecv = 0; iRecv < nRecv; iRecv++)
+ bufS_PeriodicRecv[iRecv] = 0;
+
+}
+
+void CGeometry::PostPeriodicRecvs(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- In parallel, communicate the data with non-blocking send/recv. ---*/
+
+#ifdef HAVE_MPI
+
+ /*--- Local variables ---*/
+
+ int iMessage, iRecv, offset, nPointPeriodic, count, source, tag;
+
+ /*--- Launch the non-blocking recv's first. Note that we have stored
+ the counts and sources, so we can launch these before we even load
+ the data and send from the neighbor ranks. ---*/
+
+ iMessage = 0;
+ for (iRecv = 0; iRecv < nPeriodicRecv; iRecv++) {
+
+ /*--- Compute our location in the recv buffer. ---*/
+
+ offset = countPerPeriodicPoint*nPoint_PeriodicRecv[iRecv];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of elems that we need to recv. ---*/
+
+ nPointPeriodic = nPoint_PeriodicRecv[iRecv+1] - nPoint_PeriodicRecv[iRecv];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPeriodicPoint*nPointPeriodic;
+
+ /*--- Get the rank from which we receive the message. ---*/
+
+ source = Neighbors_PeriodicRecv[iRecv];
+ tag = source + 1;
+
+ /*--- Post non-blocking recv for this proc. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Irecv(&(static_cast(bufD_PeriodicRecv)[offset]),
+ count, MPI_DOUBLE, source, tag, MPI_COMM_WORLD,
+ &(req_PeriodicRecv[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Irecv(&(static_cast(bufS_PeriodicRecv)[offset]),
+ count, MPI_UNSIGNED_SHORT, source, tag, MPI_COMM_WORLD,
+ &(req_PeriodicRecv[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for periodic MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ /*--- Increment message counter. ---*/
+
+ iMessage++;
+
+ }
+
+#endif
+
+}
+
+void CGeometry::PostPeriodicSends(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType,
+ int val_iSend) {
+
+ /*--- In parallel, communicate the data with non-blocking send/recv. ---*/
+
+#ifdef HAVE_MPI
+
+ /*--- Local variables ---*/
+
+ int iMessage, offset, nPointPeriodic, count, dest, tag;
+
+ /*--- Post the non-blocking send as soon as the buffer is loaded. ---*/
+
+ iMessage = val_iSend;
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = countPerPeriodicPoint*nPoint_PeriodicSend[val_iSend];
+
+ /*--- Take advantage of cumulative storage format to get the number
+ of points that we need to send. ---*/
+
+ nPointPeriodic = (nPoint_PeriodicSend[val_iSend+1] -
+ nPoint_PeriodicSend[val_iSend]);
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ count = countPerPeriodicPoint*nPointPeriodic;
+
+ /*--- Get the rank to which we send the message. ---*/
+
+ dest = Neighbors_PeriodicSend[val_iSend];
+ tag = rank + 1;
+
+ /*--- Post non-blocking send for this proc. ---*/
+
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ SU2_MPI::Isend(&(static_cast(bufD_PeriodicSend)[offset]),
+ count, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD,
+ &(req_PeriodicSend[iMessage]));
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ SU2_MPI::Isend(&(static_cast(bufS_PeriodicSend)[offset]),
+ count, MPI_UNSIGNED_SHORT, dest, tag, MPI_COMM_WORLD,
+ &(req_PeriodicSend[iMessage]));
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for periodic MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+#else
+
+ /*--- Copy my own rank's data into the recv buffer directly in serial. ---*/
+
+ int iSend, myStart, myFinal, iRecv, iRank;
+ iRank = geometry->PeriodicRecv2Neighbor[rank];
+ iRecv = geometry->nPoint_PeriodicRecv[iRank]*countPerPeriodicPoint;
+ myStart = nPoint_PeriodicSend[val_iSend]*countPerPeriodicPoint;
+ myFinal = nPoint_PeriodicSend[val_iSend+1]*countPerPeriodicPoint;
+ for (iSend = myStart; iSend < myFinal; iSend++) {
+ switch (commType) {
+ case COMM_TYPE_DOUBLE:
+ bufD_PeriodicRecv[iRecv] = bufD_PeriodicSend[iSend];
+ break;
+ case COMM_TYPE_UNSIGNED_SHORT:
+ bufS_PeriodicRecv[iRecv] = bufS_PeriodicSend[iSend];
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized data type for periodic MPI comms.",
+ CURRENT_FUNCTION);
+ break;
}
- delete [] CustomBoundaryTemperature;
+ iRecv++;
}
-
+
+#endif
+
}
su2double CGeometry::Point2Plane_Distance(su2double *Coord, su2double *iCoord, su2double *jCoord, su2double *kCoord) {
@@ -1377,9 +2700,12 @@ void CGeometry::RegisterOutput_Coordinates(CConfig *config){
void CGeometry::UpdateGeometry(CGeometry **geometry_container, CConfig *config) {
unsigned short iMesh;
- geometry_container[MESH_0]->Set_MPI_Coord(config);
+
+ geometry_container[MESH_0]->InitiateComms(geometry_container[MESH_0], config, COORDINATES);
+ geometry_container[MESH_0]->CompleteComms(geometry_container[MESH_0], config, COORDINATES);
if (config->GetGrid_Movement()){
- geometry_container[MESH_0]->Set_MPI_GridVel(config);
+ geometry_container[MESH_0]->InitiateComms(geometry_container[MESH_0], config, GRID_VELOCITY);
+ geometry_container[MESH_0]->CompleteComms(geometry_container[MESH_0], config, GRID_VELOCITY);
}
geometry_container[MESH_0]->SetCoord_CG();
@@ -2424,7 +3750,7 @@ CPhysicalGeometry::CPhysicalGeometry(CConfig *config, unsigned short val_iZone,
}
-CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry, CConfig *config) {
+CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry, CConfig *config, bool val_flag) {
/*--- Initialize several class data members for later. ---*/
@@ -2505,6 +3831,8 @@ CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry, CConfig *config) {
unsigned long *Buffer_Send_nBoundQuadrilateral = new unsigned long[nMarker_Max];
short *Buffer_Send_Marker_All_SendRecv = new short[nMarker_Max];
+ for (iMarker = 0; iMarker < nMarker_Max; iMarker++)
+ Buffer_Send_Marker_All_SendRecv[iMarker] = 0;
char *Marker_All_TagBound = new char[nMarker_Max*MAX_STRING_SIZE];
char *Buffer_Send_Marker_All_TagBound = new char[nMarker_Max*MAX_STRING_SIZE];
@@ -5382,8 +6710,7 @@ CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry, CConfig *config) {
}
CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry,
- CConfig *config,
- bool val_flag) {
+ CConfig *config) {
/*--- Get rank and size. ---*/
@@ -6007,13 +7334,13 @@ void CPhysicalGeometry::DistributeColoring(CConfig *config,
/*--- Launch the non-blocking sends and receives. ---*/
- InitiateComms(colorSend, nPoint_Send, colorSendReq,
- colorRecv, nPoint_Recv, colorRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(colorSend, nPoint_Send, colorSendReq,
+ colorRecv, nPoint_Recv, colorRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(idSend, nPoint_Send, idSendReq,
- idRecv, nPoint_Recv, idRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(idSend, nPoint_Send, idSendReq,
+ idRecv, nPoint_Recv, idRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
/*--- Copy my own rank's data into the recv buffer directly. ---*/
@@ -6028,8 +7355,8 @@ void CPhysicalGeometry::DistributeColoring(CConfig *config,
/*--- Complete the non-blocking communications. ---*/
- CompleteComms(nSends, colorSendReq, nRecvs, colorRecvReq);
- CompleteComms(nSends, idSendReq, nRecvs, idRecvReq);
+ CompleteCommsAll(nSends, colorSendReq, nRecvs, colorRecvReq);
+ CompleteCommsAll(nSends, idSendReq, nRecvs, idRecvReq);
/*--- Store the complete color map for this rank in class data. Now,
each rank has a color value for all owned nodes as well as any repeated
@@ -6271,13 +7598,13 @@ void CPhysicalGeometry::DistributeVolumeConnectivity(CConfig *config,
/*--- Launch the non-blocking sends and receives. ---*/
- InitiateComms(connSend, nElem_Send, connSendReq,
- connRecv, nElem_Recv, connRecvReq,
- NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(connSend, nElem_Send, connSendReq,
+ connRecv, nElem_Recv, connRecvReq,
+ NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(idSend, nElem_Send, idSendReq,
- idRecv, nElem_Recv, idRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(idSend, nElem_Send, idSendReq,
+ idRecv, nElem_Recv, idRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
/*--- Copy my own rank's data into the recv buffer directly. ---*/
@@ -6299,8 +7626,8 @@ void CPhysicalGeometry::DistributeVolumeConnectivity(CConfig *config,
/*--- Complete the non-blocking communications. ---*/
- CompleteComms(nSends, connSendReq, nRecvs, connRecvReq);
- CompleteComms(nSends, idSendReq, nRecvs, idRecvReq);
+ CompleteCommsAll(nSends, connSendReq, nRecvs, connRecvReq);
+ CompleteCommsAll(nSends, idSendReq, nRecvs, idRecvReq);
/*--- Store the connectivity for this rank in the proper structure
It will be loaded into the geometry objects in a later step. ---*/
@@ -6579,17 +7906,17 @@ void CPhysicalGeometry::DistributePoints(CConfig *config, CGeometry *geometry) {
/*--- Launch the non-blocking sends and receives. ---*/
- InitiateComms(colorSend, nPoint_Send, colorSendReq,
- colorRecv, nPoint_Recv, colorRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(colorSend, nPoint_Send, colorSendReq,
+ colorRecv, nPoint_Recv, colorRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(idSend, nPoint_Send, idSendReq,
- idRecv, nPoint_Recv, idRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(idSend, nPoint_Send, idSendReq,
+ idRecv, nPoint_Recv, idRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(coordSend, nPoint_Send, coordSendReq,
- coordRecv, nPoint_Recv, coordRecvReq,
- nDim, COMM_TYPE_DOUBLE);
+ InitiateCommsAll(coordSend, nPoint_Send, coordSendReq,
+ coordRecv, nPoint_Recv, coordRecvReq,
+ nDim, COMM_TYPE_DOUBLE);
/*--- Copy my own rank's data into the recv buffer directly. ---*/
@@ -6612,9 +7939,9 @@ void CPhysicalGeometry::DistributePoints(CConfig *config, CGeometry *geometry) {
/*--- Complete the non-blocking communications. ---*/
- CompleteComms(nSends, colorSendReq, nRecvs, colorRecvReq);
- CompleteComms(nSends, idSendReq, nRecvs, idRecvReq);
- CompleteComms(nSends, coordSendReq, nRecvs, coordRecvReq);
+ CompleteCommsAll(nSends, colorSendReq, nRecvs, colorRecvReq);
+ CompleteCommsAll(nSends, idSendReq, nRecvs, idRecvReq);
+ CompleteCommsAll(nSends, coordSendReq, nRecvs, coordRecvReq);
/*--- Store the total number of local points my rank has for
the current section after completing the communications. ---*/
@@ -6924,17 +8251,17 @@ void CPhysicalGeometry::PartitionSurfaceConnectivity(CConfig *config,
/*--- Launch the non-blocking sends and receives. ---*/
- InitiateComms(connSend, nElem_Send, connSendReq,
- connRecv, nElem_Recv, connRecvReq,
- NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(connSend, nElem_Send, connSendReq,
+ connRecv, nElem_Recv, connRecvReq,
+ NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(markerSend, nElem_Send, markerSendReq,
- markerRecv, nElem_Recv, markerRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(markerSend, nElem_Send, markerSendReq,
+ markerRecv, nElem_Recv, markerRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(idSend, nElem_Send, idSendReq,
- idRecv, nElem_Recv, idRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(idSend, nElem_Send, idSendReq,
+ idRecv, nElem_Recv, idRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
/*--- Copy my own rank's data into the recv buffer directly. ---*/
@@ -6961,9 +8288,9 @@ void CPhysicalGeometry::PartitionSurfaceConnectivity(CConfig *config,
/*--- Complete the non-blocking communications. ---*/
- CompleteComms(nSends, connSendReq, nRecvs, connRecvReq);
- CompleteComms(nSends, markerSendReq, nRecvs, markerRecvReq);
- CompleteComms(nSends, idSendReq, nRecvs, idRecvReq);
+ CompleteCommsAll(nSends, connSendReq, nRecvs, connRecvReq);
+ CompleteCommsAll(nSends, markerSendReq, nRecvs, markerRecvReq);
+ CompleteCommsAll(nSends, idSendReq, nRecvs, idRecvReq);
/*--- Store the connectivity for this rank in the proper data
structure before post-processing below. First, allocate
@@ -7278,17 +8605,17 @@ void CPhysicalGeometry::DistributeSurfaceConnectivity(CConfig *config,
/*--- Launch the non-blocking sends and receives. ---*/
- InitiateComms(connSend, nElem_Send, connSendReq,
- connRecv, nElem_Recv, connRecvReq,
- NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(connSend, nElem_Send, connSendReq,
+ connRecv, nElem_Recv, connRecvReq,
+ NODES_PER_ELEMENT, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(markerSend, nElem_Send, markerSendReq,
- markerRecv, nElem_Recv, markerRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(markerSend, nElem_Send, markerSendReq,
+ markerRecv, nElem_Recv, markerRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
- InitiateComms(idSend, nElem_Send, idSendReq,
- idRecv, nElem_Recv, idRecvReq,
- 1, COMM_TYPE_UNSIGNED_LONG);
+ InitiateCommsAll(idSend, nElem_Send, idSendReq,
+ idRecv, nElem_Recv, idRecvReq,
+ 1, COMM_TYPE_UNSIGNED_LONG);
/*--- Copy my own rank's data into the recv buffer directly. ---*/
@@ -7311,9 +8638,9 @@ void CPhysicalGeometry::DistributeSurfaceConnectivity(CConfig *config,
/*--- Complete the non-blocking communications. ---*/
- CompleteComms(nSends, connSendReq, nRecvs, connRecvReq);
- CompleteComms(nSends, markerSendReq, nRecvs, markerRecvReq);
- CompleteComms(nSends, idSendReq, nRecvs, idRecvReq);
+ CompleteCommsAll(nSends, connSendReq, nRecvs, connRecvReq);
+ CompleteCommsAll(nSends, markerSendReq, nRecvs, markerRecvReq);
+ CompleteCommsAll(nSends, idSendReq, nRecvs, idRecvReq);
/*--- Store the connectivity for this rank in the proper data
structure. It will be loaded into the geometry objects in a later step. ---*/
@@ -8176,6 +9503,7 @@ void CPhysicalGeometry::LoadSurfaceElements(CConfig *config, CGeometry *geometry
/*--- Initialize pointers for turbomachinery computations ---*/
nSpanWiseSections = new unsigned short[2];
+ nSpanSectionsByMarker = new unsigned short[nMarker];
SpanWiseValue = new su2double*[2];
for (unsigned short iMarker = 0; iMarker < 2; iMarker++){
nSpanWiseSections[iMarker] = 0;
@@ -8196,6 +9524,7 @@ void CPhysicalGeometry::LoadSurfaceElements(CConfig *config, CGeometry *geometry
MinRelAngularCoord = new su2double*[nMarker];
for (unsigned short iMarker = 0; iMarker < nMarker; iMarker++){
+ nSpanSectionsByMarker[iMarker] = 0;
nVertexSpan[iMarker] = NULL;
nTotVertexSpan[iMarker] = NULL;
turbovertex[iMarker] = NULL;
@@ -8231,14 +9560,14 @@ void CPhysicalGeometry::LoadSurfaceElements(CConfig *config, CGeometry *geometry
}
-void CPhysicalGeometry::InitiateComms(void *bufSend,
- int *nElemSend,
- SU2_MPI::Request *sendReq,
- void *bufRecv,
- int *nElemRecv,
- SU2_MPI::Request *recvReq,
- unsigned short countPerElem,
- unsigned short commType) {
+void CPhysicalGeometry::InitiateCommsAll(void *bufSend,
+ int *nElemSend,
+ SU2_MPI::Request *sendReq,
+ void *bufRecv,
+ int *nElemRecv,
+ SU2_MPI::Request *recvReq,
+ unsigned short countPerElem,
+ unsigned short commType) {
/*--- Local variables ---*/
@@ -8396,10 +9725,10 @@ void CPhysicalGeometry::InitiateComms(void *bufSend,
}
-void CPhysicalGeometry::CompleteComms(int nSends,
- SU2_MPI::Request *sendReq,
- int nRecvs,
- SU2_MPI::Request *recvReq) {
+void CPhysicalGeometry::CompleteCommsAll(int nSends,
+ SU2_MPI::Request *sendReq,
+ int nRecvs,
+ SU2_MPI::Request *recvReq) {
/*--- Local variables ---*/
@@ -8883,6 +10212,9 @@ void CPhysicalGeometry::SetBoundaries(CConfig *config) {
config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX &&
config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL)
node[Point_Surface]->SetSolidBoundary(true);
+
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY)
+ node[Point_Surface]->SetPeriodicBoundary(true);
}
}
@@ -10840,7 +12172,10 @@ void CPhysicalGeometry::Read_SU2_Format_Parallel(CConfig *config, string val_mes
text_line.erase (0,10); nPeriodic = atoi(text_line.c_str());
if (rank == MASTER_NODE) {
if (nPeriodic - 1 != 0)
- cout << nPeriodic - 1 << " periodic transformations." << endl;
+ SU2_MPI::Error(string("Mesh file contains outdated periodic format!\n\n") +
+ string("For SU2 v7.0.0 and later, preprocessing of periodic grids by SU2_MSH\n") +
+ string("is no longer necessary. Please use the original mesh file (prior to SU2_MSH)\n") +
+ string("with the same MARKER_PERIODIC definition in the configuration file.") , CURRENT_FUNCTION);
}
config->SetnPeriodicIndex(nPeriodic);
@@ -10874,23 +12209,6 @@ void CPhysicalGeometry::Read_SU2_Format_Parallel(CConfig *config, string val_mes
}
}
}
-
- /*--- If no periodic transormations were found, store default zeros ---*/
-
- if (!found_transform) {
- unsigned short nPeriodic = 1, iPeriodic = 0;
- config->SetnPeriodicIndex(nPeriodic);
- su2double* center = new su2double[3];
- su2double* rotation = new su2double[3];
- su2double* translate = new su2double[3];
- for (unsigned short iDim = 0; iDim < 3; iDim++) {
- center[iDim] = 0.0; rotation[iDim] = 0.0; translate[iDim] = 0.0;
- }
- config->SetPeriodicCenter(iPeriodic, center);
- config->SetPeriodicRotation(iPeriodic, rotation);
- config->SetPeriodicTranslate(iPeriodic, translate);
- delete [] center; delete [] rotation; delete [] translate;
- }
/*--- Close the input file ---*/
@@ -12395,22 +13713,6 @@ void CPhysicalGeometry::Read_CGNS_Format_Parallel(CConfig *config, string val_me
}
- /*--- Periodic transformations are not implemented yet for CGNS.
- Store default zeros. ---*/
-
- unsigned short nPeriodic = 1, iPeriodic = 0;
- config->SetnPeriodicIndex(nPeriodic);
- su2double* center = new su2double[3];
- su2double* rotation = new su2double[3];
- su2double* translate = new su2double[3];
- for (unsigned short iDim = 0; iDim < 3; iDim++) {
- center[iDim] = 0.0; rotation[iDim] = 0.0; translate[iDim] = 0.0;
- }
- config->SetPeriodicCenter(iPeriodic, center);
- config->SetPeriodicRotation(iPeriodic, rotation);
- config->SetPeriodicTranslate(iPeriodic, translate);
- delete [] center; delete [] rotation; delete [] translate;
-
/*--- Deallocate temporary memory. ---*/
delete[] vertices;
@@ -13379,6 +14681,7 @@ void CPhysicalGeometry::SetRCM_Ordering(CConfig *config) {
node[iPoint]->ResetBoundary();
node[iPoint]->SetPhysicalBoundary(false);
node[iPoint]->SetSolidBoundary(false);
+ node[iPoint]->SetPeriodicBoundary(false);
node[iPoint]->SetDomain(true);
}
@@ -13450,6 +14753,9 @@ void CPhysicalGeometry::SetRCM_Ordering(CConfig *config) {
config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ||
config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL)
node[InvResult[iPoint]]->SetSolidBoundary(true);
+
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY)
+ node[InvResult[iPoint]]->SetPeriodicBoundary(true);
}
}
}
@@ -13605,8 +14911,7 @@ void CPhysicalGeometry::ComputeNSpan(CConfig *config, unsigned short val_iZone,
long jVertex;
int nSpan, nSpan_loc;
su2double *coord, *valueSpan, min, max, radius, delta;
- short SendRecv;
- bool isPeriodic;
+ short PeriodicBoundary;
unsigned short SpanWise_Kind = config->GetKind_SpanWise();
#ifdef HAVE_MPI
@@ -13642,15 +14947,11 @@ void CPhysicalGeometry::ComputeNSpan(CConfig *config, unsigned short val_iZone,
/*--- loop to find the vertex that ar both of inflow or outflow marker and on the periodic
* in order to caount the number of Span ---*/
for (jMarker = 0; jMarker < nMarker; jMarker++){
- if (config->GetMarker_All_KindBC(jMarker) == SEND_RECEIVE) {
- SendRecv = config->GetMarker_All_SendRecv(jMarker);
+ if (config->GetMarker_All_KindBC(jMarker) == PERIODIC_BOUNDARY) {
+ PeriodicBoundary = config->GetMarker_All_PerBound(jMarker);
jVertex = node[iPoint]->GetVertex(jMarker);
- if (jVertex != -1) {
- isPeriodic = ((vertex[jMarker][jVertex]->GetRotation_Type() > 0) && (vertex[jMarker][jVertex]->GetRotation_Type() % 2 == 1));
- if (isPeriodic && (SendRecv < 0)){
+ if ((jVertex != -1) && (PeriodicBoundary == (val_iZone + 1))){
nSpan++;
-
- }
}
}
}
@@ -13691,43 +14992,40 @@ void CPhysicalGeometry::ComputeNSpan(CConfig *config, unsigned short val_iZone,
for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
iPoint = vertex[iMarker][iVertex]->GetNode();
for (jMarker = 0; jMarker < nMarker; jMarker++){
- if (config->GetMarker_All_KindBC(jMarker) == SEND_RECEIVE) {
- SendRecv = config->GetMarker_All_SendRecv(jMarker);
- jVertex = node[iPoint]->GetVertex(jMarker);
- if (jVertex != -1) {
- isPeriodic = ((vertex[jMarker][jVertex]->GetRotation_Type() > 0) && (vertex[jMarker][jVertex]->GetRotation_Type() % 2 == 1));
- if (isPeriodic && (SendRecv < 0)){
- coord = node[iPoint]->GetCoord();
- switch (config->GetKind_TurboMachinery(val_iZone)){
- case CENTRIFUGAL:
- valueSpan[nSpan_loc] = coord[2];
- break;
- case CENTRIPETAL:
+ if (config->GetMarker_All_KindBC(jMarker) == PERIODIC_BOUNDARY) {
+ PeriodicBoundary = config->GetMarker_All_PerBound(jMarker);
+ jVertex = node[iPoint]->GetVertex(jMarker);
+ if ((jVertex != -1) && (PeriodicBoundary == (val_iZone + 1))){
+ coord = node[iPoint]->GetCoord();
+ switch (config->GetKind_TurboMachinery(val_iZone)){
+ case CENTRIFUGAL:
+ valueSpan[nSpan_loc] = coord[2];
+ break;
+ case CENTRIPETAL:
+ valueSpan[nSpan_loc] = coord[2];
+ break;
+ case AXIAL:
+ valueSpan[nSpan_loc] = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
+ break;
+ case CENTRIPETAL_AXIAL:
+ if (marker_flag == OUTFLOW){
+ valueSpan[nSpan_loc] = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
+ }
+ else{
valueSpan[nSpan_loc] = coord[2];
- break;
- case AXIAL:
+ }
+ break;
+ case AXIAL_CENTRIFUGAL:
+ if (marker_flag == INFLOW){
valueSpan[nSpan_loc] = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
- break;
- case CENTRIPETAL_AXIAL:
- if (marker_flag == OUTFLOW){
- valueSpan[nSpan_loc] = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
- }
- else{
- valueSpan[nSpan_loc] = coord[2];
- }
- break;
- case AXIAL_CENTRIFUGAL:
- if (marker_flag == INFLOW){
- valueSpan[nSpan_loc] = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
- }
- else{
- valueSpan[nSpan_loc] = coord[2];
- }
- break;
-
}
- nSpan_loc++;
+ else{
+ valueSpan[nSpan_loc] = coord[2];
+ }
+ break;
+
}
+ nSpan_loc++;
}
}
}
@@ -13827,48 +15125,44 @@ void CPhysicalGeometry::ComputeNSpan(CConfig *config, unsigned short val_iZone,
for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
iPoint = vertex[iMarker][iVertex]->GetNode();
for (jMarker = 0; jMarker < nMarker; jMarker++){
- if (config->GetMarker_All_KindBC(jMarker) == SEND_RECEIVE) {
- SendRecv = config->GetMarker_All_SendRecv(jMarker);
+ if (config->GetMarker_All_KindBC(jMarker) == PERIODIC_BOUNDARY) {
+ PeriodicBoundary = config->GetMarker_All_PerBound(jMarker);
jVertex = node[iPoint]->GetVertex(jMarker);
- if (jVertex != -1) {
- isPeriodic = ((vertex[jMarker][jVertex]->GetRotation_Type() > 0) && (vertex[jMarker][jVertex]->GetRotation_Type() % 2 == 1));
- if (isPeriodic && (SendRecv < 0)){
- coord = node[iPoint]->GetCoord();
- switch (config->GetKind_TurboMachinery(val_iZone)){
- case CENTRIFUGAL: case CENTRIPETAL:
+ if ((jVertex != -1) && (PeriodicBoundary == (val_iZone + 1))){
+ coord = node[iPoint]->GetCoord();
+ switch (config->GetKind_TurboMachinery(val_iZone)){
+ case CENTRIFUGAL: case CENTRIPETAL:
+ if (coord[2] < min) min = coord[2];
+ if (coord[2] > max) max = coord[2];
+ break;
+ case AXIAL:
+ radius = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
+ if (radius < min) min = radius;
+ if (radius > max) max = radius;
+ break;
+ case CENTRIPETAL_AXIAL:
+ if (marker_flag == OUTFLOW){
+ radius = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
+ if (radius < min) min = radius;
+ if (radius > max) max = radius;
+ }
+ else{
if (coord[2] < min) min = coord[2];
if (coord[2] > max) max = coord[2];
- break;
- case AXIAL:
+ }
+ break;
+
+ case AXIAL_CENTRIFUGAL:
+ if (marker_flag == INFLOW){
radius = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
if (radius < min) min = radius;
if (radius > max) max = radius;
- break;
- case CENTRIPETAL_AXIAL:
- if (marker_flag == OUTFLOW){
- radius = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
- if (radius < min) min = radius;
- if (radius > max) max = radius;
- }
- else{
- if (coord[2] < min) min = coord[2];
- if (coord[2] > max) max = coord[2];
- }
- break;
-
- case AXIAL_CENTRIFUGAL:
- if (marker_flag == INFLOW){
- radius = sqrt(coord[0]*coord[0]+coord[1]*coord[1]);
- if (radius < min) min = radius;
- if (radius > max) max = radius;
- }
- else{
- if (coord[2] < min) min = coord[2];
- if (coord[2] > max) max = coord[2];
- }
- break;
}
-
+ else{
+ if (coord[2] < min) min = coord[2];
+ if (coord[2] > max) max = coord[2];
+ }
+ break;
}
}
}
@@ -14822,7 +16116,6 @@ void CPhysicalGeometry::SetAvgTurboValue(CConfig *config, unsigned short val_iZo
if (config->GetMarker_All_Turbomachinery(iMarker) == iMarkerTP){
if (config->GetMarker_All_TurbomachineryFlag(iMarker) == marker_flag){
if(allocate){
- nSpanSectionsByMarker[iMarker] = nSpanWiseSections[marker_flag-1];
AverageTurboNormal[iMarker] = new su2double *[nSpanWiseSections[marker_flag-1] + 1];
AverageNormal[iMarker] = new su2double *[nSpanWiseSections[marker_flag-1] + 1];
AverageGridVel[iMarker] = new su2double *[nSpanWiseSections[marker_flag-1] + 1];
@@ -15435,9 +16728,9 @@ void CPhysicalGeometry::SetMaxLength(CConfig* config) {
node[iPoint]->SetMaxLength(max_delta);
}
- /*--- Distribute information twice for periodic boundaries ---*/
- Set_MPI_MaxLength(config);
- Set_MPI_MaxLength(config);
+ InitiateComms(this, config, MAX_LENGTH);
+ CompleteComms(this, config, MAX_LENGTH);
+
}
void CPhysicalGeometry::MatchInterface(CConfig *config) {
@@ -16064,6 +17357,396 @@ void CPhysicalGeometry::MatchActuator_Disk(CConfig *config) {
}
+void CPhysicalGeometry::MatchPeriodic(CConfig *config,
+ unsigned short val_periodic) {
+
+ unsigned short iMarker, iDim, jMarker, pMarker = 0, index;
+ unsigned short iPeriodic, nPeriodic;
+
+ unsigned long iVertex, iPoint, iPointGlobal;
+ unsigned long jVertex, jVertex_, jPoint, jPointGlobal;
+ unsigned long pVertex = 0, pPoint = 0, pPointGlobal = 0;
+ unsigned long nLocalVertex_Periodic = 0, MaxLocalVertex_Periodic = 0;
+ unsigned long nPointMatch = 0;
+
+ int iProcessor, pProcessor = 0, nProcessor = size;
+
+ bool isBadMatch = false;
+
+ string Marker_Tag;
+
+ su2double *Coord_i, Coord_j[3], dist, mindist, maxdist_local, maxdist_global;
+ su2double *center, *angles, translation[3]={0.0,0.0,0.0}, *trans, dx, dy, dz;
+ su2double rotMatrix[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
+ su2double Theta, Phi, Psi, cosTheta, sinTheta, cosPhi, sinPhi, cosPsi, sinPsi;
+ su2double rotCoord[3] = {0.0, 0.0, 0.0};
+
+ /*--- Tolerance for distance-based match to report warning. ---*/
+
+ su2double epsilon = 1e-6;
+
+ /*--- Evaluate the number of periodic boundary conditions ---*/
+
+ nPeriodic = config->GetnMarker_Periodic();
+
+ /*--- Send an initial message to the console. ---*/
+
+ if (rank == MASTER_NODE) {
+ cout << "Matching the periodic boundary points for marker pair ";
+ cout << val_periodic << "." << endl;
+ }
+
+ /*--- Compute the total number of vertices that sit on a periodic
+ boundary on our local rank. We only include our "owned" nodes. ---*/
+
+ nLocalVertex_Periodic = 0;
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ if ((iPeriodic == val_periodic) ||
+ (iPeriodic == val_periodic + nPeriodic/2)) {
+ for (iVertex = 0; iVertex < GetnVertex(iMarker); iVertex++) {
+ iPoint = vertex[iMarker][iVertex]->GetNode();
+ if (node[iPoint]->GetDomain()) nLocalVertex_Periodic++;
+ }
+ }
+ }
+ }
+
+ /*--- Communicate our local periodic point count globally
+ and receive the counts of periodic points from all other ranks.---*/
+
+ unsigned long *Buffer_Send_nVertex = new unsigned long [1];
+ unsigned long *Buffer_Recv_nVertex = new unsigned long [nProcessor];
+
+ Buffer_Send_nVertex[0] = nLocalVertex_Periodic;
+
+ /*--- Copy our own count in serial or use collective comms with MPI. ---*/
+
+#ifndef HAVE_MPI
+ MaxLocalVertex_Periodic = nLocalVertex_Periodic;
+ Buffer_Recv_nVertex[0] = Buffer_Send_nVertex[0];
+#else
+ SU2_MPI::Allreduce(&nLocalVertex_Periodic, &MaxLocalVertex_Periodic, 1,
+ MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG,
+ Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+#endif
+
+ /*--- Prepare buffers to send the information for each
+ periodic point to all ranks so that we can match pairs. ---*/
+
+ su2double *Buffer_Send_Coord = new su2double [MaxLocalVertex_Periodic*nDim];
+ unsigned long *Buffer_Send_Point = new unsigned long [MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Send_Vertex = new unsigned long [MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Send_Marker = new unsigned long [MaxLocalVertex_Periodic];
+
+ su2double *Buffer_Recv_Coord = new su2double [nProcessor*MaxLocalVertex_Periodic*nDim];
+ unsigned long *Buffer_Recv_Point = new unsigned long [nProcessor*MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Recv_Vertex = new unsigned long [nProcessor*MaxLocalVertex_Periodic];
+ unsigned long *Buffer_Recv_Marker = new unsigned long [nProcessor*MaxLocalVertex_Periodic];
+
+ unsigned long nBuffer_Coord = MaxLocalVertex_Periodic*nDim;
+ unsigned long nBuffer_Point = MaxLocalVertex_Periodic;
+ unsigned long nBuffer_GlobalIndex = MaxLocalVertex_Periodic;
+ unsigned long nBuffer_Vertex = MaxLocalVertex_Periodic;
+ unsigned long nBuffer_Marker = MaxLocalVertex_Periodic;
+
+ for (iVertex = 0; iVertex < MaxLocalVertex_Periodic; iVertex++) {
+ Buffer_Send_Point[iVertex] = 0;
+ Buffer_Send_GlobalIndex[iVertex] = 0;
+ Buffer_Send_Vertex[iVertex] = 0;
+ Buffer_Send_Marker[iVertex] = 0;
+ for (iDim = 0; iDim < nDim; iDim++)
+ Buffer_Send_Coord[iVertex*nDim+iDim] = 0.0;
+ }
+
+ /*--- Store the local index, global index, local boundary index,
+ marker index, and point coordinates in the buffers for sending.
+ Note again that this is only for the current pair of periodic
+ markers and for only the "owned" points on each rank. ---*/
+
+ nLocalVertex_Periodic = 0;
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ if ((iPeriodic == val_periodic) ||
+ (iPeriodic == val_periodic + nPeriodic/2)) {
+ for (iVertex = 0; iVertex < GetnVertex(iMarker); iVertex++) {
+ iPoint = vertex[iMarker][iVertex]->GetNode();
+ iPointGlobal = node[iPoint]->GetGlobalIndex();
+ if (node[iPoint]->GetDomain()) {
+ Buffer_Send_Point[nLocalVertex_Periodic] = iPoint;
+ Buffer_Send_GlobalIndex[nLocalVertex_Periodic] = iPointGlobal;
+ Buffer_Send_Vertex[nLocalVertex_Periodic] = iVertex;
+ Buffer_Send_Marker[nLocalVertex_Periodic] = iMarker;
+ for (iDim = 0; iDim < nDim; iDim++)
+ Buffer_Send_Coord[nLocalVertex_Periodic*nDim+iDim] = node[iPoint]->GetCoord(iDim);
+ nLocalVertex_Periodic++;
+ }
+ }
+ }
+ }
+ }
+
+ /*--- Copy our own data in serial or use collective comms to gather
+ the data for all points on each rank with MPI. Note that, since the
+ periodic point count should be small relative to the volume grid
+ and we are only storing one periodic marker pair at a time,
+ repeating the data for each pair on all ranks should be manageable. ---*/
+
+#ifndef HAVE_MPI
+ for (unsigned long iBuffer_Coord = 0; iBuffer_Coord < nBuffer_Coord; iBuffer_Coord++)
+ Buffer_Recv_Coord[iBuffer_Coord] = Buffer_Send_Coord[iBuffer_Coord];
+ for (unsigned long iBuffer_Point = 0; iBuffer_Point < nBuffer_Point; iBuffer_Point++)
+ Buffer_Recv_Point[iBuffer_Point] = Buffer_Send_Point[iBuffer_Point];
+ for (unsigned long iBuffer_GlobalIndex = 0; iBuffer_GlobalIndex < nBuffer_GlobalIndex; iBuffer_GlobalIndex++)
+ Buffer_Recv_GlobalIndex[iBuffer_GlobalIndex] = Buffer_Send_GlobalIndex[iBuffer_GlobalIndex];
+ for (unsigned long iBuffer_Vertex = 0; iBuffer_Vertex < nBuffer_Vertex; iBuffer_Vertex++)
+ Buffer_Recv_Vertex[iBuffer_Vertex] = Buffer_Send_Vertex[iBuffer_Vertex];
+ for (unsigned long iBuffer_Marker = 0; iBuffer_Marker < nBuffer_Marker; iBuffer_Marker++)
+ Buffer_Recv_Marker[iBuffer_Marker] = Buffer_Send_Marker[iBuffer_Marker];
+#else
+ SU2_MPI::Allgather(Buffer_Send_Coord, nBuffer_Coord, MPI_DOUBLE,
+ Buffer_Recv_Coord, nBuffer_Coord, MPI_DOUBLE, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_Point, nBuffer_Point, MPI_UNSIGNED_LONG,
+ Buffer_Recv_Point, nBuffer_Point, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_GlobalIndex, nBuffer_GlobalIndex, MPI_UNSIGNED_LONG,
+ Buffer_Recv_GlobalIndex, nBuffer_GlobalIndex, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_Vertex, nBuffer_Vertex, MPI_UNSIGNED_LONG,
+ Buffer_Recv_Vertex, nBuffer_Vertex, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(Buffer_Send_Marker, nBuffer_Marker, MPI_UNSIGNED_LONG,
+ Buffer_Recv_Marker, nBuffer_Marker, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+#endif
+
+ /*--- Now that all ranks have the data for all periodic points for
+ this pair of periodic markers, we match the individual points
+ based on the translation / rotation specified for the marker pair. ---*/
+
+ maxdist_local = 0.0;
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ if ((iPeriodic == val_periodic) ||
+ (iPeriodic == val_periodic + nPeriodic/2)) {
+
+ /*--- Retrieve the supplied periodic information. ---*/
+
+ Marker_Tag = config->GetMarker_All_TagBound(iMarker);
+ center = config->GetPeriodicRotCenter(Marker_Tag);
+ angles = config->GetPeriodicRotAngles(Marker_Tag);
+ trans = config->GetPeriodicTranslation(Marker_Tag);
+
+ /*--- Store (center+trans) as it is constant and will be added. ---*/
+
+ translation[0] = center[0] + trans[0];
+ translation[1] = center[1] + trans[1];
+ translation[2] = center[2] + trans[2];
+
+ /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
+
+ Theta = angles[0]; Phi = angles[1]; Psi = angles[2];
+ cosTheta = cos(Theta); cosPhi = cos(Phi); cosPsi = cos(Psi);
+ sinTheta = sin(Theta); sinPhi = sin(Phi); sinPsi = sin(Psi);
+
+ /*--- 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;
+
+ /*--- Loop over each point on the periodic marker that this rank
+ holds locally and find the matching point from the donor marker. ---*/
+
+ for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
+
+ /*--- Local and global index for the owned periodic point. ---*/
+
+ iPoint = vertex[iMarker][iVertex]->GetNode();
+ iPointGlobal = node[iPoint]->GetGlobalIndex();
+
+ /*--- If this is not a ghost, find the periodic match. ---*/
+
+ if (node[iPoint]->GetDomain()) {
+
+ /*--- Coordinates of the current boundary point ---*/
+
+ Coord_i = node[iPoint]->GetCoord();
+
+ /*--- Get the position vector from rotation center to point. ---*/
+
+ dx = Coord_i[0] - center[0];
+ dy = Coord_i[1] - center[1];
+ if (nDim == 3) dz = Coord_i[2] - center[2];
+ else dz = 0.0;
+
+ /*--- Compute transformed point coordinates. ---*/
+
+ rotCoord[0] = (rotMatrix[0][0]*dx +
+ rotMatrix[0][1]*dy +
+ rotMatrix[0][2]*dz + translation[0]);
+
+ rotCoord[1] = (rotMatrix[1][0]*dx +
+ rotMatrix[1][1]*dy +
+ rotMatrix[1][2]*dz + translation[1]);
+
+ rotCoord[2] = (rotMatrix[2][0]*dx +
+ rotMatrix[2][1]*dy +
+ rotMatrix[2][2]*dz + translation[2]);
+
+ /*--- Our search is based on the minimum distance, so we
+ initialize the distance to a large value. ---*/
+
+ mindist = 1E6; pProcessor = 0; pPoint = 0;
+
+ /*--- Loop over all of the periodic data that was gathered from
+ all ranks in order to find the matching periodic point. ---*/
+
+ for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
+ for (jVertex = 0; jVertex < Buffer_Recv_nVertex[iProcessor]; jVertex++) {
+
+ /*--- Store the loop index more easily. ---*/
+
+ index = iProcessor*MaxLocalVertex_Periodic + jVertex;
+
+ /*--- For each candidate, we have the local and global index,
+ along with the boundary vertex and marker index. ---*/
+
+ jPoint = Buffer_Recv_Point[index];
+ jPointGlobal = Buffer_Recv_GlobalIndex[index];
+ jVertex_ = Buffer_Recv_Vertex[index];
+ jMarker = Buffer_Recv_Marker[index];
+
+ /*--- The gathered data will also include the current
+ "owned" periodic point that we are matching, so first make
+ sure that we avoid the original point by checking that the
+ global index values are not the same. ---*/
+
+ if ((jPointGlobal != iPointGlobal)) {
+
+ /*--- Compute the distance between the candidate periodic
+ point and the transformed coordinates of the owned point. ---*/
+
+ dist = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++) {
+ Coord_j[iDim] = Buffer_Recv_Coord[index*nDim + iDim];
+ dist += pow(Coord_j[iDim]-rotCoord[iDim],2.0);
+ }
+ dist = sqrt(dist);
+
+ /*--- Compare the distance against the existing minimum
+ and also perform checks just to be sure that this is an
+ independent periodic point (even if on the same rank). ---*/
+
+ if (((dist < mindist) && (iProcessor != rank)) ||
+ ((dist < mindist) && (iProcessor == rank) && (jPoint != iPoint))) {
+
+ /*--- We have found an intermediate match. Store the
+ data for this point before continuing the search. ---*/
+
+ mindist = dist;
+ pProcessor = iProcessor;
+ pPoint = jPoint;
+ pPointGlobal = jPointGlobal;
+ pVertex = jVertex_;
+ pMarker = jMarker;
+
+ }
+ }
+
+ }
+
+ /*--- Store the data for the best match found for the
+ owned periodic point. ---*/
+
+ vertex[iMarker][iVertex]->SetDonorPoint(pPoint, pPointGlobal, pVertex, pMarker, pProcessor);
+ maxdist_local = max(maxdist_local, mindist);
+ nPointMatch++;
+
+ /*--- If the distance to the closest point is larger than our
+ tolerance, then throw a warning for this point. ---*/
+
+ if (mindist > epsilon) {
+ cout.precision(10);
+ cout << endl;
+ cout << " Bad match for point " << iPointGlobal << ".\tNearest";
+ cout << " donor distance: " << scientific << mindist << ".";
+ maxdist_local = min(maxdist_local, 0.0);
+ isBadMatch = true;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ /*--- Communicate the final count of number of matched points
+ for the periodic boundary pair and the max distance for all
+ pairs of points. ---*/
+
+#ifndef HAVE_MPI
+ maxdist_global = maxdist_local;
+#else
+ unsigned long nPointMatch_Local = nPointMatch;
+ SU2_MPI::Reduce(&nPointMatch_Local, &nPointMatch, 1, MPI_UNSIGNED_LONG,
+ MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
+ SU2_MPI::Reduce(&maxdist_local, &maxdist_global, 1, MPI_DOUBLE,
+ MPI_MAX, MASTER_NODE, MPI_COMM_WORLD);
+#endif
+
+ /*--- Output some information about the matching process. ---*/
+
+ if (rank == MASTER_NODE) {
+ if (nPointMatch > 0) {
+ cout <<" Matched " << nPointMatch << " points with a max distance of: ";
+ cout << maxdist_global <<"."<< endl;
+ } else {
+ cout <<" No matching points for periodic marker pair ";
+ cout << val_periodic << " in current zone." << endl;
+ }
+
+ /*--- Print final warning when finding bad matches. ---*/
+
+ if (isBadMatch) {
+ cout << endl;
+ cout << "\n !!! Warning !!!" << endl;
+ cout << "Bad matches found. Computation will continue, but be cautious.\n";
+ }
+ }
+
+ /*--- Free local memory for communications. ---*/
+
+ delete[] Buffer_Send_Coord;
+ delete[] Buffer_Send_Point;
+
+ delete[] Buffer_Recv_Coord;
+ delete[] Buffer_Recv_Point;
+
+ delete[] Buffer_Send_nVertex;
+ delete[] Buffer_Recv_nVertex;
+
+ delete [] Buffer_Send_GlobalIndex;
+ delete [] Buffer_Send_Vertex;
+ delete [] Buffer_Send_Marker;
+
+ delete [] Buffer_Recv_GlobalIndex;
+ delete [] Buffer_Recv_Vertex;
+ delete [] Buffer_Recv_Marker;
+
+}
void CPhysicalGeometry::SetControlVolume(CConfig *config, unsigned short action) {
unsigned long face_iPoint = 0, face_jPoint = 0, iPoint, iElem;
@@ -19138,28 +20821,10 @@ void CPhysicalGeometry::ReadUnorderedSensitivity(CConfig *config) {
void CPhysicalGeometry::Check_Periodicity(CConfig *config) {
- bool isPeriodic = false;
- unsigned long iVertex;
- unsigned short iMarker, RotationKind, nPeriodicR = 0, nPeriodicS = 0;
-
- /*--- Check for the presence of any periodic BCs ---*/
-
- for (iMarker = 0; iMarker < nMarker; iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
- for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
- RotationKind = vertex[iMarker][iVertex]->GetRotation_Type();
- if (RotationKind > 0) nPeriodicS++;
- }
- }
- }
-#ifndef HAVE_MPI
- nPeriodicR = nPeriodicS;
-#else
- SU2_MPI::Allreduce(&nPeriodicS, &nPeriodicR, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD);
-#endif
- if (nPeriodicR != 0) isPeriodic = true;
-
- if (isPeriodic && (config->GetnMGLevels() > 0)) {
+ /*--- Check for the presence of any periodic BCs and disable multigrid
+ for now if found. ---*/
+
+ if ((config->GetnMarker_Periodic() != 0) && (config->GetnMGLevels() > 0)) {
if (rank == MASTER_NODE)
cout << "WARNING: Periodicity has been detected. Disabling multigrid. "<< endl;
config->SetMGLevels(0);
@@ -21670,6 +23335,33 @@ void CMultiGridGeometry::MatchInterface(CConfig *config) {
}
+void CMultiGridGeometry::MatchPeriodic(CConfig *config, unsigned short val_periodic) {
+
+ unsigned short iMarker, iPeriodic, nPeriodic;
+ unsigned long iVertex, iPoint;
+ int iProcessor = rank;
+
+ /*--- Evaluate the number of periodic boundary conditions ---*/
+
+ nPeriodic = config->GetnMarker_Periodic();
+
+ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
+ if (config->GetMarker_All_KindBC(iMarker) == PERIODIC_BOUNDARY) {
+ iPeriodic = config->GetMarker_All_PerBound(iMarker);
+ if ((iPeriodic == val_periodic) ||
+ (iPeriodic == val_periodic + nPeriodic/2)) {
+ for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
+ iPoint = vertex[iMarker][iVertex]->GetNode();
+ if (node[iPoint]->GetDomain()) {
+ vertex[iMarker][iVertex]->SetDonorPoint(iPoint, node[iPoint]->GetGlobalIndex(), iVertex, iMarker, iProcessor);
+ }
+ }
+ }
+ }
+ }
+
+}
+
void CMultiGridGeometry::SetControlVolume(CConfig *config, CGeometry *fine_grid, unsigned short action) {
unsigned long iFinePoint, iFinePoint_Neighbor, iCoarsePoint, iEdge, iParent;
diff --git a/Common/src/grid_adaptation_structure.cpp b/Common/src/grid_adaptation_structure.cpp
index 51145213bc52..74c190b3e412 100644
--- a/Common/src/grid_adaptation_structure.cpp
+++ b/Common/src/grid_adaptation_structure.cpp
@@ -3210,7 +3210,8 @@ void CGridAdaptation::SetIndicator_Flow(CGeometry *geometry, CConfig *config, un
}
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
Solution_Vertex = ConsVar_Sol[Point][0];
@@ -3220,7 +3221,8 @@ void CGridAdaptation::SetIndicator_Flow(CGeometry *geometry, CConfig *config, un
Gradient[Point][iDim] = Gradient[Point][iDim] - Partial_Res;
}
}
-
+ }
+
for (iPoint = 0; iPointGetnPoint(); iPoint++)
for (iDim = 0; iDim < nDim; iDim++) {
DualArea = geometry->node[iPoint]->GetVolume();
@@ -3277,7 +3279,8 @@ void CGridAdaptation::SetIndicator_Adj(CGeometry *geometry, CConfig *config, uns
}
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
Solution_Vertex = AdjVar_Sol[Point][0];
@@ -3287,6 +3290,7 @@ void CGridAdaptation::SetIndicator_Adj(CGeometry *geometry, CConfig *config, uns
Gradient[Point][iDim] = Gradient[Point][iDim] - Partial_Res;
}
}
+ }
for (iPoint = 0; iPointGetnPoint(); iPoint++)
for (iDim = 0; iDim < nDim; iDim++) {
@@ -3347,7 +3351,8 @@ void CGridAdaptation::SetIndicator_FlowAdj(CGeometry *geometry, CConfig *config)
}
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
@@ -3356,6 +3361,7 @@ void CGridAdaptation::SetIndicator_FlowAdj(CGeometry *geometry, CConfig *config)
Gradient_Adj[Point][iDim] = Gradient_Adj[Point][iDim] - AdjVar_Sol[Point][0] * Normal[iDim];
}
}
+ }
for (iPoint = 0; iPointGetnPoint(); iPoint++)
for (iDim = 0; iDim < nDim; iDim++) {
diff --git a/Common/src/grid_movement_structure.cpp b/Common/src/grid_movement_structure.cpp
index f0e481359ba5..073dee7ecc57 100644
--- a/Common/src/grid_movement_structure.cpp
+++ b/Common/src/grid_movement_structure.cpp
@@ -97,8 +97,9 @@ void CVolumetricMovement::UpdateGridCoord(CGeometry *geometry, CConfig *config)
* Hence we still need a communication of the transformed coordinates, otherwise periodicity
* is not maintained. ---*/
- geometry->Set_MPI_Coord(config);
-
+ geometry->InitiateComms(geometry, config, COORDINATES);
+ geometry->CompleteComms(geometry, config, COORDINATES);
+
}
void CVolumetricMovement::UpdateDualGrid(CGeometry *geometry, CConfig *config) {
@@ -191,9 +192,12 @@ void CVolumetricMovement::SetVolume_Deformation(CGeometry *geometry, CConfig *co
/*--- Communicate any prescribed boundary displacements via MPI,
so that all nodes have the same solution and r.h.s. entries
across all partitions. ---*/
-
- StiffMatrix.SendReceive_Solution(LinSysSol, geometry, config);
- StiffMatrix.SendReceive_Solution(LinSysRes, geometry, config);
+
+ 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);
/*--- Definition of the preconditioner matrix vector multiplication, and linear solver ---*/
@@ -250,7 +254,7 @@ void CVolumetricMovement::SetVolume_Deformation(CGeometry *geometry, CConfig *co
Tot_Iter = 0; MaxIter = RestartIter;
- System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, 1, &Residual_Init, false);
+ System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, 1, &Residual_Init, false, config);
if ((rank == MASTER_NODE) && Screen_Output) {
cout << "\n# FGMRES (with restart) residual history" << endl;
@@ -265,7 +269,8 @@ void CVolumetricMovement::SetVolume_Deformation(CGeometry *geometry, CConfig *co
if (IterLinSol + RestartIter > Smoothing_Iter)
MaxIter = Smoothing_Iter - IterLinSol;
- IterLinSol = System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, MaxIter, &Residual, false);
+ IterLinSol = System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, MaxIter, &Residual, false, config);
+
Tot_Iter += IterLinSol;
if ((rank == MASTER_NODE) && Screen_Output) { cout << " " << Tot_Iter << " " << Residual/Residual_Init << endl; }
@@ -285,7 +290,7 @@ void CVolumetricMovement::SetVolume_Deformation(CGeometry *geometry, CConfig *co
case FGMRES:
- Tot_Iter = System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output);
+ Tot_Iter = System.FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output, config);
break;
@@ -293,14 +298,14 @@ void CVolumetricMovement::SetVolume_Deformation(CGeometry *geometry, CConfig *co
case BCGSTAB:
- Tot_Iter = System.BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output);
+ Tot_Iter = System.BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output, config);
break;
case CONJUGATE_GRADIENT:
- Tot_Iter = System.CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output);
+ Tot_Iter = System.CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, NumError, Smoothing_Iter, &Residual, Screen_Output, config);
break;
@@ -3360,7 +3365,6 @@ void CSurfaceMovement::SetParametricCoord(CGeometry *geometry, CConfig *config,
}
#ifdef HAVE_MPI
- SU2_MPI::Barrier(MPI_COMM_WORLD);
SU2_MPI::Allreduce(&my_MaxDiff, &MaxDiff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
#else
MaxDiff = my_MaxDiff;
@@ -9238,8 +9242,11 @@ void CElasticityMovement::SetVolume_Deformation_Elas(CGeometry *geometry, CConfi
AD::StopRecording();
}
#endif
- StiffMatrix.SendReceive_Solution(LinSysSol, geometry, config);
- StiffMatrix.SendReceive_Solution(LinSysRes, geometry, config);
+ 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
@@ -9289,8 +9296,9 @@ void CElasticityMovement::UpdateGridCoord(CGeometry *geometry, CConfig *config){
* Hence we still need a communication of the transformed coordinates, otherwise periodicity
* is not maintained. ---*/
- geometry->Set_MPI_Coord(config);
-
+ geometry->InitiateComms(geometry, config, COORDINATES);
+ geometry->CompleteComms(geometry, config, COORDINATES);
+
}
@@ -9361,7 +9369,8 @@ void CElasticityMovement::SetBoundaryDisplacements(CGeometry *geometry, CConfig
}
}
}
- StiffMatrix.SendReceive_Solution(LinSysSol, geometry, config);
+ StiffMatrix.InitiateComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
+ StiffMatrix.CompleteComms(LinSysSol, geometry, config, SOLUTION_MATRIX);
/*--- Apply displacement boundary conditions to the FSI interfaces. ---*/
diff --git a/Common/src/linear_solvers_structure.cpp b/Common/src/linear_solvers_structure.cpp
index 6d0d0eee3c9d..32ee01388549 100644
--- a/Common/src/linear_solvers_structure.cpp
+++ b/Common/src/linear_solvers_structure.cpp
@@ -197,10 +197,12 @@ void CSysSolve::WriteHistory(const int & iter, const su2double & res, const su2d
}
unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
- CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring) {
+ CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring, CConfig *config) {
int rank = SU2_MPI::GetRank();
-
+ su2double norm_r = 0.0, norm0 = 0.0;
+ int i = 0;
+
/*--- Check the subspace size ---*/
if (m < 1) {
@@ -218,32 +220,38 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMat
}
/*--- Calculate the initial residual, compute norm, and check if system is already solved ---*/
-
+
mat_vec(x, A_x);
r = b; r -= A_x;
- su2double norm_r = r.norm();
- su2double norm0 = b.norm();
- if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
- if (rank == MASTER_NODE) cout << "CSysSolve::ConjugateGradient(): system solved by initial guess." << endl;
- return 0;
+
+ /*--- Only compute the residuals in full communication mode. ---*/
+
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ norm_r = r.norm();
+ norm0 = b.norm();
+ if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
+ if (rank == MASTER_NODE) cout << "CSysSolve::ConjugateGradient(): system solved by initial guess." << endl;
+ return 0;
+ }
+
+ /*--- Set the norm to the initial initial residual value ---*/
+
+ norm0 = norm_r;
+
+ /*--- Output header information including initial residual ---*/
+
+ if ((monitoring) && (rank == MASTER_NODE)) {
+ WriteHeader("CG", tol, norm_r);
+ WriteHistory(i, norm_r, norm0);
+ }
+
}
su2double alpha, beta, r_dot_z;
precond(r, z);
p = z;
-
- /*--- Set the norm to the initial initial residual value ---*/
-
- norm0 = norm_r;
-
- /*--- Output header information including initial residual ---*/
-
- int i = 0;
- if ((monitoring) && (rank == MASTER_NODE)) {
- WriteHeader("CG", tol, norm_r);
- WriteHistory(i, norm_r, norm0);
- }
-
+
/*--- Loop over all search directions ---*/
for (i = 0; i < (int)m; i++) {
@@ -263,11 +271,17 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMat
x.Plus_AX(alpha, p);
r.Plus_AX(-alpha, A_x);
- /*--- Check if solution has converged, else output the relative residual if necessary ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm_r = r.norm();
- if (norm_r < tol*norm0) break;
- if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 10 == 0)) WriteHistory(i+1, norm_r, norm0);
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ /*--- Check if solution has converged, else output the relative residual if necessary ---*/
+
+ norm_r = r.norm();
+ if (norm_r < tol*norm0) break;
+ if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 10 == 0)) WriteHistory(i+1, norm_r, norm0);
+
+ }
precond(r, z);
@@ -284,16 +298,14 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMat
}
-
-
- if ((monitoring) && (rank == MASTER_NODE)) {
- cout << "# Conjugate Gradient final (true) residual:" << endl;
- cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
- }
-
/*--- Recalculate final residual (this should be optional) ---*/
- if (monitoring) {
+ if ((monitoring) && (config->GetComm_Level() == COMM_FULL)) {
+
+ if (rank == MASTER_NODE) {
+ cout << "# Conjugate Gradient final (true) residual:" << endl;
+ cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
+ }
mat_vec(x, A_x);
r = b; r -= A_x;
@@ -309,7 +321,6 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMat
}
}
-
(*residual) = norm_r;
return (unsigned long) i;
@@ -317,7 +328,7 @@ unsigned long CSysSolve::CG_LinSolver(const CSysVector & b, CSysVector & x, CMat
}
unsigned long CSysSolve::FGMRES_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
- CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring) {
+ CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring, CConfig *config) {
int rank = SU2_MPI::GetRank();
@@ -470,9 +481,11 @@ unsigned long CSysSolve::FGMRES_LinSolver(const CSysVector & b, CSysVector & x,
}
unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
- CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring) {
+ CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring, CConfig *config) {
int rank = SU2_MPI::GetRank();
+ su2double norm_r = 0.0, norm0 = 0.0;
+ int i = 0;
/*--- Check the subspace size ---*/
@@ -496,11 +509,29 @@ unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x,
mat_vec(x, A_x);
r = b; r -= A_x;
- su2double norm_r = r.norm();
- su2double norm0 = b.norm();
- if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
- if (rank == MASTER_NODE) cout << "CSysSolve::BCGSTAB(): system solved by initial guess." << endl;
- return 0;
+
+ /*--- Only compute the residuals in full communication mode. ---*/
+
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ norm_r = r.norm();
+ norm0 = b.norm();
+ if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
+ if (rank == MASTER_NODE) cout << "CSysSolve::BCGSTAB(): system solved by initial guess." << endl;
+ return 0;
+ }
+
+ /*--- Set the norm to the initial initial residual value ---*/
+
+ norm0 = norm_r;
+
+ /*--- Output header information including initial residual ---*/
+
+ if ((monitoring) && (rank == MASTER_NODE)) {
+ WriteHeader("BCGSTAB", tol, norm_r);
+ WriteHistory(i, norm_r, norm0);
+ }
+
}
/*--- Initialization ---*/
@@ -508,18 +539,6 @@ unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x,
su2double alpha = 1.0, beta = 1.0, omega = 1.0, rho = 1.0, rho_prime = 1.0;
p = su2double(0.0); v = su2double(0.0); r_0 = r;
- /*--- Set the norm to the initial initial residual value ---*/
-
- norm0 = norm_r;
-
- /*--- Output header information including initial residual ---*/
-
- int i = 0;
- if ((monitoring) && (rank == MASTER_NODE)) {
- WriteHeader("BCGSTAB", tol, norm_r);
- WriteHistory(i, norm_r, norm0);
- }
-
/*--- Loop over all search directions ---*/
for (i = 0; i < (int)m; i++) {
@@ -575,21 +594,29 @@ unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x,
/*--- r_{i} = r_{i-1/2} - omega * A * z ---*/
r.Plus_AX(-omega, A_x);
- /*--- Check if solution has converged, else output the relative residual if necessary ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm_r = r.norm();
- if (norm_r < tol*norm0) break;
- if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 10 == 0) && (rank == MASTER_NODE)) WriteHistory(i+1, norm_r, norm0);
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ /*--- Check if solution has converged, else output the relative residual if necessary ---*/
+
+ norm_r = r.norm();
+ if (norm_r < tol*norm0) break;
+ if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 10 == 0) && (rank == MASTER_NODE)) WriteHistory(i+1, norm_r, norm0);
+
+ }
}
- if ((monitoring) && (rank == MASTER_NODE)) {
- cout << "# BCGSTAB final (true) residual:" << endl;
- cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
- }
+ /*--- Recalculate final residual (this should be optional) ---*/
- /*--- Recalculate final residual (this should be optional) ---*/
- if (monitoring) {
+ if ((monitoring) && (config->GetComm_Level() == COMM_FULL)) {
+
+ if (rank == MASTER_NODE) {
+ cout << "# BCGSTAB final (true) residual:" << endl;
+ cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
+ }
+
mat_vec(x, A_x);
r = b; r -= A_x;
su2double true_res = r.norm();
@@ -600,6 +627,7 @@ unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x,
cout << "# true_res = " << true_res <<", calc_res = " << norm_r <<", tol = " << tol*10 <<"."<< endl;
cout << "# true_res - calc_res = " << true_res <<" "<< norm_r << endl;
}
+
}
(*residual) = norm_r;
@@ -688,13 +716,13 @@ unsigned long CSysSolve::Solve(CSysMatrix & Jacobian, CSysVector & LinSysRes, CS
switch (KindSolver) {
case BCGSTAB:
- IterLinSol = BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput);
+ IterLinSol = BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput, config);
break;
case FGMRES:
- IterLinSol = FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput);
+ IterLinSol = FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput, config);
break;
case CONJUGATE_GRADIENT:
- IterLinSol = CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput);
+ IterLinSol = CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput, config);
break;
case RESTARTED_FGMRES:
IterLinSol = 0;
@@ -702,7 +730,7 @@ unsigned long CSysSolve::Solve(CSysMatrix & Jacobian, CSysVector & LinSysRes, CS
while (IterLinSol < MaxIter) {
/*--- Enforce a hard limit on total number of iterations ---*/
unsigned long IterLimit = min(RestartIter, MaxIter-IterLinSol);
- IterLinSol += FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, IterLimit, &Residual, ScreenOutput);
+ IterLinSol += FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, IterLimit, &Residual, ScreenOutput, config);
if ( Residual < SolverTol*Norm0 ) break;
}
break;
@@ -755,7 +783,7 @@ unsigned long CSysSolve::Solve(CSysMatrix & Jacobian, CSysVector & LinSysRes, CS
AD::StartRecording();
- AD::SetExtFuncOut(&LinSysSol[0], LinSysSol.GetLocSize());
+ AD::SetExtFuncOut(&LinSysSol[0], (int)LinSysSol.GetLocSize());
#ifdef CODI_REVERSE_TYPE
AD::FuncHelper->addUserData(&LinSysRes);
@@ -841,13 +869,13 @@ unsigned long CSysSolve::Solve_b(CSysMatrix & Jacobian, CSysVector & LinSysRes,
switch(KindSolver) {
case FGMRES:
- IterLinSol = FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , MaxIter, &Residual, ScreenOutput);
+ IterLinSol = FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , MaxIter, &Residual, ScreenOutput, config);
break;
case BCGSTAB:
- IterLinSol = BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , MaxIter, &Residual, ScreenOutput);
+ IterLinSol = BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , MaxIter, &Residual, ScreenOutput, config);
break;
case CONJUGATE_GRADIENT:
- IterLinSol = CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput);
+ IterLinSol = CG_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, ScreenOutput, config);
break;
case RESTARTED_FGMRES:
IterLinSol = 0;
@@ -855,7 +883,7 @@ unsigned long CSysSolve::Solve_b(CSysMatrix & Jacobian, CSysVector & LinSysRes,
while (IterLinSol < MaxIter) {
/*--- Enforce a hard limit on total number of iterations ---*/
unsigned long IterLimit = min(RestartIter, MaxIter-IterLinSol);
- IterLinSol += FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , IterLimit, &Residual, ScreenOutput);
+ IterLinSol += FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol , IterLimit, &Residual, ScreenOutput, config);
if ( Residual < SolverTol*Norm0 ) break;
}
break;
diff --git a/Common/src/linear_solvers_structure_b.cpp b/Common/src/linear_solvers_structure_b.cpp
index 033dbc71f415..be986badefa2 100644
--- a/Common/src/linear_solvers_structure_b.cpp
+++ b/Common/src/linear_solvers_structure_b.cpp
@@ -76,5 +76,4 @@ void CSysSolve_b::Solve_b(const codi::RealReverse::Real* x, codi::RealReverse::R
}
}
-
#endif
diff --git a/Common/src/matrix_structure.cpp b/Common/src/matrix_structure.cpp
index b7e8d8cbd354..82efa98295a6 100644
--- a/Common/src/matrix_structure.cpp
+++ b/Common/src/matrix_structure.cpp
@@ -410,6 +410,279 @@ void CSysMatrix::SetIndexes(unsigned long val_nPoint, unsigned long val_nPointDo
}
+void CSysMatrix::InitiateComms(CSysVector & x,
+ CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iVar;
+ unsigned short COUNT_PER_POINT = 0;
+ unsigned short MPI_TYPE = 0;
+
+ unsigned long iPoint, offset, buf_offset;
+
+ int iMessage, iSend, nSend;
+
+ /*--- Create a boolean for reversing the order of comms. ---*/
+
+ bool reverse = false;
+
+ /*--- Set the size of the data packet and type depending on quantity. ---*/
+
+ switch (commType) {
+ case SOLUTION_MATRIX:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ reverse = false;
+ break;
+ case SOLUTION_MATRIXTRANS:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ reverse = true;
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ /*--- Check to make sure we have created a large enough buffer
+ for these comms during preprocessing. This is only for the su2double
+ buffer. It will be reallocated whenever we find a larger count
+ per point. After the first cycle of comms, this should be inactive. ---*/
+
+ if (COUNT_PER_POINT > geometry->countPerPoint) {
+ geometry->AllocateP2PComms(COUNT_PER_POINT);
+ }
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDSend = geometry->bufD_P2PSend;
+
+ /*--- Load the specified quantity from the solver into the generic
+ communication buffer in the geometry class. ---*/
+
+ if (geometry->nP2PSend > 0) {
+
+ /*--- Post all non-blocking recvs first before sends. ---*/
+
+ geometry->PostP2PRecvs(geometry, config, MPI_TYPE, reverse);
+
+ for (iMessage = 0; iMessage < geometry->nP2PSend; iMessage++) {
+
+ switch (commType) {
+
+ case SOLUTION_MATRIX:
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = geometry->nPoint_P2PSend[iMessage];
+
+ /*--- Total count can include multiple pieces of data per point. ---*/
+
+ nSend = (geometry->nPoint_P2PSend[iMessage+1] -
+ geometry->nPoint_P2PSend[iMessage]);
+
+ for (iSend = 0; iSend < nSend; iSend++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PSend[offset + iSend];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iSend)*geometry->countPerPoint;
+
+ /*--- Load the buffer with the data to be sent. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = x[iPoint*nVar+iVar];
+
+ }
+
+ break;
+
+ case SOLUTION_MATRIXTRANS:
+
+ /*--- We are going to communicate in reverse, so we use the
+ recv buffer for the send instead. Also, all of the offsets
+ and counts are derived from the recv data structures. ---*/
+
+ bufDSend = geometry->bufD_P2PRecv;
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = geometry->nPoint_P2PRecv[iMessage];
+
+ /*--- Total count can include multiple pieces of data per point. ---*/
+
+ nSend = (geometry->nPoint_P2PRecv[iMessage+1] -
+ geometry->nPoint_P2PRecv[iMessage]);
+
+ for (iSend = 0; iSend < nSend; iSend++) {
+
+ /*--- Get the local index for this communicated data. Here we
+ again use the recv structure to find the send point, since
+ the usual recv points are now the senders in reverse mode. ---*/
+
+ iPoint = geometry->Local_Point_P2PRecv[offset + iSend];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iSend)*geometry->countPerPoint;
+
+ /*--- Load the buffer with the data to be sent. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = x[iPoint*nVar+iVar];
+
+ }
+
+ break;
+
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+
+ }
+
+ /*--- Launch the point-to-point MPI send for this message. ---*/
+
+ geometry->PostP2PSends(geometry, config, MPI_TYPE, iMessage, reverse);
+
+ }
+ }
+
+}
+
+void CSysMatrix::CompleteComms(CSysVector & x,
+ CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iVar;
+ unsigned long iPoint, iRecv, nRecv, offset, buf_offset;
+
+ int ind, source, iMessage, jRecv;
+ SU2_MPI::Status status;
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDRecv = geometry->bufD_P2PRecv;
+
+ /*--- Store the data that was communicated into the appropriate
+ location within the local class data structures. ---*/
+
+ if (geometry->nP2PRecv > 0) {
+
+ for (iMessage = 0; iMessage < geometry->nP2PRecv; iMessage++) {
+
+ /*--- For efficiency, recv the messages dynamically based on
+ the order they arrive. ---*/
+
+ SU2_MPI::Waitany(geometry->nP2PRecv, geometry->req_P2PRecv,
+ &ind, &status);
+
+ /*--- Once we have recv'd a message, get the source rank. ---*/
+
+ source = status.MPI_SOURCE;
+
+ switch (commType) {
+ case SOLUTION_MATRIX:
+
+ /*--- We know the offsets based on the source rank. ---*/
+
+ jRecv = geometry->P2PRecv2Neighbor[source];
+
+ /*--- Get the point offset for the start of this message. ---*/
+
+ offset = geometry->nPoint_P2PRecv[jRecv];
+
+ /*--- Get the number of packets to be received in this message. ---*/
+
+ nRecv = (geometry->nPoint_P2PRecv[jRecv+1] -
+ geometry->nPoint_P2PRecv[jRecv]);
+
+ for (iRecv = 0; iRecv < nRecv; iRecv++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PRecv[offset + iRecv];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iRecv)*geometry->countPerPoint;
+
+ /*--- Store the data correctly depending on the quantity. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ x[iPoint*nVar+iVar] = bufDRecv[buf_offset+iVar];
+
+ }
+ break;
+
+ case SOLUTION_MATRIXTRANS:
+
+ /*--- We are going to communicate in reverse, so we use the
+ send buffer for the recv instead. Also, all of the offsets
+ and counts are derived from the send data structures. ---*/
+
+ bufDRecv = geometry->bufD_P2PSend;
+
+ /*--- We know the offsets based on the source rank. ---*/
+
+ jRecv = geometry->P2PSend2Neighbor[source];
+
+ /*--- Get the point offset for the start of this message. ---*/
+
+ offset = geometry->nPoint_P2PSend[jRecv];
+
+ /*--- Get the number of packets to be received in this message. ---*/
+
+ nRecv = (geometry->nPoint_P2PSend[jRecv+1] -
+ geometry->nPoint_P2PSend[jRecv]);
+
+ for (iRecv = 0; iRecv < nRecv; iRecv++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PSend[offset + iRecv];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iRecv)*geometry->countPerPoint;
+
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ x[iPoint*nVar+iVar] += bufDRecv[buf_offset+iVar];
+
+ }
+
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+
+ /*--- Verify that all non-blocking point-to-point sends have finished.
+ Note that this should be satisfied, as we have received all of the
+ data in the loop above at this point. ---*/
+
+#ifdef HAVE_MPI
+ SU2_MPI::Waitall(geometry->nP2PSend, geometry->req_P2PSend, MPI_STATUS_IGNORE);
+#endif
+
+ }
+
+}
+
su2double *CSysMatrix::GetBlock(unsigned long block_i, unsigned long block_j) {
unsigned long step = 0, index;
@@ -660,7 +933,6 @@ void CSysMatrix::DeleteValsRowi(unsigned long i) {
}
-
su2double CSysMatrix::MatrixDeterminant(su2double **a, unsigned long n) {
unsigned long i, j, j1, j2;
@@ -1216,7 +1488,9 @@ void CSysMatrix::MatrixVectorProduct(const CSysVector & vec, CSysVector & prod,
}
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
}
@@ -1247,8 +1521,10 @@ void CSysMatrix::MatrixVectorProductTransposed(const CSysVector & vec, CSysVecto
}
/*--- MPI Parallelization ---*/
- SendReceive_SolutionTransposed(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIXTRANS);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIXTRANS);
+
}
void CSysMatrix::GetMultBlockBlock(su2double *c, su2double *a, su2double *b) {
@@ -1448,13 +1724,16 @@ void CSysMatrix::ComputeJacobiPreconditioner(const CSysVector & vec, CSysVector
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
}
unsigned long CSysMatrix::Jacobi_Smoother(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec, su2double tol, unsigned long m, su2double *residual, bool monitoring, CGeometry *geometry, CConfig *config) {
unsigned long iPoint, iVar, jVar;
+ su2double norm_r = 0.0, norm0 = 0.0;
+ int i = 0;
/*--- Check the number of iterations requested ---*/
@@ -1476,25 +1755,31 @@ unsigned long CSysMatrix::Jacobi_Smoother(const CSysVector & b, CSysVector & x,
mat_vec(x, A_x);
r -= A_x;
- su2double norm_r = r.norm();
- su2double norm0 = b.norm();
- if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
- if (rank == MASTER_NODE) cout << "CSysMatrix::Jacobi_Smoother(): system solved by initial guess." << endl;
- return 0;
- }
- /*--- Set the norm to the initial initial residual value ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm0 = norm_r;
-
- /*--- Output header information including initial residual ---*/
-
- int i = 0;
- if ((monitoring) && (rank == MASTER_NODE)) {
- cout << "\n# " << "Jacobi Smoother" << " residual history" << endl;
- cout << "# Residual tolerance target = " << tol << endl;
- cout << "# Initial residual norm = " << norm_r << endl;
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ norm_r = r.norm();
+ norm0 = b.norm();
+ if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
+ if (rank == MASTER_NODE) cout << "CSysMatrix::Jacobi_Smoother(): system solved by initial guess." << endl;
+ return 0;
+ }
+
+ /*--- Set the norm to the initial residual value ---*/
+
+ norm0 = norm_r;
+
+ /*--- Output header information including initial residual ---*/
+
+ if ((monitoring) && (rank == MASTER_NODE)) {
+ cout << "\n# " << "Jacobi Smoother" << " residual history" << endl;
+ cout << "# Residual tolerance target = " << tol << endl;
+ cout << "# Initial residual norm = " << norm_r << endl;
+ cout << " " << i << " " << norm_r/norm0 << endl;
+ }
+
}
/*--- Loop over all smoothing iterations ---*/
@@ -1515,7 +1800,8 @@ unsigned long CSysMatrix::Jacobi_Smoother(const CSysVector & b, CSysVector & x,
/*--- MPI Parallelization ---*/
- SendReceive_Solution(x, geometry, config);
+ InitiateComms(x, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(x, geometry, config, SOLUTION_MATRIX);
/*--- Update the residual (r^k+1 = b - A*x^k+1) with the new solution ---*/
@@ -1523,17 +1809,23 @@ unsigned long CSysMatrix::Jacobi_Smoother(const CSysVector & b, CSysVector & x,
mat_vec(x, A_x);
r -= A_x;
- /*--- Check if solution has converged, else output the relative
- residual if necessary. ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm_r = r.norm();
- if (norm_r < tol*norm0) break;
- if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ /*--- Check if solution has converged, else output the relative
+ residual if necessary. ---*/
+
+ norm_r = r.norm();
+ if (norm_r < tol*norm0) break;
+ if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
+ cout << " " << i << " " << norm_r/norm0 << endl;
+
+ }
}
- if ((monitoring) && (rank == MASTER_NODE)) {
+ if ((monitoring) && (rank == MASTER_NODE) && (config->GetComm_Level() == COMM_FULL)) {
cout << "# Jacobi smoother final (true) residual:" << endl;
cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
}
@@ -1685,7 +1977,8 @@ void CSysMatrix::ComputeILUPreconditioner(const CSysVector & vec, CSysVector & p
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
}
@@ -1695,6 +1988,8 @@ unsigned long CSysMatrix::ILU_Smoother(const CSysVector & b, CSysVector & x, CMa
su2double *Block_ij, omega = 1.0;
long iPoint, jPoint;
unsigned short iVar;
+ su2double norm_r = 0.0, norm0 = 0.0;
+ int i = 0;
/*--- Check the number of iterations requested ---*/
@@ -1716,25 +2011,31 @@ unsigned long CSysMatrix::ILU_Smoother(const CSysVector & b, CSysVector & x, CMa
mat_vec(x, A_x);
r -= A_x;
- su2double norm_r = r.norm();
- su2double norm0 = b.norm();
- if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
- if (rank == MASTER_NODE) cout << "CSysMatrix::ILU_Smoother(): system solved by initial guess." << endl;
- return 0;
- }
- /*--- Set the norm to the initial initial residual value ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm0 = norm_r;
-
- /*--- Output header information including initial residual ---*/
-
- int i = 0;
- if ((monitoring) && (rank == MASTER_NODE)) {
- cout << "\n# " << "ILU Smoother" << " residual history" << endl;
- cout << "# Residual tolerance target = " << tol << endl;
- cout << "# Initial residual norm = " << norm_r << endl;
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ norm_r = r.norm();
+ norm0 = b.norm();
+ if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
+ if (rank == MASTER_NODE) cout << "CSysMatrix::ILU_Smoother(): system solved by initial guess." << endl;
+ return 0;
+ }
+
+ /*--- Set the norm to the initial residual value ---*/
+
+ norm0 = norm_r;
+
+ /*--- Output header information including initial residual ---*/
+
+ if ((monitoring) && (rank == MASTER_NODE)) {
+ cout << "\n# " << "ILU Smoother" << " residual history" << endl;
+ cout << "# Residual tolerance target = " << tol << endl;
+ cout << "# Initial residual norm = " << norm_r << endl;
+ cout << " " << i << " " << norm_r/norm0 << endl;
+ }
+
}
/*--- Loop over all smoothing iterations ---*/
@@ -1806,7 +2107,8 @@ unsigned long CSysMatrix::ILU_Smoother(const CSysVector & b, CSysVector & x, CMa
/*--- MPI Parallelization ---*/
- SendReceive_Solution(x, geometry, config);
+ InitiateComms(x, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(x, geometry, config, SOLUTION_MATRIX);
/*--- Update the residual (r^k+1 = b - A*x^k+1) with the new solution ---*/
@@ -1814,17 +2116,23 @@ unsigned long CSysMatrix::ILU_Smoother(const CSysVector & b, CSysVector & x, CMa
mat_vec(x, A_x);
r -= A_x;
- /*--- Check if solution has converged, else output the relative
- residual if necessary. ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm_r = r.norm();
- if (norm_r < tol*norm0) break;
- if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ /*--- Check if solution has converged, else output the relative
+ residual if necessary. ---*/
+
+ norm_r = r.norm();
+ if (norm_r < tol*norm0) break;
+ if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
+ cout << " " << i << " " << norm_r/norm0 << endl;
+
+ }
}
- if ((monitoring) && (rank == MASTER_NODE)) {
+ if ((monitoring) && (rank == MASTER_NODE) && (config->GetComm_Level() == COMM_FULL)) {
cout << "# ILU smoother final (true) residual:" << endl;
cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
}
@@ -1849,7 +2157,8 @@ void CSysMatrix::ComputeLU_SGSPreconditioner(const CSysVector & vec, CSysVector
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
/*--- Second part of the symmetric iteration: (D+U).x_(1) = D.x* ---*/
@@ -1867,7 +2176,8 @@ void CSysMatrix::ComputeLU_SGSPreconditioner(const CSysVector & vec, CSysVector
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
}
@@ -1875,6 +2185,8 @@ unsigned long CSysMatrix::LU_SGS_Smoother(const CSysVector & b, CSysVector & x,
unsigned long iPoint, iVar;
su2double omega = 1.0;
+ su2double norm_r = 0.0, norm0 = 0.0;
+ int i = 0;
/*--- Check the number of iterations requested ---*/
@@ -1897,25 +2209,31 @@ unsigned long CSysMatrix::LU_SGS_Smoother(const CSysVector & b, CSysVector & x,
mat_vec(x, A_x);
r -= A_x;
- su2double norm_r = r.norm();
- su2double norm0 = b.norm();
- if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
- if (rank == MASTER_NODE) cout << "CSysMatrix::LU_SGS_Smoother(): system solved by initial guess." << endl;
- return 0;
- }
- /*--- Set the norm to the initial initial residual value ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm0 = norm_r;
-
- /*--- Output header information including initial residual ---*/
-
- int i = 0;
- if ((monitoring) && (rank == MASTER_NODE)) {
- cout << "\n# " << "LU_SGS Smoother" << " residual history" << endl;
- cout << "# Residual tolerance target = " << tol << endl;
- cout << "# Initial residual norm = " << norm_r << endl;
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ norm_r = r.norm();
+ norm0 = b.norm();
+ if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
+ if (rank == MASTER_NODE) cout << "CSysMatrix::LU_SGS_Smoother(): system solved by initial guess." << endl;
+ return 0;
+ }
+
+ /*--- Set the norm to the initial initial residual value ---*/
+
+ norm0 = norm_r;
+
+ /*--- Output header information including initial residual ---*/
+
+ if ((monitoring) && (rank == MASTER_NODE)) {
+ cout << "\n# " << "LU_SGS Smoother" << " residual history" << endl;
+ cout << "# Residual tolerance target = " << tol << endl;
+ cout << "# Initial residual norm = " << norm_r << endl;
+ cout << " " << i << " " << norm_r/norm0 << endl;
+ }
+
}
/*--- Loop over all smoothing iterations ---*/
@@ -1935,7 +2253,8 @@ unsigned long CSysMatrix::LU_SGS_Smoother(const CSysVector & b, CSysVector & x,
/*--- MPI Parallelization ---*/
- SendReceive_Solution(xStar, geometry, config);
+ InitiateComms(xStar, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(xStar, geometry, config, SOLUTION_MATRIX);
/*--- Second part of the symmetric iteration: (D+U).x_(1) = D.x* ---*/
@@ -1959,7 +2278,8 @@ unsigned long CSysMatrix::LU_SGS_Smoother(const CSysVector & b, CSysVector & x,
/*--- MPI Parallelization ---*/
- SendReceive_Solution(x, geometry, config);
+ InitiateComms(x, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(x, geometry, config, SOLUTION_MATRIX);
/*--- Update the residual (r^k+1 = b - A*x^k+1) with the new solution ---*/
@@ -1968,17 +2288,23 @@ unsigned long CSysMatrix::LU_SGS_Smoother(const CSysVector & b, CSysVector & x,
r -= A_x;
xStar = x;
- /*--- Check if solution has converged, else output the relative
- residual if necessary. ---*/
+ /*--- Only compute the residuals in full communication mode. ---*/
- norm_r = r.norm();
- if (norm_r < tol*norm0) break;
- if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
- cout << " " << i << " " << norm_r/norm0 << endl;
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ /*--- Check if solution has converged, else output the relative
+ residual if necessary. ---*/
+
+ norm_r = r.norm();
+ if (norm_r < tol*norm0) break;
+ if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 5 == 0))
+ cout << " " << i << " " << norm_r/norm0 << endl;
+
+ }
}
- if ((monitoring) && (rank == MASTER_NODE)) {
+ if ((monitoring) && (rank == MASTER_NODE) && (config->GetComm_Level() == COMM_FULL)) {
cout << "# LU_SGS smoother final (true) residual:" << endl;
cout << "# Iteration = " << i << ": |res|/|res0| = " << norm_r/norm0 << ".\n" << endl;
}
@@ -2203,7 +2529,8 @@ void CSysMatrix::ComputeLineletPreconditioner(const CSysVector & vec, CSysVector
/*--- MPI Parallelization ---*/
- SendReceive_Solution(prod, geometry, config);
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
/*--- Solve linelet using a Thomas' algorithm ---*/
@@ -2272,8 +2599,9 @@ void CSysMatrix::ComputeLineletPreconditioner(const CSysVector & vec, CSysVector
}
/*--- MPI Parallelization ---*/
-
- SendReceive_Solution(prod, geometry, config);
+
+ InitiateComms(prod, geometry, config, SOLUTION_MATRIX);
+ CompleteComms(prod, geometry, config, SOLUTION_MATRIX);
}
else {
diff --git a/SU2_CFD/include/solver_structure.hpp b/SU2_CFD/include/solver_structure.hpp
index 3be00e84ef44..d248918f746e 100644
--- a/SU2_CFD/include/solver_structure.hpp
+++ b/SU2_CFD/include/solver_structure.hpp
@@ -123,7 +123,8 @@ class CSolver {
**Jacobian_ij, /*!< \brief Auxiliary matrices for storing point to point Jacobians. */
**Jacobian_ji, /*!< \brief Auxiliary matrices for storing point to point Jacobians. */
**Jacobian_jj; /*!< \brief Auxiliary matrices for storing point to point Jacobians. */
-
+ su2double *iPoint_UndLapl, /*!< \brief Auxiliary variable for the undivided Laplacians. */
+ *jPoint_UndLapl; /*!< \brief Auxiliary variable for the undivided Laplacians. */
su2double **Smatrix, /*!< \brief Auxiliary structure for computing gradients by least-squares */
**Cvector; /*!< \brief Auxiliary structure for computing gradients by least-squares */
@@ -140,6 +141,9 @@ class CSolver {
unsigned long *nCol_InletFile; /*!< \brief Auxiliary structure for holding the number of columns for a particular marker in an inlet profile file. */
passivedouble *Inlet_Data; /*!< \brief Auxiliary structure for holding the data values from an inlet profile file. */
+ bool rotate_periodic; /*!< \brief Flag that controls whether the periodic solution needs to be rotated for the solver. */
+ bool implicit_periodic; /*!< \brief Flag that controls whether the implicit system should be treated by the periodic BC comms. */
+
public:
CSysVector LinSysSol; /*!< \brief vector to store iterative solution of implicit linear system. */
@@ -166,6 +170,50 @@ class CSolver {
*/
virtual ~CSolver(void);
+ /*!
+ * \brief Routine to load a solver quantity into the data structures for MPI point-to-point communication and to launch non-blocking sends and recvs.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ */
+ void InitiateComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType);
+
+ /*!
+ * \brief Routine to complete the set of non-blocking communications launched by InitiateComms() and unpacking of the data in the solver class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] commType - Enumerated type for the quantity to be unpacked.
+ */
+ void CompleteComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType);
+
+ /*!
+ * \brief Routine to load a solver quantity into the data structures for MPI periodic communication and to launch non-blocking sends and recvs.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] val_periodic_index - Index for the periodic marker to be treated (first in a pair).
+ * \param[in] commType - Enumerated type for the quantity to be communicated.
+ */
+ void InitiatePeriodicComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short val_periodic_index,
+ unsigned short commType);
+
+ /*!
+ * \brief Routine to complete the set of non-blocking periodic communications launched by InitiatePeriodicComms() and unpacking of the data in the solver class.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] config - Definition of the particular problem.
+ * \param[in] val_periodic_index - Index for the periodic marker to be treated (first in a pair).
+ * \param[in] commType - Enumerated type for the quantity to be unpacked.
+ */
+ void CompletePeriodicComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short val_periodic_index,
+ unsigned short commType);
+
/*!
* \brief Set number of linear solver iterations.
* \param[in] val_iterlinsolver - Number of linear iterations.
@@ -505,11 +553,11 @@ class CSolver {
su2double* GetPoint_Max_Coord_BGS(unsigned short val_var);
/*!
- * \brief Set Value of the residual if there is a grid movement.
+ * \brief Set Value of the residual due to the Geometric Conservation Law (GCL) for steady rotating frame problems.
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
*/
- void SetGrid_Movement_Residual(CGeometry *geometry, CConfig *config);
+ void SetRotatingFrame_GCL(CGeometry *geometry, CConfig *config);
/*!
* \brief Impose the send-receive boundary condition.
@@ -961,6 +1009,16 @@ class CSolver {
*/
virtual void BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short val_marker);
+ /*!
+ * \brief A virtual member.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] solver_container - Container vector with all the solutions.
+ * \param[in] numerics - Description of the numerical method.
+ * \param[in] config - Definition of the particular problem.
+ */
+ virtual void BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config);
+
/*!
* \brief Impose the interface state across sliding meshes.
* \param[in] geometry - Geometrical definition of the problem.
@@ -2814,7 +2872,7 @@ class CSolver {
* \return Value of the pressure coefficient.
*/
virtual su2double GetDonorPrimVar(unsigned short val_marker, unsigned long val_vertex, unsigned short val_var);
-
+
/*!
* \brief A virtual member.
* \param[in] val_marker - Surface marker where the coefficient is computed.
@@ -4368,6 +4426,18 @@ class CSolver {
*/
virtual void SetDES_LengthScale(CSolver** solver, CGeometry *geometry, CConfig *config);
+ /*!
+ * \brief Routine that sets the flag controlling implicit treatment for periodic BCs.
+ * \param[in] val_implicit_periodic - Flag controlling implicit treatment for periodic BCs.
+ */
+ void SetImplicitPeriodic(bool val_implicit_periodic);
+
+ /*!
+ * \brief Routine that sets the flag controlling solution rotation for periodic BCs.
+ * \param[in] val_implicit_periodic - Flag controlling solution rotation for periodic BCs.
+ */
+ void SetRotatePeriodic(bool val_rotate_periodic);
+
};
/*!
@@ -4701,8 +4771,6 @@ class CEulerSolver : public CSolver {
*Surface_HF_Visc, /*!< \brief Total (integrated) heat flux for each monitored surface. */
*Surface_MaxHF_Visc; /*!< \brief Maximum heat flux for each monitored surface. */
- su2double *iPoint_UndLapl, /*!< \brief Auxiliary variable for the undivided Laplacians. */
- *jPoint_UndLapl; /*!< \brief Auxiliary variable for the undivided Laplacians. */
su2double *SecondaryVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */
*SecondaryVar_j; /*!< \brief Auxiliary vector for storing the solution at point j. */
su2double *PrimVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */
@@ -5216,6 +5284,16 @@ class CEulerSolver : public CSolver {
void BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics,
CConfig *config, unsigned short val_marker);
+ /*!
+ * \brief Impose a periodic boundary condition by summing contributions from the complete control volume.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] solver_container - Container vector with all the solutions.
+ * \param[in] numerics - Description of the numerical method.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config);
+
/*!
* \brief Impose the dirichlet boundary condition using the residual.
* \param[in] geometry - Geometrical definition of the problem.
@@ -7012,7 +7090,7 @@ class CIncEulerSolver : public CSolver {
su2double **Inlet_Ptotal, /*!< \brief Value of the Total P. */
**Inlet_Ttotal, /*!< \brief Value of the Total T. */
***Inlet_FlowDir; /*!< \brief Value of the Flow Direction. */
-
+
su2double
AllBound_CD_Inv, /*!< \brief Total drag coefficient (inviscid contribution) for all the boundaries. */
AllBound_CL_Inv, /*!< \brief Total lift coefficient (inviscid contribution) for all the boundaries. */
@@ -7093,8 +7171,6 @@ class CIncEulerSolver : public CSolver {
*Surface_HF_Visc, /*!< \brief Total (integrated) heat flux for each monitored surface. */
*Surface_MaxHF_Visc; /*!< \brief Maximum heat flux for each monitored surface. */
- su2double *iPoint_UndLapl, /*!< \brief Auxiliary variable for the undivided Laplacians. */
- *jPoint_UndLapl; /*!< \brief Auxiliary variable for the undivided Laplacians. */
su2double *SecondaryVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */
*SecondaryVar_j; /*!< \brief Auxiliary vector for storing the solution at point j. */
su2double *PrimVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */
@@ -7494,6 +7570,16 @@ class CIncEulerSolver : public CSolver {
*/
void BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config);
+ /*!
+ * \brief Impose a periodic boundary condition by summing contributions from the complete control volume.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] solver_container - Container vector with all the solutions.
+ * \param[in] numerics - Description of the numerical method.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config);
+
/*!
* \brief compare to values.
* \param[in] a - value 1.
@@ -8179,7 +8265,7 @@ class CIncEulerSolver : public CSolver {
* \return Value of the pressure coefficient.
*/
su2double *GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex);
-
+
/*!
* \brief Set the total residual adding the term that comes from the Dual Time Strategy.
* \param[in] geometry - Geometrical definition of the problem.
@@ -9462,7 +9548,16 @@ class CTurbSolver : public CSolver {
void BC_Giles(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config,
unsigned short val_marker);
-
+ /*!
+ * \brief Impose a periodic boundary condition by summing contributions from the complete control volume.
+ * \param[in] geometry - Geometrical definition of the problem.
+ * \param[in] solver_container - Container vector with all the solutions.
+ * \param[in] numerics - Description of the numerical method.
+ * \param[in] config - Definition of the particular problem.
+ */
+ void BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config);
+
/*!
* \brief Update the solution using an implicit solver.
* \param[in] geometry - Geometrical definition of the problem.
@@ -10293,8 +10388,6 @@ class CAdjEulerSolver : public CSolver {
su2double Total_Sens_Press; /*!< \brief Total farfield sensitivity to pressure. */
su2double Total_Sens_Temp; /*!< \brief Total farfield sensitivity to temperature. */
su2double Total_Sens_BPress; /*!< \brief Total sensitivity to back pressure. */
- su2double *iPoint_UndLapl, /*!< \brief Auxiliary variable for the undivided Laplacians. */
- *jPoint_UndLapl; /*!< \brief Auxiliary variable for the undivided Laplacians. */
bool space_centered; /*!< \brief True if space centered scheeme used. */
su2double **Jacobian_Axisymmetric; /*!< \brief Storage for axisymmetric Jacobian. */
unsigned long nMarker; /*!< \brief Total number of markers using the grid information. */
diff --git a/SU2_CFD/include/solver_structure.inl b/SU2_CFD/include/solver_structure.inl
index e47acded591f..1ffaa512f7dd 100644
--- a/SU2_CFD/include/solver_structure.inl
+++ b/SU2_CFD/include/solver_structure.inl
@@ -731,6 +731,9 @@ inline void CSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver
inline void CSolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics,
CConfig *config, unsigned short val_marker) { }
+inline void CSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config) { }
+
inline void CSolver::BC_ActDisk_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics,
CConfig *config, unsigned short val_marker) { }
@@ -1185,6 +1188,10 @@ inline void CSolver::SetConjugateHeatVariable(unsigned short val_marker, unsigne
inline su2double CSolver::GetConjugateHeatVariable(unsigned short val_marker, unsigned long val_vertex, unsigned short pos_var) { return 0.0; }
+inline void CSolver::SetImplicitPeriodic(bool val_implicit_periodic) { implicit_periodic = val_implicit_periodic; }
+
+inline void CSolver::SetRotatePeriodic(bool val_rotate_periodic) { rotate_periodic = val_rotate_periodic; }
+
inline su2double CEulerSolver::GetDensity_Inf(void) { return Density_Inf; }
inline su2double CEulerSolver::GetModVelocity_Inf(void) {
diff --git a/SU2_CFD/include/variable_structure.hpp b/SU2_CFD/include/variable_structure.hpp
index 2a0324dfc6e2..84cea6d6c865 100644
--- a/SU2_CFD/include/variable_structure.hpp
+++ b/SU2_CFD/include/variable_structure.hpp
@@ -65,6 +65,7 @@ class CVariable {
su2double *Solution_time_n, /*!< \brief Solution of the problem at time n for dual-time stepping technique. */
*Solution_time_n1; /*!< \brief Solution of the problem at time n-1 for dual-time stepping technique. */
su2double **Gradient; /*!< \brief Gradient of the solution of the problem. */
+ su2double **Rmatrix; /*!< \brief Geometry-based matrix for weighted least squares gradient calculations. */
su2double *Limiter; /*!< \brief Limiter of the solution of the problem. */
su2double *Solution_Max; /*!< \brief Max solution for limiter computation. */
su2double *Solution_Min; /*!< \brief Min solution for limiter computation. */
@@ -542,6 +543,35 @@ class CVariable {
*/
su2double GetGradient(unsigned short val_var, unsigned short val_dim);
+ /*!
+ * \brief Set the value of an entry in the Rmatrix for least squares gradient calculations.
+ * \param[in] val_iDim - Index of the dimension.
+ * \param[in] val_jDim - Index of the dimension.
+ * \param[in] val_value - Value of the Rmatrix entry.
+ */
+ void SetRmatrix(unsigned short val_iDim, unsigned short val_jDim, su2double val_value);
+
+ /*!
+ * \brief Set to zero the Rmatrix for least squares gradient calculations.
+ */
+ void SetRmatrixZero(void);
+
+ /*!
+ * \brief Add val_value to the Rmatrix for least squares gradient calculations.
+ * \param[in] val_iDim - Index of the dimension.
+ * \param[in] val_jDim - Index of the dimension.
+ * \param[in] val_value - Value to add to the Rmatrix entry.
+ */
+ void AddRmatrix(unsigned short val_iDim, unsigned short val_jDim, su2double val_value);
+
+ /*!
+ * \brief Get the value of the Rmatrix entry for least squares gradient calculations.
+ * \param[in] val_iDim - Index of the dimension.
+ * \param[in] val_jDim - Index of the dimension.
+ * \return Value of the Rmatrix entry.
+ */
+ su2double GetRmatrix(unsigned short val_iDim, unsigned short val_jDim);
+
/*!
* \brief Set the value of the limiter.
* \param[in] val_var - Index of the variable.
diff --git a/SU2_CFD/include/variable_structure.inl b/SU2_CFD/include/variable_structure.inl
index b5bac935c2cf..4d4460932aa8 100644
--- a/SU2_CFD/include/variable_structure.inl
+++ b/SU2_CFD/include/variable_structure.inl
@@ -153,6 +153,12 @@ inline void CVariable::SubtractAuxVarGradient(unsigned short val_dim, su2double
inline su2double CVariable::GetGradient(unsigned short val_var, unsigned short val_dim) { return Gradient[val_var][val_dim]; }
+inline void CVariable::SetRmatrix(unsigned short val_iDim, unsigned short val_jDim, su2double val_value) { Rmatrix[val_iDim][val_jDim] = val_value; }
+
+inline void CVariable::AddRmatrix(unsigned short val_iDim, unsigned short val_jDim, su2double val_value) { Rmatrix[val_iDim][val_jDim] += val_value; }
+
+inline su2double CVariable::GetRmatrix(unsigned short val_iDim, unsigned short val_jDim) { return Rmatrix[val_iDim][val_jDim]; }
+
inline su2double CVariable::GetLimiter(unsigned short val_var) { return Limiter[val_var]; }
inline su2double CVariable::GetSolution_Max(unsigned short val_var) { return Solution_Max[val_var]; }
diff --git a/SU2_CFD/src/SU2_CFD.cpp b/SU2_CFD/src/SU2_CFD.cpp
index 7715d68a7136..15b330a49a73 100644
--- a/SU2_CFD/src/SU2_CFD.cpp
+++ b/SU2_CFD/src/SU2_CFD.cpp
@@ -96,7 +96,6 @@ int main(int argc, char *argv[]) {
nDim = CConfig::GetnDim(config->GetMesh_FileName(), config->GetMesh_FileFormat());
fsi = config->GetFSI_Simulation();
turbo = config->GetBoolTurbomachinery();
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
zone_specific = config->GetBoolZoneSpecific();
/*--- First, given the basic information about the number of zones and the
diff --git a/SU2_CFD/src/driver_direct_multizone.cpp b/SU2_CFD/src/driver_direct_multizone.cpp
index b0b186c58004..1c2b621b2ac4 100644
--- a/SU2_CFD/src/driver_direct_multizone.cpp
+++ b/SU2_CFD/src/driver_direct_multizone.cpp
@@ -139,6 +139,7 @@ CMultizoneDriver::~CMultizoneDriver(void) {
delete [] init_res;
delete [] residual;
delete [] residual_rel;
+ delete [] nVarZone;
delete [] prefixed_motion;
diff --git a/SU2_CFD/src/driver_structure.cpp b/SU2_CFD/src/driver_structure.cpp
index c44ef2350bed..5dd3d3890721 100644
--- a/SU2_CFD/src/driver_structure.cpp
+++ b/SU2_CFD/src/driver_structure.cpp
@@ -186,7 +186,30 @@ CDriver::CDriver(char* confFile,
geometry_container[iZone][iInst][iMesh]->MatchInterface(config_container[iZone]);
geometry_container[iZone][iInst][iMesh]->MatchActuator_Disk(config_container[iZone]);
}
-
+
+ /*--- If we have any periodic markers in this calculation, we must
+ match the periodic points found on both sides of the periodic BC.
+ Note that the current implementation requires a 1-to-1 matching of
+ periodic points on the pair of periodic faces after the translation
+ or rotation is taken into account. ---*/
+
+ if ((config_container[iZone]->GetnMarker_Periodic() != 0) && !fem_solver) {
+ for (iMesh = 0; iMesh <= config_container[iZone]->GetnMGLevels(); iMesh++) {
+
+ /*--- Note that we loop over pairs of periodic markers individually
+ so that repeated nodes on adjacent periodic faces are properly
+ accounted for in multiple places. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config_container[iZone]->GetnMarker_Periodic()/2; iPeriodic++) {
+ geometry_container[iZone][iInst][iMesh]->MatchPeriodic(config_container[iZone], iPeriodic);
+ }
+
+ /*--- Initialize the communication framework for the periodic BCs. ---*/
+ geometry_container[iZone][iInst][iMesh]->PreprocessPeriodicComms(geometry_container[iZone][iInst][iMesh], config_container[iZone]);
+
+ }
+ }
+
}
}
@@ -576,9 +599,9 @@ void CDriver::Postprocessing() {
}
delete [] ConvHist_file[iZone];
}
- delete [] ConvHist_file;
}
+ delete [] ConvHist_file;
if (rank == MASTER_NODE)
cout << endl <<"------------------------- Solver Postprocessing -------------------------" << endl;
@@ -624,10 +647,13 @@ void CDriver::Postprocessing() {
}
delete [] iteration_container;
if (rank == MASTER_NODE) cout << "Deleted CIteration container." << endl;
-
+
if (interpolator_container != NULL) {
for (iZone = 0; iZone < nZone; iZone++) {
- if (interpolator_container[iZone] != NULL){
+ if (interpolator_container[iZone] != NULL) {
+ for (unsigned short jZone = 0; jZone < nZone; jZone++)
+ if (interpolator_container[iZone][jZone] != NULL)
+ delete interpolator_container[iZone][jZone];
delete [] interpolator_container[iZone];
}
}
@@ -785,7 +811,7 @@ void CDriver::Input_Preprocessing(SU2_Comm MPICommunicator, bool val_periodic) {
/*--- Initialize the configuration of the driver ---*/
- driver_config = new CConfig(config_file_name, SU2_CFD, ZONE_0, nZone, nDim, VERB_NONE);
+ driver_config = new CConfig(config_file_name, SU2_CFD, ZONE_0, nZone, nDim, false);
/*--- Loop over all zones to initialize the various classes. In most
cases, nZone is equal to one. This represents the solution of a partial
@@ -799,10 +825,10 @@ void CDriver::Input_Preprocessing(SU2_Comm MPICommunicator, bool val_periodic) {
if (driver_config->GetKind_Solver() == MULTIZONE){
strcpy(zone_file_name, driver_config->GetConfigFilename(iZone).c_str());
- config_container[iZone] = new CConfig(zone_file_name, SU2_CFD, iZone, nZone, nDim, VERB_HIGH);
+ config_container[iZone] = new CConfig(zone_file_name, SU2_CFD, iZone, nZone, nDim, true);
}
else{
- config_container[iZone] = new CConfig(config_file_name, SU2_CFD, iZone, nZone, nDim, VERB_HIGH);
+ config_container[iZone] = new CConfig(config_file_name, SU2_CFD, iZone, nZone, nDim, true);
}
/*--- Set the MPI communicator ---*/
@@ -883,15 +909,10 @@ void CDriver::Input_Preprocessing(SU2_Comm MPICommunicator, bool val_periodic) {
}
else {
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
+
+ geometry_container[iZone][iInst][MESH_0] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- if (val_periodic) {
- geometry_container[iZone][iInst][MESH_0] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone][iInst][MESH_0] = new CPhysicalGeometry(geometry_aux, config_container[iZone], val_periodic);
- }
}
/*--- Deallocate the memory of geometry_aux and solver_aux ---*/
@@ -913,7 +934,7 @@ void CDriver::Input_Preprocessing(SU2_Comm MPICommunicator, bool val_periodic) {
void CDriver::Geometrical_Preprocessing() {
- unsigned short iMGlevel;
+ unsigned short iZone, iInst, iMGlevel;
unsigned short requestedMGlevels = config_container[ZONE_0]->GetnMGLevels();
unsigned long iPoint;
bool fea = false;
@@ -971,11 +992,6 @@ void CDriver::Geometrical_Preprocessing() {
geometry_container[iZone][iInst][MESH_0]->SetControlVolume(config_container[iZone], ALLOCATE);
geometry_container[iZone][iInst][MESH_0]->SetBoundControlVolume(config_container[iZone], ALLOCATE);
- /*--- Compute the max length. ---*/
-
- if ((rank == MASTER_NODE) && (!fea)) cout << "Finding max control volume width." << endl;
- geometry_container[iZone][iInst][MESH_0]->SetMaxLength(config_container[iZone]);
-
/*--- Visualize a dual control volume if requested ---*/
if ((config_container[iZone]->GetVisualize_CV() >= 0) &&
@@ -1040,10 +1056,6 @@ void CDriver::Geometrical_Preprocessing() {
geometry_container[iZone][iInst][iMGlevel]->SetBoundControlVolume(config_container[iZone], geometry_container[iZone][iInst][iMGlevel-1], ALLOCATE);
geometry_container[iZone][iInst][iMGlevel]->SetCoord(geometry_container[iZone][iInst][iMGlevel-1]);
- /*--- Compute the max length. ---*/
-
- geometry_container[iZone][iInst][iMGlevel]->SetMaxLength(config_container[iZone]);
-
/*--- Find closest neighbor to a surface point ---*/
geometry_container[iZone][iInst][iMGlevel]->FindNormal_Neighbor(config_container[iZone]);
@@ -1088,6 +1100,36 @@ void CDriver::Geometrical_Preprocessing() {
}
}
+ /*--- Create the data structure for MPI point-to-point communications. ---*/
+
+ for (iZone = 0; iZone < nZone; iZone++) {
+ for (iInst = 0; iInst < nInst[iZone]; iInst++) {
+ for (iMGlevel = 0; iMGlevel <= config_container[iZone]->GetnMGLevels(); iMGlevel++)
+ geometry_container[iZone][iInst][iMGlevel]->PreprocessP2PComms(geometry_container[iZone][iInst][iMGlevel], config_container[iZone]);
+ }
+ }
+
+ /*--- Perform a few preprocessing routines and communications. ---*/
+
+ for (iZone = 0; iZone < nZone; iZone++) {
+ for (iInst = 0; iInst < nInst[iZone]; iInst++) {
+ for (iMGlevel = 0; iMGlevel <= config_container[iZone]->GetnMGLevels(); iMGlevel++) {
+
+ /*--- Compute the max length. ---*/
+
+ if ((rank == MASTER_NODE) && (!fea) && (iMGlevel == MESH_0)) cout << "Finding max control volume width." << endl;
+ geometry_container[iZone][iInst][iMGlevel]->SetMaxLength(config_container[iZone]);
+
+ /*--- Communicate the number of neighbors. This is needed for
+ some centered schemes and for multigrid in parallel. ---*/
+
+ if ((rank == MASTER_NODE) && (size > SINGLE_NODE) && (!fea) && (iMGlevel == MESH_0)) cout << "Communicating number of neighbors." << endl;
+ geometry_container[iZone][iInst][iMGlevel]->InitiateComms(geometry_container[iZone][iInst][iMGlevel], config_container[iZone], NEIGHBORS);
+ geometry_container[iZone][iInst][iMGlevel]->CompleteComms(geometry_container[iZone][iInst][iMGlevel], config_container[iZone], NEIGHBORS);
+ }
+ }
+ }
+
}
void CDriver::Geometrical_Preprocessing_DGFEM() {
@@ -3843,10 +3885,6 @@ void CDriver::PreprocessExtIter(unsigned long ExtIter) {
}
}
-#ifdef HAVE_MPI
- SU2_MPI::Barrier(MPI_COMM_WORLD);
-#endif
-
}
bool CDriver::Monitor(unsigned long ExtIter) {
@@ -5690,9 +5728,9 @@ void CFSIDriver::Predict_Displacements(unsigned short donorZone, unsigned short
solver_container[donorZone][INST_0]);
/*--- For parallel simulations we need to communicate the predicted solution before updating the fluid mesh ---*/
-
- solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->Set_MPI_Solution_Pred(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone]);
+ solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone], SOLUTION_PRED);
+ solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone], SOLUTION_PRED);
}
@@ -5732,8 +5770,10 @@ void CFSIDriver::Relaxation_Displacements(unsigned short donorZone, unsigned sho
solver_container[donorZone][INST_0]);
/*----------------- Communicate the predicted solution and the old one ------------------*/
- solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->Set_MPI_Solution_Pred_Old(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone]);
+ solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone], SOLUTION_PRED_OLD);
+ solver_container[donorZone][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[donorZone][INST_0][MESH_0], config_container[donorZone], SOLUTION_PRED_OLD);
+
}
@@ -6604,13 +6644,17 @@ void CDiscAdjFSIDriver::Fluid_Iteration_Direct(unsigned short ZONE_FLOW, unsigne
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]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_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]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW]);
+
+ 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);
+
}
/*-----------------------------------------------------------------*/
@@ -6628,7 +6672,8 @@ void CDiscAdjFSIDriver::Fluid_Iteration_Direct(unsigned short ZONE_FLOW, unsigne
/*--------------------- Set MPI Solution --------------------------*/
/*-----------------------------------------------------------------*/
- solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_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);
}
@@ -6641,17 +6686,22 @@ void CDiscAdjFSIDriver::Structural_Iteration_Direct(unsigned short ZONE_FLOW, un
/*---------- Set Dependencies on Geometry and Flow ----------------*/
/*-----------------------------------------------------------------*/
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->Set_MPI_Solution(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT]);
+ 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]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_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]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_0], config_container[ZONE_FLOW]);
+
+ 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);
+
}
/*-----------------------------------------------------------------*/
@@ -6672,8 +6722,8 @@ void CDiscAdjFSIDriver::Structural_Iteration_Direct(unsigned short ZONE_FLOW, un
/*--------------------- Set MPI Solution --------------------------*/
/*-----------------------------------------------------------------*/
- solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->Set_MPI_Solution(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT]);
-
+ 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);
}
@@ -6688,11 +6738,13 @@ void CDiscAdjFSIDriver::Mesh_Deformation_Direct(unsigned short ZONE_FLOW, unsign
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]->Set_MPI_Solution(geometry_container[ZONE_FLOW][INST_0][MESH_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]->Set_MPI_Solution(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT]);
+ 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 ----------------------*/
@@ -6711,8 +6763,9 @@ void CDiscAdjFSIDriver::Mesh_Deformation_Direct(unsigned short ZONE_FLOW, unsign
config_container, ZONE_FLOW, INST_0, IntIter, 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]->Set_MPI_Solution(geometry_container[ZONE_STRUCT][INST_0][MESH_0], config_container[ZONE_STRUCT]);
+ 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);
}
diff --git a/SU2_CFD/src/integration_structure.cpp b/SU2_CFD/src/integration_structure.cpp
index dcba21877e4b..541e846c5fdf 100644
--- a/SU2_CFD/src/integration_structure.cpp
+++ b/SU2_CFD/src/integration_structure.cpp
@@ -107,7 +107,6 @@ void CIntegration::Space_Integration(CGeometry *geometry,
solver_container[MainSolver]->PreprocessBC_Giles(geometry, config, numerics[CONV_BOUND_TERM], OUTFLOW);
}
-
/*--- Weak boundary conditions ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
@@ -180,7 +179,7 @@ void CIntegration::Space_Integration(CGeometry *geometry,
break;
}
}
-
+
/*--- Strong boundary conditions (Navier-Stokes and Dirichlet type BCs) ---*/
for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
@@ -208,7 +207,17 @@ void CIntegration::Space_Integration(CGeometry *geometry,
solver_container[MainSolver]->BC_HeatFlux_Wall(geometry, solver_container, numerics[CONV_BOUND_TERM], numerics[VISC_BOUND_TERM], config, iMarker);
}
break;
- }
+ }
+
+ /*--- Complete residuals for periodic boundary conditions. We loop over
+ the periodic BCs in matching pairs so that, in the event that there are
+ adjacent periodic markers, the repeated points will have their residuals
+ accumulated corectly during the communications. ---*/
+
+ if (config->GetnMarker_Periodic() > 0) {
+ solver_container[MainSolver]->BC_Periodic(geometry, solver_container, numerics[CONV_BOUND_TERM], config);
+ }
+
}
void CIntegration::Space_Integration_FEM(CGeometry *geometry,
@@ -441,7 +450,9 @@ void CIntegration::Time_Integration_FEM(CGeometry *geometry, CSolver **solver_co
}
/*--- Perform the MPI communication of the solution ---*/
- solver_container[MainSolver]->Set_MPI_Solution(geometry, config);
+
+ solver_container[MainSolver]->InitiateComms(geometry, config, SOLUTION_FEA);
+ solver_container[MainSolver]->CompleteComms(geometry, config, SOLUTION_FEA);
}
diff --git a/SU2_CFD/src/integration_time.cpp b/SU2_CFD/src/integration_time.cpp
index 31247cbe3dce..60315f1237fd 100644
--- a/SU2_CFD/src/integration_time.cpp
+++ b/SU2_CFD/src/integration_time.cpp
@@ -324,8 +324,9 @@ void CMultiGridIntegration::GetProlongated_Correction(unsigned short RunTime_EqS
/*--- MPI the set solution old ---*/
- sol_coarse->Set_MPI_Solution_Old(geo_coarse, config);
-
+ sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_OLD);
+ sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_OLD);
+
for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) {
for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) {
Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren);
@@ -391,12 +392,14 @@ void CMultiGridIntegration::SmoothProlongated_Correction (unsigned short RunTime
/*--- Copy boundary values ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
- for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
+ for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
Residual_Old = solver->node[iPoint]->GetResidual_Old();
solver->LinSysRes.SetBlock(iPoint, Residual_Old);
}
+ }
}
delete [] Residual;
@@ -458,12 +461,14 @@ void CMultiGridIntegration::Smooth_Solution(unsigned short RunTime_EqSystem, CSo
/*--- Copy boundary values ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
- for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
+ for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
Solution_Old = solver->node[iPoint]->GetResidual_Old();
solver->node[iPoint]->SetSolution(Solution_Old);
}
+ }
}
delete [] Solution;
@@ -494,7 +499,9 @@ void CMultiGridIntegration::SetProlongated_Correction(CSolver *sol_fine, CGeomet
}
/*--- MPI the new interpolated solution ---*/
- sol_fine->Set_MPI_Solution(geo_fine, config);
+
+ sol_fine->InitiateComms(geo_fine, config, SOLUTION);
+ sol_fine->CompleteComms(geo_fine, config, SOLUTION);
delete [] Solution;
}
@@ -668,7 +675,8 @@ void CMultiGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSyst
/*--- MPI the new interpolated solution ---*/
- sol_coarse->Set_MPI_Solution(geo_coarse, config);
+ sol_coarse->InitiateComms(geo_coarse, config, SOLUTION);
+ sol_coarse->CompleteComms(geo_coarse, config, SOLUTION);
delete [] Solution;
@@ -879,7 +887,8 @@ void CSingleGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSys
/*--- MPI the new interpolated solution ---*/
- sol_coarse->Set_MPI_Solution(geo_coarse, config);
+ sol_coarse->InitiateComms(geo_coarse, config, SOLUTION);
+ sol_coarse->CompleteComms(geo_coarse, config, SOLUTION);
delete [] Solution;
@@ -925,8 +934,9 @@ void CSingleGridIntegration::SetRestricted_EddyVisc(unsigned short RunTime_EqSys
}
/*--- MPI the new interpolated solution (this also includes the eddy viscosity) ---*/
-
- sol_coarse->Set_MPI_Solution(geo_coarse, config);
+
+ sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_EDDY);
+ sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_EDDY);
}
diff --git a/SU2_CFD/src/iteration_structure.cpp b/SU2_CFD/src/iteration_structure.cpp
index 6f4d014bdb9e..252693389e83 100644
--- a/SU2_CFD/src/iteration_structure.cpp
+++ b/SU2_CFD/src/iteration_structure.cpp
@@ -1762,8 +1762,9 @@ void CFEAIteration::Predictor(COutput *output,
solver_container[val_iZone][val_iInst]);
/*--- For parallel simulations we need to communicate the predicted solution before updating the fluid mesh ---*/
-
- solver_container[val_iZone][val_iInst][MESH_0][FEA_SOL]->Set_MPI_Solution_Pred(geometry_container[val_iZone][val_iInst][MESH_0], config_container[val_iZone]);
+
+ solver_container[val_iZone][val_iInst][MESH_0][FEA_SOL]->InitiateComms(geometry_container[val_iZone][val_iInst][MESH_0], config_container[val_iZone], SOLUTION_PRED);
+ solver_container[val_iZone][val_iInst][MESH_0][FEA_SOL]->CompleteComms(geometry_container[val_iZone][val_iInst][MESH_0], config_container[val_iZone], SOLUTION_PRED);
}
void CFEAIteration::Relaxation(COutput *output,
@@ -1793,8 +1794,9 @@ void CFEAIteration::Relaxation(COutput *output,
solver_container[val_iZone][INST_0]);
/*----------------- Communicate the predicted solution and the old one ------------------*/
- solver_container[val_iZone][INST_0][MESH_0][FEA_SOL]->Set_MPI_Solution_Pred_Old(geometry_container[val_iZone][INST_0][MESH_0], config_container[val_iZone]);
+ solver_container[val_iZone][INST_0][MESH_0][FEA_SOL]->InitiateComms(geometry_container[val_iZone][INST_0][MESH_0], config_container[val_iZone], SOLUTION_PRED_OLD);
+ solver_container[val_iZone][INST_0][MESH_0][FEA_SOL]->CompleteComms(geometry_container[val_iZone][INST_0][MESH_0], config_container[val_iZone], SOLUTION_PRED_OLD);
}
@@ -2472,19 +2474,23 @@ void CDiscAdjFluidIteration::SetDependencies(CSolver *****solver_container, CGeo
/*--- Compute coupling between flow and turbulent equations ---*/
- solver_container[iZone][iInst][MESH_0][FLOW_SOL]->Set_MPI_Solution(geometry_container[iZone][iInst][MESH_0], config_container[iZone]);
+ solver_container[iZone][iInst][MESH_0][FLOW_SOL]->InitiateComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+ solver_container[iZone][iInst][MESH_0][FLOW_SOL]->CompleteComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
if (turbulent && !frozen_visc){
solver_container[iZone][iInst][MESH_0][FLOW_SOL]->Preprocessing(geometry_container[iZone][iInst][MESH_0],solver_container[iZone][iInst][MESH_0], config_container[iZone], MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
solver_container[iZone][iInst][MESH_0][TURB_SOL]->Postprocessing(geometry_container[iZone][iInst][MESH_0],solver_container[iZone][iInst][MESH_0], config_container[iZone], MESH_0);
- solver_container[iZone][iInst][MESH_0][TURB_SOL]->Set_MPI_Solution(geometry_container[iZone][iInst][MESH_0], config_container[iZone]);
+ solver_container[iZone][iInst][MESH_0][TURB_SOL]->InitiateComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+ solver_container[iZone][iInst][MESH_0][TURB_SOL]->CompleteComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+
}
if (heat){
solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Set_Heatflux_Areas(geometry_container[iZone][iInst][MESH_0], config_container[iZone]);
solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Preprocessing(geometry_container[iZone][iInst][MESH_0],solver_container[iZone][iInst][MESH_0], config_container[iZone], MESH_0, NO_RK_ITER, RUNTIME_HEAT_SYS, true);
solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Postprocessing(geometry_container[iZone][iInst][MESH_0],solver_container[iZone][iInst][MESH_0], config_container[iZone], MESH_0);
- solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Set_MPI_Solution(geometry_container[iZone][iInst][MESH_0], config_container[iZone]);
+ solver_container[iZone][iInst][MESH_0][HEAT_SOL]->InitiateComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+ solver_container[iZone][iInst][MESH_0][HEAT_SOL]->CompleteComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
}
}
@@ -3509,8 +3515,10 @@ void CDiscAdjHeatIteration::SetDependencies(CSolver *****solver_container,
solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Preprocessing(geometry_container[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0],
config_container[iZone], MESH_0, NO_RK_ITER, RUNTIME_HEAT_SYS, true);
solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Postprocessing(geometry_container[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0],
- config_container[iZone], MESH_0);
- solver_container[iZone][iInst][MESH_0][HEAT_SOL]->Set_MPI_Solution(geometry_container[iZone][iInst][MESH_0], config_container[iZone]);
+ config_container[iZone], MESH_0);
+ solver_container[iZone][iInst][MESH_0][HEAT_SOL]->InitiateComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+ solver_container[iZone][iInst][MESH_0][HEAT_SOL]->CompleteComms(geometry_container[iZone][iInst][MESH_0], config_container[iZone], SOLUTION);
+
}
void CDiscAdjHeatIteration::RegisterOutput(CSolver *****solver_container,
diff --git a/SU2_CFD/src/output_paraview.cpp b/SU2_CFD/src/output_paraview.cpp
index ab4c41e1b054..c2fea61e3b56 100644
--- a/SU2_CFD/src/output_paraview.cpp
+++ b/SU2_CFD/src/output_paraview.cpp
@@ -2863,7 +2863,6 @@ void COutput::WriteParaViewBinary_Parallel(CConfig *config,
fclose(fhw);
-
#else
/*--- Parallel binary output using MPI I/O. ---*/
diff --git a/SU2_CFD/src/output_structure.cpp b/SU2_CFD/src/output_structure.cpp
index a93a8f43b502..209dadcc6146 100644
--- a/SU2_CFD/src/output_structure.cpp
+++ b/SU2_CFD/src/output_structure.cpp
@@ -12645,6 +12645,7 @@ void COutput::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver *
bool transition = (config->GetKind_Trans_Model() == BC);
bool grid_movement = (config->GetGrid_Movement());
+ bool rotating_frame = config->GetRotating_Frame();
bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
int *Local_Halo = NULL;
@@ -12876,6 +12877,27 @@ void COutput::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver *
/*--- New variables get registered here before the end of the loop. ---*/
+ if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
+ nVar_Par += 2;
+ Variable_Names.push_back("Vorticity_x");
+ Variable_Names.push_back("Vorticity_y");
+ if (geometry->GetnDim() == 3) {
+ nVar_Par += 1; Variable_Names.push_back("Vorticity_z");
+ }
+
+ nVar_Par +=1;
+ Variable_Names.push_back("Q_Criterion");
+ }
+
+ if (rotating_frame) {
+ nVar_Par += 2;
+ Variable_Names.push_back("Relative_Velocity_x");
+ Variable_Names.push_back("Relative_Velocity_y");
+ if (geometry->GetnDim() == 3) {
+ nVar_Par += 1; Variable_Names.push_back("Relative_Velocity_z");
+ }
+ }
+
}
/*--- Auxiliary vectors for variables defined on surfaces only. ---*/
@@ -13108,6 +13130,51 @@ void COutput::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver *
/*--- New variables can be loaded to the Local_Data structure here,
assuming they were registered above correctly. ---*/
+
+ if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[0]; iVar++;
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[1]; iVar++;
+ if (geometry->GetnDim() == 3) {
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[2];
+ iVar++;
+ }
+
+ su2double Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ su2double Omega[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ su2double Strain[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (unsigned short jDim = 0 ; jDim < nDim; jDim++) {
+ Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->node[iPoint]->GetGradient_Primitive(iDim+1, jDim);
+ Strain[iDim][jDim] = 0.5*(Grad_Vel[iDim][jDim] + Grad_Vel[jDim][iDim]);
+ Omega[iDim][jDim] = 0.5*(Grad_Vel[iDim][jDim] - Grad_Vel[jDim][iDim]);
+ }
+ }
+
+ su2double OmegaMag = 0.0, StrainMag = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (unsigned short jDim = 0 ; jDim < nDim; jDim++) {
+ StrainMag += Strain[iDim][jDim]*Strain[iDim][jDim];
+ OmegaMag += Omega[iDim][jDim]*Omega[iDim][jDim];
+ }
+ }
+ StrainMag = sqrt(StrainMag);
+ OmegaMag = sqrt(OmegaMag);
+ su2double Q = 0.5*(OmegaMag - StrainMag);
+ Local_Data[jPoint][iVar] = Q; iVar++;
+ }
+
+ /*--- For rotating frame problems, compute the relative velocity. ---*/
+
+ if (rotating_frame) {
+ Grid_Vel = geometry->node[iPoint]->GetGridVel();
+ su2double *Solution = solver[FLOW_SOL]->node[iPoint]->GetSolution();
+ Local_Data[jPoint][iVar] = Solution[1]/Solution[0] - Grid_Vel[0]; iVar++;
+ Local_Data[jPoint][iVar] = Solution[2]/Solution[0] - Grid_Vel[1]; iVar++;
+ if (geometry->GetnDim() == 3) {
+ Local_Data[jPoint][iVar] = Solution[3]/Solution[0] - Grid_Vel[2];
+ iVar++;
+ }
+ }
}
@@ -13397,6 +13464,16 @@ void COutput::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolve
Variable_Names.push_back("Thermal_Conductivity");
}
+ if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
+ nVar_Par += 2;
+ Variable_Names.push_back("Vorticity_x");
+ Variable_Names.push_back("Vorticity_y");
+ nVar_Par += 1; Variable_Names.push_back("Vorticity_z");
+
+ nVar_Par +=1;
+ Variable_Names.push_back("Q_Criterion");
+ }
+
/*--- New variables get registered here before the end of the loop. ---*/
}
@@ -13636,6 +13713,37 @@ void COutput::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolve
/*--- New variables can be loaded to the Local_Data structure here,
assuming they were registered above correctly. ---*/
+ if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
+
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[0]; iVar++;
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[1]; iVar++;
+ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetVorticity()[2]; iVar++;
+
+ su2double Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ su2double Omega[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ su2double Strain[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}};
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (unsigned short jDim = 0 ; jDim < nDim; jDim++) {
+ Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->node[iPoint]->GetGradient_Primitive(iDim+1, jDim);
+ Strain[iDim][jDim] = 0.5*(Grad_Vel[iDim][jDim] + Grad_Vel[jDim][iDim]);
+ Omega[iDim][jDim] = 0.5*(Grad_Vel[iDim][jDim] - Grad_Vel[jDim][iDim]);
+ }
+ }
+
+ su2double OmegaMag = 0.0, StrainMag = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (unsigned short jDim = 0 ; jDim < nDim; jDim++) {
+ StrainMag += Strain[iDim][jDim]*Strain[iDim][jDim];
+ OmegaMag += Omega[iDim][jDim]*Omega[iDim][jDim];
+ }
+ }
+ StrainMag = sqrt(StrainMag); OmegaMag = sqrt(OmegaMag);
+
+ su2double Q = 0.5*(OmegaMag - StrainMag);
+ Local_Data[jPoint][iVar] = Q; iVar++;
+
+ }
+
}
/*--- Increment the point counter, as there may have been halos we
@@ -17912,7 +18020,7 @@ void COutput::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry,
for (iVar = 0; iVar < nVar_Par; iVar++) {
disp = var_buf_size*sizeof(int) + iVar*CGNS_STRING_SIZE*sizeof(char);
- strcpy(str_buf, Variable_Names[iVar].c_str());
+ strncpy(str_buf, Variable_Names[iVar].c_str(), CGNS_STRING_SIZE);
MPI_File_write_at(fhw, disp, str_buf, CGNS_STRING_SIZE, MPI_CHAR, MPI_STATUS_IGNORE);
file_size += (su2double)CGNS_STRING_SIZE*sizeof(char);
}
@@ -18951,21 +19059,21 @@ void COutput::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry,
}
#ifdef HAVE_MPI
-
- SU2_MPI::Allreduce(Surface_MassFlow_Local, Surface_MassFlow_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Mach_Local, Surface_Mach_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Temperature_Local, Surface_Temperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Density_Local, Surface_Density_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Enthalpy_Local, Surface_Enthalpy_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_NormalVelocity_Local, Surface_NormalVelocity_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_StreamVelocity2_Local, Surface_StreamVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_TransvVelocity2_Local, Surface_TransvVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Pressure_Local, Surface_Pressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_TotalTemperature_Local, Surface_TotalTemperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_TotalPressure_Local, Surface_TotalPressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_Area_Local, Surface_Area_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(Surface_MassFlow_Abs_Local, Surface_MassFlow_Abs_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(Surface_MassFlow_Local, Surface_MassFlow_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Mach_Local, Surface_Mach_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Temperature_Local, Surface_Temperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Density_Local, Surface_Density_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Enthalpy_Local, Surface_Enthalpy_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_NormalVelocity_Local, Surface_NormalVelocity_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_StreamVelocity2_Local, Surface_StreamVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_TransvVelocity2_Local, Surface_TransvVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Pressure_Local, Surface_Pressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_TotalTemperature_Local, Surface_TotalTemperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_TotalPressure_Local, Surface_TotalPressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_Area_Local, Surface_Area_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(Surface_MassFlow_Abs_Local, Surface_MassFlow_Abs_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
#else
for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
diff --git a/SU2_CFD/src/output_tecplot.cpp b/SU2_CFD/src/output_tecplot.cpp
index 295d1e778795..2544a0d27ebe 100644
--- a/SU2_CFD/src/output_tecplot.cpp
+++ b/SU2_CFD/src/output_tecplot.cpp
@@ -1338,7 +1338,7 @@ void COutput::WriteTecplotBinary_Parallel(CConfig *config, CGeometry *geometry,
}
else {
values_to_write.resize(rank_num_points);
- for(unsigned long i = 0; i < rank_num_points; ++i)
+ for(unsigned long i = 0; i < (unsigned long)rank_num_points; ++i)
values_to_write[i] = SU2_TYPE::GetValue(Parallel_Data[iVar][i]);
err = tecZoneVarWriteDoubleValues(file_handle, zone, iVar + 1, 0, rank_num_points, &values_to_write[0]);
}
@@ -1378,14 +1378,22 @@ void COutput::WriteTecplotBinary_Parallel(CConfig *config, CGeometry *geometry,
unsigned short iVar;
+ vector var_data;
+ size_t var_data_size = nVar_Par * (surf_sol ? nSurf_Poin_Par : nParallel_Poin);
+ var_data.reserve(var_data_size);
+
if (surf_sol) {
for (iVar = 0; err == 0 && iVar < nVar_Par; iVar++) {
- err = tecZoneVarWriteDoubleValues(file_handle, zone, iVar + 1, 0, nSurf_Poin_Par, Parallel_Surf_Data[iVar]);
+ for(unsigned long i = 0; i < nSurf_Poin_Par; ++i)
+ var_data.push_back(SU2_TYPE::GetValue(Parallel_Surf_Data[iVar][i]));
+ err = tecZoneVarWriteDoubleValues(file_handle, zone, iVar + 1, 0, nSurf_Poin_Par, &var_data[iVar * nSurf_Poin_Par]);
if (err) cout << rank << ": Error outputting Tecplot variable value." << endl;
}
} else {
for (iVar = 0; err == 0 && iVar < nVar_Par; iVar++) {
- err = tecZoneVarWriteDoubleValues(file_handle, zone, iVar + 1, 0, nParallel_Poin, Parallel_Data[iVar]);
+ for(unsigned long i = 0; i < nParallel_Poin; ++i)
+ var_data.push_back(SU2_TYPE::GetValue(Parallel_Data[iVar][i]));
+ err = tecZoneVarWriteDoubleValues(file_handle, zone, iVar + 1, 0, nParallel_Poin, &var_data[iVar * nParallel_Poin]);
if (err) cout << rank << ": Error outputting Tecplot variable value." << endl;
}
}
diff --git a/SU2_CFD/src/solver_adjoint_discrete.cpp b/SU2_CFD/src/solver_adjoint_discrete.cpp
index 5b6298346685..ca7c728b79b4 100644
--- a/SU2_CFD/src/solver_adjoint_discrete.cpp
+++ b/SU2_CFD/src/solver_adjoint_discrete.cpp
@@ -685,8 +685,6 @@ void CDiscAdjSolver::ExtractAdjoint_CrossTerm(CGeometry *geometry, CConfig *conf
}
-// Set_MPI_CrossTerm(geometry, config);
-
}
void CDiscAdjSolver::ExtractAdjoint_CrossTerm_Geometry(CGeometry *geometry, CConfig *config) {
diff --git a/SU2_CFD/src/solver_adjoint_mean.cpp b/SU2_CFD/src/solver_adjoint_mean.cpp
index 2f0120ac890b..88d176c1a4f1 100644
--- a/SU2_CFD/src/solver_adjoint_mean.cpp
+++ b/SU2_CFD/src/solver_adjoint_mean.cpp
@@ -377,8 +377,10 @@ CAdjEulerSolver::CAdjEulerSolver(CGeometry *geometry, CConfig *config, unsigned
}
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
}
CAdjEulerSolver::~CAdjEulerSolver(void) {
@@ -391,8 +393,6 @@ CAdjEulerSolver::~CAdjEulerSolver(void) {
if (Sens_Press != NULL) delete [] Sens_Press;
if (Sens_Temp != NULL) delete [] Sens_Temp;
if (Sens_BPress != NULL) delete [] Sens_BPress;
- if (iPoint_UndLapl != NULL) delete [] iPoint_UndLapl;
- if (jPoint_UndLapl != NULL) delete [] jPoint_UndLapl;
if (FlowPrimVar_i != NULL) delete [] FlowPrimVar_i;
if (FlowPrimVar_j != NULL) delete [] FlowPrimVar_j;
@@ -2572,7 +2572,8 @@ void CAdjEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solve
solver_container[iMesh][ADJFLOW_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver_container[iMesh][ADJFLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver_container[iMesh][ADJFLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver_container[iMesh][ADJFLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
}
delete [] Solution;
}
@@ -2665,7 +2666,7 @@ void CAdjEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contai
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
@@ -3009,8 +3010,7 @@ void CAdjEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *confi
if (config->GetMarker_All_KindBC(iMarker) != SEND_RECEIVE &&
config->GetMarker_All_KindBC(iMarker) != INTERFACE_BOUNDARY &&
- config->GetMarker_All_KindBC(iMarker) != NEARFIELD_BOUNDARY &&
- config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY) {
+ config->GetMarker_All_KindBC(iMarker) != NEARFIELD_BOUNDARY) {
for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
@@ -3042,7 +3042,8 @@ void CAdjEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *confi
/*--- MPI parallelization ---*/
- Set_MPI_Undivided_Laplacian(geometry, config);
+ InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN);
+ CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN);
}
@@ -3074,7 +3075,9 @@ void CAdjEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfi
}
/*--- MPI parallelization ---*/
- Set_MPI_Sensor(geometry, config);
+
+ InitiateComms(geometry, config, SENSOR);
+ CompleteComms(geometry, config, SENSOR);
}
@@ -3109,7 +3112,9 @@ void CAdjEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver
}
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -3144,7 +3149,9 @@ void CAdjEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
}
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -3226,7 +3233,8 @@ void CAdjEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -5789,8 +5797,9 @@ void CAdjEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- Communicate the loaded solution on the fine grid before we transfer
it down to the coarse levels. We also call the preprocessing routine
on the fine level in order to have all necessary quantities updated. ---*/
-
- solver[MESH_0][ADJFLOW_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
+
+ solver[MESH_0][ADJFLOW_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
+ solver[MESH_0][ADJFLOW_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
solver[MESH_0][ADJFLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
@@ -5809,7 +5818,8 @@ void CAdjEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
}
solver[iMesh][ADJFLOW_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver[iMesh][ADJFLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver[iMesh][ADJFLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver[iMesh][ADJFLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
solver[iMesh][ADJFLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
}
@@ -6103,7 +6113,9 @@ CAdjNSSolver::CAdjNSSolver(CGeometry *geometry, CConfig *config, unsigned short
}
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
}
@@ -6194,7 +6206,7 @@ void CAdjNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
diff --git a/SU2_CFD/src/solver_adjoint_turbulent.cpp b/SU2_CFD/src/solver_adjoint_turbulent.cpp
index 238d83843dc7..c3a4917507c9 100644
--- a/SU2_CFD/src/solver_adjoint_turbulent.cpp
+++ b/SU2_CFD/src/solver_adjoint_turbulent.cpp
@@ -200,7 +200,9 @@ CAdjTurbSolver::CAdjTurbSolver(CGeometry *geometry, CConfig *config, unsigned sh
}
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
}
@@ -867,8 +869,9 @@ void CAdjTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solv
}
/*--- MPI solution ---*/
-
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
diff --git a/SU2_CFD/src/solver_direct_elasticity.cpp b/SU2_CFD/src/solver_direct_elasticity.cpp
index 1c4aa0846686..18fa9b51fa48 100644
--- a/SU2_CFD/src/solver_direct_elasticity.cpp
+++ b/SU2_CFD/src/solver_direct_elasticity.cpp
@@ -466,11 +466,15 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() {
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
/*--- If dynamic, we also need to communicate the old solution ---*/
- if(dynamic) Set_MPI_Solution_Old(geometry, config);
+ if(dynamic) {
+ InitiateComms(geometry, config, SOLUTION_FEA_OLD);
+ CompleteComms(geometry, config, SOLUTION_FEA_OLD);
+ }
}
@@ -2738,8 +2742,9 @@ void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container,
Conv_Check[2] = dotProd(LinSysSol, LinSysRes); // Position for the energy tolerance
/*--- MPI solution ---*/
-
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
}
else {
/*--- If the problem is linear, the only check we do is the RMS of the displacements ---*/
@@ -2766,8 +2771,9 @@ void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container,
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
+
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -2844,8 +2850,9 @@ void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container,
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
+
} else {
/*--- If the problem is linear, the only check we do is the RMS of the displacements ---*/
@@ -2872,9 +2879,10 @@ void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container,
}
/*--- MPI solution ---*/
-
- Set_MPI_Solution(geometry, config);
-
+
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
+
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -3875,8 +3883,8 @@ void CFEASolver::ImplicitNewmark_Update(CGeometry *geometry, CSolver **solver_co
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
}
@@ -3938,7 +3946,8 @@ void CFEASolver::ImplicitNewmark_Relaxation(CGeometry *geometry, CSolver **solve
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
/*--- After the solution has been communicated, set the 'old' predicted solution as the solution ---*/
/*--- Loop over n points (as we have already communicated everything ---*/
@@ -4135,7 +4144,8 @@ void CFEASolver::GeneralizedAlpha_UpdateDisp(CGeometry *geometry, CSolver **solv
/*--- Perform the MPI communication of the solution, displacements only ---*/
- Set_MPI_Solution_DispOnly(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_DISPONLY);
+ CompleteComms(geometry, config, SOLUTION_DISPONLY);
}
@@ -4204,7 +4214,8 @@ void CFEASolver::GeneralizedAlpha_UpdateSolution(CGeometry *geometry, CSolver **
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_FEA);
+ CompleteComms(geometry, config, SOLUTION_FEA);
}
@@ -4491,7 +4502,8 @@ void CFEASolver::Update_StructSolution(CGeometry **fea_geometry,
/*--- Perform the MPI communication of the solution, displacements only ---*/
- Set_MPI_Solution_DispOnly(fea_geometry[MESH_0], fea_config);
+ InitiateComms(fea_geometry[MESH_0], fea_config, SOLUTION_DISPONLY);
+ CompleteComms(fea_geometry[MESH_0], fea_config, SOLUTION_DISPONLY);
}
@@ -5053,12 +5065,20 @@ void CFEASolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *c
}
/*--- MPI. If dynamic, we also need to communicate the old solution ---*/
-
- solver[MESH_0][FEA_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
- if (dynamic) solver[MESH_0][FEA_SOL]->Set_MPI_Solution_Old(geometry[MESH_0], config);
+
+ solver[MESH_0][FEA_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION_FEA);
+ solver[MESH_0][FEA_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION_FEA);
+
+ if (dynamic) {
+ solver[MESH_0][FEA_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION_FEA_OLD);
+ solver[MESH_0][FEA_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION_FEA_OLD);
+ }
if (fluid_structure && !dynamic){
- solver[MESH_0][FEA_SOL]->Set_MPI_Solution_Pred(geometry[MESH_0], config);
- solver[MESH_0][FEA_SOL]->Set_MPI_Solution_Pred_Old(geometry[MESH_0], config);
+ solver[MESH_0][FEA_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION_PRED);
+ solver[MESH_0][FEA_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION_PRED);
+
+ solver[MESH_0][FEA_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION_PRED_OLD);
+ solver[MESH_0][FEA_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION_PRED_OLD);
}
delete [] Sol;
diff --git a/SU2_CFD/src/solver_direct_heat.cpp b/SU2_CFD/src/solver_direct_heat.cpp
index dccc7ffdf102..5a3d2b1cbe5d 100644
--- a/SU2_CFD/src/solver_direct_heat.cpp
+++ b/SU2_CFD/src/solver_direct_heat.cpp
@@ -241,7 +241,10 @@ CHeatSolverFVM::CHeatSolverFVM(CGeometry *geometry, CConfig *config, unsigned sh
node[iPoint] = new CHeatFVMVariable(Temperature_Solid_Freestream_ND, nDim, nVar, config);
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
}
CHeatSolverFVM::~CHeatSolverFVM(void) { }
@@ -399,8 +402,10 @@ void CHeatSolverFVM::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfi
it down to the coarse levels. We alo call the preprocessing routine
on the fine level in order to have all necessary quantities updated,
especially if this is a turbulent simulation (eddy viscosity). ---*/
-
- solver[MESH_0][HEAT_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
+
+ solver[MESH_0][HEAT_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
+ solver[MESH_0][HEAT_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
+
solver[MESH_0][HEAT_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_HEAT_SYS, false);
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
@@ -419,7 +424,8 @@ void CHeatSolverFVM::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfi
}
solver[iMesh][HEAT_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver[iMesh][HEAT_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver[iMesh][HEAT_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver[iMesh][HEAT_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
solver[iMesh][HEAT_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_HEAT_SYS, false);
}
@@ -479,9 +485,10 @@ void CHeatSolverFVM::SetUndivided_Laplacian(CGeometry *geometry, CConfig *config
}
/*--- MPI parallelization ---*/
-
- Set_MPI_Undivided_Laplacian(geometry, config);
-
+
+ InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN);
+ CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN);
+
delete [] Diff;
}
@@ -1566,7 +1573,7 @@ void CHeatSolverFVM::SetTime_Step(CGeometry *geometry, CSolver **solver_containe
}
/*--- Compute the max and the min dt (in parallel) ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
su2double rbuf_time, sbuf_time;
sbuf_time = Min_Delta_Time;
@@ -1655,8 +1662,9 @@ void CHeatSolverFVM::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solv
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -1749,8 +1757,9 @@ void CHeatSolverFVM::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solv
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -2052,8 +2061,9 @@ void CHeatSolverFVM::SetInitialCondition(CGeometry **geometry, CSolver ***solver
}
}
solver_container[iMesh][HEAT_SOL]->node[iPoint]->SetSolution(Solution);
- }
- solver_container[iMesh][HEAT_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ }
+ solver_container[iMesh][HEAT_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver_container[iMesh][HEAT_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
}
delete [] Solution;
}
diff --git a/SU2_CFD/src/solver_direct_mean.cpp b/SU2_CFD/src/solver_direct_mean.cpp
index 865a49d71b14..f96eaadc91fc 100755
--- a/SU2_CFD/src/solver_direct_mean.cpp
+++ b/SU2_CFD/src/solver_direct_mean.cpp
@@ -90,8 +90,6 @@ CEulerSolver::CEulerSolver(void) : CSolver() {
/*--- Numerical methods array initialization ---*/
- iPoint_UndLapl = NULL;
- jPoint_UndLapl = NULL;
LowMach_Precontioner = NULL;
Primitive = NULL; Primitive_i = NULL; Primitive_j = NULL;
CharacPrimVar = NULL;
@@ -361,7 +359,6 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short
nVar = nDim+2;
nPrimVar = nDim+9; nPrimVarGrad = nDim+4;
nSecondaryVar = 2; nSecondaryVarGrad = 2;
-
/*--- Initialize nVarGrad for deallocation ---*/
@@ -842,7 +839,7 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short
/*--- Warning message about non-physical points ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
#else
@@ -862,10 +859,23 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short
if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true;
else least_squares = false;
-
+
+ /*--- Communicate and store volume and the number of neighbors for
+ any dual CVs that lie on on periodic markers. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ }
+ SetImplicitPeriodic(euler_implicit);
+ if (iMesh == MESH_0) SetRotatePeriodic(true);
+
/*--- Perform the MPI communication of the solution ---*/
-
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
}
@@ -959,9 +969,6 @@ CEulerSolver::~CEulerSolver(void) {
if (Exhaust_Pressure != NULL) delete [] Exhaust_Pressure;
if (Exhaust_Temperature != NULL) delete [] Exhaust_Temperature;
- if (iPoint_UndLapl != NULL) delete [] iPoint_UndLapl;
- if (jPoint_UndLapl != NULL) delete [] jPoint_UndLapl;
-
if (Primitive != NULL) delete [] Primitive;
if (Primitive_i != NULL) delete [] Primitive_i;
if (Primitive_j != NULL) delete [] Primitive_j;
@@ -4172,16 +4179,19 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c
}
/*--- Set the MPI communication ---*/
-
- solver_container[iMesh][FLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
- solver_container[iMesh][FLOW_SOL]->Set_MPI_Solution_Old(geometry[iMesh], config);
+
+ solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
+
+ solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION_OLD);
+ solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION_OLD);
}
}
}
-
+
/*--- Make sure that the solution is well initialized for unsteady
calculations with dual time-stepping (load additional restarts for 2nd-order). ---*/
@@ -4292,6 +4302,7 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container
if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) {
SetPrimitive_Gradient_LS(geometry, config);
}
+
/*--- Limiter computation ---*/
@@ -4322,10 +4333,10 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container
/*--- Initialize the Jacobian matrices ---*/
if (implicit && !disc_adjoint) Jacobian.SetValZero();
-
+
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
@@ -4425,7 +4436,8 @@ void CEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -4454,7 +4466,7 @@ void CEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
if (geometry->node[iPoint]->GetDomain()) {
node[iPoint]->AddMax_Lambda_Inv(Lambda);
}
-
+ }
}
}
@@ -4481,7 +4493,7 @@ void CEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
/*--- Compute the max and the min dt (in parallel) ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
su2double rbuf_time, sbuf_time;
sbuf_time = Min_Delta_Time;
@@ -4848,7 +4860,7 @@ void CEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_contain
/*--- Warning message about non-physical reconstructions ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
#else
@@ -4935,6 +4947,11 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain
if (rotating_frame) {
+ /*--- Include the residual contribution from GCL due to the static
+ mesh movement that is set for rotating frame. ---*/
+
+ SetRotatingFrame_GCL(geometry, config);
+
/*--- Loop over all points ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
@@ -4950,7 +4967,7 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain
/*--- Add the source residual to the total ---*/
LinSysRes.AddBlock(iPoint, Residual);
-
+
/*--- Add the implicit Jacobian contribution ---*/
if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i);
@@ -5134,7 +5151,8 @@ void CEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) {
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -5164,13 +5182,21 @@ void CEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) {
if (geometry->node[iPoint]->GetDomain()) {
node[iPoint]->AddLambda(Lambda);
}
-
+ }
}
}
+ /*--- Correct the eigenvalue values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG);
+ }
+
/*--- MPI parallelization ---*/
- Set_MPI_MaxEigenvalue(geometry, config);
+ InitiateComms(geometry, config, MAX_EIGENVALUE);
+ CompleteComms(geometry, config, MAX_EIGENVALUE);
}
@@ -5224,9 +5250,17 @@ void CEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *config)
}
+ /*--- Correct the Laplacian values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN);
+ }
+
/*--- MPI parallelization ---*/
- Set_MPI_Undivided_Laplacian(geometry, config);
+ InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN);
+ CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN);
delete [] Diff;
@@ -5277,6 +5311,13 @@ void CEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *
}
+ /*--- Correct the sensor values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR);
+ }
+
/*--- Set pressure switch for each point ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++)
@@ -5284,7 +5325,8 @@ void CEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *
/*--- MPI parallelization ---*/
- Set_MPI_Sensor(geometry, config);
+ InitiateComms(geometry, config, SENSOR);
+ CompleteComms(geometry, config, SENSOR);
}
@@ -5357,7 +5399,8 @@ void CEulerSolver::SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config)
}
}
- Set_MPI_Sensor(geometry, config);
+ InitiateComms(geometry, config, SENSOR);
+ CompleteComms(geometry, config, SENSOR);
}
@@ -5647,23 +5690,25 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) {
AllBound_CMerit_Inv = 0.0;
MyAllBound_CNearFieldOF_Inv = AllBound_CNearFieldOF_Inv; AllBound_CNearFieldOF_Inv = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Inv, &AllBound_CD_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Inv, &AllBound_CL_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Inv, &AllBound_CSF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Inv, &AllBound_CMx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Inv, &AllBound_CMy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Inv, &AllBound_CMz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Inv, &AllBound_CoPx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Inv, &AllBound_CoPy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Inv, &AllBound_CoPz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Inv, &AllBound_CFx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Inv, &AllBound_CFy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Inv, &AllBound_CFz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Inv, &AllBound_CT_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Inv, &AllBound_CQ_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CNearFieldOF_Inv, &AllBound_CNearFieldOF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Inv, &AllBound_CD_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Inv, &AllBound_CL_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Inv, &AllBound_CSF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Inv, &AllBound_CMx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Inv, &AllBound_CMy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Inv, &AllBound_CMz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Inv, &AllBound_CoPx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Inv, &AllBound_CoPy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Inv, &AllBound_CoPz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Inv, &AllBound_CFx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Inv, &AllBound_CFy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Inv, &AllBound_CFz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Inv, &AllBound_CT_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Inv, &AllBound_CQ_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CNearFieldOF_Inv, &AllBound_CNearFieldOF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
/*--- Add the forces on the surfaces using all the nodes ---*/
@@ -5702,17 +5747,19 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) {
Surface_CMz_Inv[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Inv, Surface_CL_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Inv, Surface_CD_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Inv, Surface_CSF_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Inv, Surface_CFx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Inv, Surface_CFy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Inv, Surface_CFz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Inv, Surface_CMx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Inv, Surface_CMy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Inv, Surface_CMz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Inv, Surface_CL_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Inv, Surface_CD_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Inv, Surface_CSF_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Inv, Surface_CFx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Inv, Surface_CFy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Inv, Surface_CFz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Inv, Surface_CMx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Inv, Surface_CMy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Inv, Surface_CMz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
delete [] MySurface_CL_Inv; delete [] MySurface_CD_Inv; delete [] MySurface_CSF_Inv;
delete [] MySurface_CEff_Inv; delete [] MySurface_CFx_Inv; delete [] MySurface_CFy_Inv;
@@ -6021,22 +6068,24 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) {
MyAllBound_CT_Mnt = AllBound_CT_Mnt; AllBound_CT_Mnt = 0.0;
MyAllBound_CQ_Mnt = AllBound_CQ_Mnt; AllBound_CQ_Mnt = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Mnt, &AllBound_CD_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Mnt, &AllBound_CL_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Mnt, &AllBound_CSF_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Mnt, &AllBound_CFx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Mnt, &AllBound_CFy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Mnt, &AllBound_CFz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Mnt, &AllBound_CMx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Mnt, &AllBound_CMy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Mnt, &AllBound_CMz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Mnt, &AllBound_CoPx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Mnt, &AllBound_CoPy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Mnt, &AllBound_CoPz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Mnt, &AllBound_CT_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Mnt, &AllBound_CQ_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Mnt = AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Mnt, &AllBound_CD_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Mnt, &AllBound_CL_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Mnt, &AllBound_CSF_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Mnt, &AllBound_CFx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Mnt, &AllBound_CFy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Mnt, &AllBound_CFz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Mnt, &AllBound_CMx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Mnt, &AllBound_CMy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Mnt, &AllBound_CMz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Mnt, &AllBound_CoPx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Mnt, &AllBound_CoPy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Mnt, &AllBound_CoPz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Mnt, &AllBound_CT_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Mnt, &AllBound_CQ_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Mnt = AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS);
+ }
/*--- Add the forces on the surfaces using all the nodes ---*/
@@ -6075,17 +6124,19 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) {
Surface_CMz_Mnt[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Mnt, Surface_CL_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Mnt, Surface_CD_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Mnt, Surface_CSF_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Mnt, Surface_CFx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Mnt, Surface_CFy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Mnt, Surface_CFz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Mnt, Surface_CMx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Mnt, Surface_CMy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Mnt, Surface_CMz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Mnt, Surface_CL_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Mnt, Surface_CD_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Mnt, Surface_CSF_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Mnt, Surface_CFx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Mnt, Surface_CFy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Mnt, Surface_CFz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Mnt, Surface_CMx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Mnt, Surface_CMy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Mnt, Surface_CMz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
delete [] MySurface_CL_Mnt; delete [] MySurface_CD_Mnt; delete [] MySurface_CSF_Mnt;
delete [] MySurface_CEff_Mnt; delete [] MySurface_CFx_Mnt; delete [] MySurface_CFy_Mnt;
@@ -6147,7 +6198,8 @@ void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_co
/*--- Update the solution ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
Delta = node[iPoint]->GetDelta_Time() / Vol;
Res_TruncError = node[iPoint]->GetResTruncError();
@@ -6166,7 +6218,8 @@ void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_co
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -6196,7 +6249,8 @@ void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
Delta = node[iPoint]->GetDelta_Time() / Vol;
Res_TruncError = node[iPoint]->GetResTruncError();
@@ -6227,8 +6281,9 @@ void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
/*--- Compute the root mean square residual ---*/
SetResidual_RMS(geometry, config);
@@ -6250,12 +6305,12 @@ void CEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver
/*--- Update the solution ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
Delta = node[iPoint]->GetDelta_Time() / Vol;
local_Res_TruncError = node[iPoint]->GetResTruncError();
local_Residual = LinSysRes.GetBlock(iPoint);
-
if (!adjoint) {
for (iVar = 0; iVar < nVar; iVar++) {
Res = local_Residual[iVar] + local_Res_TruncError[iVar];
@@ -6269,7 +6324,8 @@ void CEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -6304,7 +6360,8 @@ void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver
/*--- Read the volume ---*/
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
/*--- Modify matrix diagonal to assure diagonal dominance ---*/
@@ -6370,9 +6427,15 @@ void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver
}
}
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ }
+
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -6384,7 +6447,7 @@ void CEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *config
unsigned long iPoint, jPoint, iEdge, iVertex;
unsigned short iDim, iVar, iMarker;
su2double *PrimVar_Vertex, *PrimVar_i, *PrimVar_j, PrimVar_Average,
- Partial_Gradient, Partial_Res, *Normal;
+ Partial_Gradient, Partial_Res, *Normal, Vol;
/*--- Gradient primitive variables compressible (temp, vx, vy, vz, P, rho) ---*/
@@ -6424,8 +6487,8 @@ void CEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *config
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY &&
- config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
if (geometry->node[iPoint]->GetDomain()) {
@@ -6441,33 +6504,52 @@ void CEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *config
}
}
}
+ }
}
+ /*--- Correct the sensor values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_GG);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_GG);
+ }
+
/*--- Update gradient value ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
+
+ /*--- Get the volume, which may include periodic components. ---*/
+
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
+
for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
- Partial_Gradient = node[iPoint]->GetGradient_Primitive(iVar, iDim) / (geometry->node[iPoint]->GetVolume());
+ Partial_Gradient = node[iPoint]->GetGradient_Primitive(iVar, iDim)/Vol;
node[iPoint]->SetGradient_Primitive(iVar, iDim, Partial_Gradient);
}
}
+
}
delete [] PrimVar_Vertex;
delete [] PrimVar_i;
delete [] PrimVar_j;
- Set_MPI_Primitive_Gradient(geometry, config);
+ /*--- Communicate the gradient values via MPI. ---*/
+ InitiateComms(geometry, config, PRIMITIVE_GRADIENT);
+ CompleteComms(geometry, config, PRIMITIVE_GRADIENT);
+
}
void CEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *config) {
unsigned short iVar, iDim, jDim, iNeigh;
unsigned long iPoint, jPoint;
- su2double *PrimVar_i, *PrimVar_j, *Coord_i, *Coord_j, r11, r12, r13, r22, r23, r23_a,
- r23_b, r33, weight, product, z11, z12, z13, z22, z23, z33, detR2;
+ su2double *PrimVar_i, *PrimVar_j, *Coord_i, *Coord_j;
+ su2double r11, r12, r13, r22, r23, r23_a, r23_b, r33, weight;
+ su2double z11, z12, z13, z22, z23, z33, detR2;
bool singular;
/*--- Loop over points of the grid ---*/
@@ -6491,21 +6573,17 @@ void CEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *config
for (iDim = 0; iDim < nDim; iDim++)
Cvector[iVar][iDim] = 0.0;
- r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
- r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+ /*--- Clear Rmatrix, which could eventually be computed once
+ and stored for static meshes, as well as the prim gradient. ---*/
- AD::StartPreacc();
- AD::SetPreaccIn(PrimVar_i, nPrimVarGrad);
- AD::SetPreaccIn(Coord_i, nDim);
+ node[iPoint]->SetRmatrixZero();
+ node[iPoint]->SetGradient_PrimitiveZero(nPrimVarGrad);
for (iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); iNeigh++) {
jPoint = geometry->node[iPoint]->GetPoint(iNeigh);
Coord_j = geometry->node[jPoint]->GetCoord();
PrimVar_j = node[jPoint]->GetPrimitive();
-
- AD::SetPreaccIn(Coord_j, nDim);
- AD::SetPreaccIn(PrimVar_j, nPrimVarGrad);
weight = 0.0;
for (iDim = 0; iDim < nDim; iDim++)
@@ -6514,35 +6592,64 @@ void CEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *config
/*--- Sumations for entries of upper triangular matrix R ---*/
if (weight != 0.0) {
-
- r11 += (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight;
- r12 += (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight;
- r22 += (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight;
-
+
+ node[iPoint]->AddRmatrix(0, 0, (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight);
+ node[iPoint]->AddRmatrix(0, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight);
+ node[iPoint]->AddRmatrix(1, 1, (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight);
+
if (nDim == 3) {
- r13 += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r23_a += (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight;
- r23_b += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r33 += (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight;
+ node[iPoint]->AddRmatrix(0, 2, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(1, 2, (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 2, (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight);
}
/*--- Entries of c:= transpose(A)*b ---*/
- for (iVar = 0; iVar < nPrimVarGrad; iVar++)
- for (iDim = 0; iDim < nDim; iDim++)
- Cvector[iVar][iDim] += (Coord_j[iDim]-Coord_i[iDim])*(PrimVar_j[iVar]-PrimVar_i[iVar])/weight;
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->AddGradient_Primitive(iVar,iDim, (Coord_j[iDim]-Coord_i[iDim])*(PrimVar_j[iVar]-PrimVar_i[iVar])/weight);
+ }
+ }
}
-
}
+ }
+
+ /*--- Correct the gradient values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_LS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_LS);
+ }
+
+ /*--- Second loop over points of the grid to compute final gradient ---*/
+
+ for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
+
+ /*--- Set the value of the singular ---*/
+
+ singular = false;
/*--- Entries of upper triangular matrix R ---*/
+
+ r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
+ r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+
+ r11 = node[iPoint]->GetRmatrix(0,0);
+ r12 = node[iPoint]->GetRmatrix(0,1);
+ r22 = node[iPoint]->GetRmatrix(1,1);
if (r11 >= 0.0) r11 = sqrt(r11); else r11 = 0.0;
if (r11 != 0.0) r12 = r12/r11; else r12 = 0.0;
if (r22-r12*r12 >= 0.0) r22 = sqrt(r22-r12*r12); else r22 = 0.0;
if (nDim == 3) {
+ r13 = node[iPoint]->GetRmatrix(0,2);
+ r23_a = node[iPoint]->GetRmatrix(1,2);
+ r23_b = node[iPoint]->GetRmatrix(2,1);
+ r33 = node[iPoint]->GetRmatrix(2,2);
+
if (r11 != 0.0) r13 = r13/r11; else r13 = 0.0;
if ((r22 != 0.0) && (r11*r22 != 0.0)) r23 = r23_a/r22 - r23_b*r12/(r11*r22); else r23 = 0.0;
if (r33-r23*r23-r13*r13 >= 0.0) r33 = sqrt(r33-r23*r23-r13*r13); else r33 = 0.0;
@@ -6589,20 +6696,25 @@ void CEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *config
/*--- Computation of the gradient: S*c ---*/
for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
- product = 0.0;
+ Cvector[iVar][iDim] = 0.0;
for (jDim = 0; jDim < nDim; jDim++) {
- product += Smatrix[iDim][jDim]*Cvector[iVar][jDim];
+ Cvector[iVar][iDim] += Smatrix[iDim][jDim]*node[iPoint]->GetGradient_Primitive(iVar, jDim);
}
-
- node[iPoint]->SetGradient_Primitive(iVar, iDim, product);
}
}
- AD::SetPreaccOut(node[iPoint]->GetGradient_Primitive(), nPrimVarGrad, nDim);
- AD::EndPreacc();
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->SetGradient_Primitive(iVar, iDim, Cvector[iVar][iDim]);
+ }
+ }
+
}
- Set_MPI_Primitive_Gradient(geometry, config);
+ /*--- Communicate the gradient values via MPI. ---*/
+
+ InitiateComms(geometry, config, PRIMITIVE_GRADIENT);
+ CompleteComms(geometry, config, PRIMITIVE_GRADIENT);
}
@@ -6666,6 +6778,13 @@ void CEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config) {
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_1);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_1);
+ }
+
}
/*--- Barth-Jespersen limiter with Venkatakrishnan modification ---*/
@@ -6776,15 +6895,17 @@ void CEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config) {
}
+ if (config->GetKind_SlopeLimit_Flow() == VENKATAKRISHNAN_WANG) {
#ifdef HAVE_MPI
- SU2_MPI::Allreduce(LocalMinPrimitive, GlobalMinPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(LocalMaxPrimitive, GlobalMaxPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMinPrimitive, GlobalMinPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMaxPrimitive, GlobalMaxPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
#else
- for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
- GlobalMinPrimitive[iVar] = LocalMinPrimitive[iVar];
- GlobalMaxPrimitive[iVar] = LocalMaxPrimitive[iVar];
- }
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ GlobalMinPrimitive[iVar] = LocalMinPrimitive[iVar];
+ GlobalMaxPrimitive[iVar] = LocalMaxPrimitive[iVar];
+ }
#endif
+ }
for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) {
@@ -6862,10 +6983,18 @@ void CEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config) {
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_2);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_2);
+ }
+
/*--- Limiter MPI ---*/
- Set_MPI_Primitive_Limiter(geometry, config);
-
+ InitiateComms(geometry, config, PRIMITIVE_LIMITER);
+ CompleteComms(geometry, config, PRIMITIVE_LIMITER);
+
}
void CEulerSolver::SetPreconditioner(CConfig *config, unsigned long iPoint) {
@@ -9281,11 +9410,11 @@ void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container,
conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config);
/*--- Update residual value ---*/
-
+
LinSysRes.AddBlock(iPoint, Residual);
-
+
/*--- Convective Jacobian contribution for implicit integration ---*/
-
+
if (implicit)
Jacobian.AddBlock(iPoint, iPoint, Jacobian_i);
@@ -9329,9 +9458,9 @@ void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container,
visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config);
LinSysRes.SubtractBlock(iPoint, Residual);
-
+
/*--- Viscous Jacobian contribution for implicit integration ---*/
-
+
if (implicit)
Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i);
@@ -13445,6 +13574,22 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C
}
+void CEulerSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config) {
+
+ /*--- Complete residuals for periodic boundary conditions. We loop over
+ the periodic BCs in matching pairs so that, in the event that there are
+ adjacent periodic markers, the repeated points will have their residuals
+ accumulated correctly during the communications. For implicit calculations,
+ the Jacobians and linear system are also correctly adjusted here. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ }
+
+}
+
void CEulerSolver::BC_Dirichlet(CGeometry *geometry, CSolver **solver_container,
CConfig *config, unsigned short val_marker) { }
@@ -13568,7 +13713,8 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co
/*--- Loop over the boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Get the index for node i plus the boundary face normal ---*/
@@ -13595,6 +13741,7 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co
LinSysRes.AddBlock(iPoint, Residual);
}
+ }
}
/*--- Loop over all nodes (excluding halos) to compute the remainder
@@ -13832,8 +13979,9 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
on the fine level in order to have all necessary quantities updated,
especially if this is a turbulent simulation (eddy viscosity). ---*/
- solver[MESH_0][FLOW_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
- solver[MESH_0][FLOW_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
+ solver[MESH_0][FLOW_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
+ solver[MESH_0][FLOW_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
+
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
@@ -13852,8 +14000,10 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
}
solver[iMesh][FLOW_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver[iMesh][FLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
- solver[iMesh][FLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+
+ solver[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
+
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
}
@@ -13863,9 +14013,12 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
- geometry[MESH_0]->Set_MPI_Coord(config);
- geometry[MESH_0]->Set_MPI_GridVel(config);
-
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
+
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, GRID_VELOCITY);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, GRID_VELOCITY);
+
/*--- Recompute the edges and dual mesh control volumes in the
domain and on the boundaries. ---*/
@@ -13893,8 +14046,9 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
- geometry[MESH_0]->Set_MPI_Coord(config);
-
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
+
/*--- Recompute the edges and dual mesh control volumes in the
domain and on the boundaries. ---*/
@@ -15088,6 +15242,8 @@ CNSSolver::CNSSolver(void) : CEulerSolver() {
SlidingState = NULL;
SlidingStateNodes = NULL;
+ DonorPrimVar = NULL; DonorGlobalIndex = NULL;
+
HeatConjugateVar = NULL;
}
@@ -15233,7 +15389,7 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh)
nMarker = config->GetnMarker_All();
nPoint = geometry->GetnPoint();
nPointDomain = geometry->GetnPointDomain();
-
+
/*--- Store the number of vertices on each marker for deallocation later ---*/
nVertex = new unsigned long[nMarker];
@@ -15391,6 +15547,16 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh)
}
}
+ /*--- Store the value of the characteristic primitive variables index at the boundaries ---*/
+
+ DonorGlobalIndex = new unsigned long* [nMarker];
+ for (iMarker = 0; iMarker < nMarker; iMarker++) {
+ DonorGlobalIndex[iMarker] = new unsigned long [geometry->nVertex[iMarker]];
+ for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
+ DonorGlobalIndex[iMarker][iVertex] = 0;
+ }
+ }
+
/*--- Store the values of the temperature and the heat flux density at the boundaries,
used for coupling with a solid donor cell ---*/
unsigned short nHeatConjugateVar = 4;
@@ -15408,16 +15574,6 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh)
}
}
- /*--- Store the value of the characteristic primitive variables at the boundaries ---*/
-
- DonorGlobalIndex = new unsigned long* [nMarker];
- for (iMarker = 0; iMarker < nMarker; iMarker++) {
- DonorGlobalIndex[iMarker] = new unsigned long [geometry->nVertex[iMarker]];
- for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
- DonorGlobalIndex[iMarker][iVertex] = 0;
- }
- }
-
/*--- Store the value of the Delta P at the Actuator Disk ---*/
ActDisk_DeltaP = new su2double* [nMarker];
@@ -15806,7 +15962,7 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh)
/*--- Warning message about non-physical points ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
#else
@@ -15842,9 +15998,22 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh)
if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true;
else least_squares = false;
+ /*--- Communicate and store volume and the number of neighbors for
+ any dual CVs that lie on on periodic markers. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ }
+ SetImplicitPeriodic(euler_implicit);
+ if (iMesh == MESH_0) SetRotatePeriodic(true);
+
/*--- Perform the MPI communication of the solution ---*/
-
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
}
@@ -15945,7 +16114,7 @@ void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, C
config->GetKind_Upwind_Flow() == SLAU ||
config->GetKind_Upwind_Flow() == SLAU2);
bool wall_functions = config->GetWall_Functions();
-
+
/*--- Update the angle of attack at the far-field for fixed CL calculations (only direct problem). ---*/
if ((fixed_cl) && (!disc_adjoint) && (!cont_adjoint)) { SetFarfield_AoA(geometry, solver_container, config, iMesh, Output); }
@@ -16035,7 +16204,7 @@ void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, C
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
@@ -16180,7 +16349,8 @@ void CNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CC
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -16224,6 +16394,7 @@ void CNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CC
if (geometry->node[iPoint]->GetDomain()) node[iPoint]->AddMax_Lambda_Visc(Lambda);
}
+ }
}
/*--- Each element uses their own speed, steady state simulation ---*/
@@ -16252,7 +16423,7 @@ void CNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CC
/*--- Compute the max and the min dt (in parallel) ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
su2double rbuf_time, sbuf_time;
sbuf_time = Min_Delta_Time;
@@ -16723,25 +16894,27 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
MyAllBound_HF_Visc = AllBound_HF_Visc; AllBound_HF_Visc = 0.0;
MyAllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, MaxNorm); AllBound_MaxHF_Visc = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Visc, &AllBound_CD_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Visc, &AllBound_CL_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Visc, &AllBound_CSF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Visc, &AllBound_CMx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Visc, &AllBound_CMy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Visc, &AllBound_CMz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Visc, &AllBound_CFx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Visc, &AllBound_CFy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Visc, &AllBound_CFz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Visc, &AllBound_CoPx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Visc, &AllBound_CoPy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Visc, &AllBound_CoPz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Visc, &AllBound_CT_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Visc, &AllBound_CQ_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS);
- SU2_MPI::Allreduce(&MyAllBound_HF_Visc, &AllBound_HF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_MaxHF_Visc, &AllBound_MaxHF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Visc, &AllBound_CD_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Visc, &AllBound_CL_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Visc, &AllBound_CSF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Visc, &AllBound_CMx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Visc, &AllBound_CMy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Visc, &AllBound_CMz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Visc, &AllBound_CFx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Visc, &AllBound_CFy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Visc, &AllBound_CFz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Visc, &AllBound_CoPx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Visc, &AllBound_CoPy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Visc, &AllBound_CoPz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Visc, &AllBound_CT_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Visc, &AllBound_CQ_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_HF_Visc, &AllBound_HF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_MaxHF_Visc, &AllBound_MaxHF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm);
+ }
/*--- Add the forces on the surfaces using all the nodes ---*/
@@ -16787,19 +16960,21 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Visc, Surface_CL_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Visc, Surface_CD_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Visc, Surface_CSF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring] / (Surface_CD_Visc[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Visc, Surface_CFx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Visc, Surface_CFy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Visc, Surface_CFz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Visc, Surface_CMx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Visc, Surface_CMy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Visc, Surface_CMz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_HF_Visc, Surface_HF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_MaxHF_Visc, Surface_MaxHF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Visc, Surface_CL_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Visc, Surface_CD_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Visc, Surface_CSF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring] / (Surface_CD_Visc[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Visc, Surface_CFx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Visc, Surface_CFy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Visc, Surface_CFz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Visc, Surface_CMx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Visc, Surface_CMy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Visc, Surface_CMz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_HF_Visc, Surface_HF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_MaxHF_Visc, Surface_MaxHF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
delete [] MySurface_CL_Visc; delete [] MySurface_CD_Visc; delete [] MySurface_CSF_Visc;
delete [] MySurface_CEff_Visc; delete [] MySurface_CFx_Visc; delete [] MySurface_CFy_Visc;
diff --git a/SU2_CFD/src/solver_direct_mean_fem.cpp b/SU2_CFD/src/solver_direct_mean_fem.cpp
index c35075ba4a49..c81c695da974 100644
--- a/SU2_CFD/src/solver_direct_mean_fem.cpp
+++ b/SU2_CFD/src/solver_direct_mean_fem.cpp
@@ -3438,7 +3438,7 @@ void CFEM_DG_EulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_co
}
/*--- Collect the number of non-physical points for this iteration. ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter;
SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
@@ -3957,7 +3957,7 @@ void CFEM_DG_EulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_con
do this for steady calculations if the high verbosity is set, but we
always perform the reduction for unsteady calculations where the CFL
limit is used to set the global time step. ---*/
- if ((config->GetConsole_Output_Verb() == VERB_HIGH) || time_stepping) {
+ if ((config->GetComm_Level() == COMM_FULL) || time_stepping) {
#ifdef HAVE_MPI
su2double rbuf_time = Min_Delta_Time;
SU2_MPI::Allreduce(&rbuf_time, &Min_Delta_Time, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
@@ -7099,7 +7099,7 @@ void CFEM_DG_EulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config)
}
/* Sum up all the data from all ranks. The result will be available on all ranks. */
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
SU2_MPI::Allreduce(locBuf.data(), globBuf.data(), nCommSize, MPI_DOUBLE,
MPI_SUM, MPI_COMM_WORLD);
}
@@ -7208,7 +7208,7 @@ void CFEM_DG_EulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **so
#ifdef HAVE_MPI
/* Parallel mode. Disable the reduce for the residual to avoid overhead if requested. */
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
/*--- The local L2 norms must be added to obtain the
global value. Also check for divergence. ---*/
@@ -7317,7 +7317,7 @@ void CFEM_DG_EulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **
#ifdef HAVE_MPI
/* Parallel mode. Disable the reduce for the residual to avoid overhead if requested. */
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
/*--- The local L2 norms must be added to obtain the
global value. Also check for divergence. ---*/
@@ -9573,7 +9573,7 @@ void CFEM_DG_EulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, C
}
/*--- Warning message about non-physical points ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long nBadDOFsLoc = nBadDOFs;
SU2_MPI::Reduce(&nBadDOFsLoc, &nBadDOFs, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
@@ -10275,7 +10275,7 @@ void CFEM_DG_NSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
}
/* Sum up all the data from all ranks. The result will be available on all ranks. */
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
SU2_MPI::Allreduce(locBuf.data(), globBuf.data(), nCommSize, MPI_DOUBLE,
MPI_SUM, MPI_COMM_WORLD);
}
@@ -10302,7 +10302,7 @@ void CFEM_DG_NSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
/* Determine the maximum heat flux over all ranks. */
su2double localMax = AllBound_MaxHeatFlux_Visc;
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
SU2_MPI::Allreduce(&localMax, &AllBound_MaxHeatFlux_Visc, 1, MPI_DOUBLE,
MPI_MAX, MPI_COMM_WORLD);
}
@@ -10727,7 +10727,7 @@ void CFEM_DG_NSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_contai
do this for steady calculations if the high verbosity is set, but we
always perform the reduction for unsteady calculations where the CFL
limit is used to set the global time step. ---*/
- if ((config->GetConsole_Output_Verb() == VERB_HIGH) || time_stepping) {
+ if ((config->GetComm_Level() == COMM_FULL) || time_stepping) {
#ifdef HAVE_MPI
su2double rbuf_time = Min_Delta_Time;
SU2_MPI::Allreduce(&rbuf_time, &Min_Delta_Time, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
diff --git a/SU2_CFD/src/solver_direct_mean_inc.cpp b/SU2_CFD/src/solver_direct_mean_inc.cpp
index 629310785c24..dde412db7a48 100755
--- a/SU2_CFD/src/solver_direct_mean_inc.cpp
+++ b/SU2_CFD/src/solver_direct_mean_inc.cpp
@@ -95,6 +95,7 @@ CIncEulerSolver::CIncEulerSolver(void) : CSolver() {
SlidingState = NULL;
SlidingStateNodes = NULL;
+
}
CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CSolver() {
@@ -350,7 +351,7 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned
}
}
}
-
+
/*--- Force definition and coefficient arrays for all of the markers ---*/
CPressure = new su2double* [nMarker];
@@ -580,10 +581,23 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned
if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true;
else least_squares = false;
+ /*--- Communicate and store volume and the number of neighbors for
+ any dual CVs that lie on on periodic markers. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ }
+ SetImplicitPeriodic(euler_implicit);
+ if (iMesh == MESH_0) SetRotatePeriodic(true);
+
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
}
CIncEulerSolver::~CIncEulerSolver(void) {
@@ -667,9 +681,6 @@ CIncEulerSolver::~CIncEulerSolver(void) {
if (ForceMomentum != NULL) delete [] ForceMomentum;
if (MomentMomentum != NULL) delete [] MomentMomentum;
- if (iPoint_UndLapl != NULL) delete [] iPoint_UndLapl;
- if (jPoint_UndLapl != NULL) delete [] jPoint_UndLapl;
-
if (Primitive != NULL) delete [] Primitive;
if (Primitive_i != NULL) delete [] Primitive_i;
if (Primitive_j != NULL) delete [] Primitive_j;
@@ -2391,7 +2402,8 @@ void CIncEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solve
}
solver_container[iMesh][FLOW_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver_container[iMesh][FLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
}
delete [] Solution;
@@ -2415,7 +2427,8 @@ void CIncEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solve
}
solver_container[iMesh][TURB_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver_container[iMesh][TURB_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver_container[iMesh][TURB_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION_EDDY);
+ solver_container[iMesh][TURB_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION_EDDY);
solver_container[iMesh][TURB_SOL]->Postprocessing(geometry[iMesh], solver_container[iMesh], config, iMesh);
}
delete [] Solution;
@@ -2535,7 +2548,7 @@ void CIncEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contai
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
@@ -2644,6 +2657,8 @@ void CIncEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_contain
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -2679,6 +2694,7 @@ void CIncEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_contain
}
}
+ }
}
/*--- Local time-stepping: each element uses their own speed for steady state
@@ -2705,7 +2721,7 @@ void CIncEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_contain
/*--- Compute the max and the min dt (in parallel) ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
su2double rbuf_time, sbuf_time;
sbuf_time = Min_Delta_Time;
@@ -2944,7 +2960,7 @@ void CIncEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_cont
/*--- Warning message about non-physical reconstructions. ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD);
#else
@@ -3237,6 +3253,8 @@ void CIncEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) {
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -3271,11 +3289,20 @@ void CIncEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) {
}
}
+ }
+ }
+
+ /*--- Correct the eigenvalue values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG);
}
/*--- MPI parallelization ---*/
- Set_MPI_MaxEigenvalue(geometry, config);
+ InitiateComms(geometry, config, MAX_EIGENVALUE);
+ CompleteComms(geometry, config, MAX_EIGENVALUE);
}
@@ -3323,9 +3350,17 @@ void CIncEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *confi
}
+ /*--- Correct the Laplacian values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN);
+ }
+
/*--- MPI parallelization ---*/
- Set_MPI_Undivided_Laplacian(geometry, config);
+ InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN);
+ CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN);
delete [] Diff;
@@ -3393,6 +3428,13 @@ void CIncEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfi
}
+ /*--- Correct the sensor values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR);
+ }
+
/*--- Set pressure switch for each point ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++)
@@ -3400,7 +3442,8 @@ void CIncEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfi
/*--- MPI parallelization ---*/
- Set_MPI_Sensor(geometry, config);
+ InitiateComms(geometry, config, SENSOR);
+ CompleteComms(geometry, config, SENSOR);
}
@@ -3681,23 +3724,25 @@ void CIncEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) {
MyAllBound_CQ_Inv = AllBound_CQ_Inv; AllBound_CQ_Inv = 0.0;
AllBound_CMerit_Inv = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Inv, &AllBound_CD_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Inv, &AllBound_CL_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Inv, &AllBound_CSF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Inv, &AllBound_CMx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Inv, &AllBound_CMy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Inv, &AllBound_CMz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Inv, &AllBound_CoPx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Inv, &AllBound_CoPy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Inv, &AllBound_CoPz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Inv, &AllBound_CFx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Inv, &AllBound_CFy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Inv, &AllBound_CFz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Inv, &AllBound_CT_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Inv, &AllBound_CQ_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Inv, &AllBound_CD_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Inv, &AllBound_CL_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Inv, &AllBound_CSF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Inv, &AllBound_CMx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Inv, &AllBound_CMy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Inv, &AllBound_CMz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Inv, &AllBound_CoPx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Inv, &AllBound_CoPy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Inv, &AllBound_CoPz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Inv, &AllBound_CFx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Inv, &AllBound_CFy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Inv, &AllBound_CFz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Inv, &AllBound_CT_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Inv, &AllBound_CQ_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS);
+ }
+
/*--- Add the forces on the surfaces using all the nodes ---*/
MySurface_CL_Inv = new su2double[config->GetnMarker_Monitoring()];
@@ -3735,18 +3780,20 @@ void CIncEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) {
Surface_CMz_Inv[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Inv, Surface_CL_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Inv, Surface_CD_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Inv, Surface_CSF_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Inv, Surface_CFx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Inv, Surface_CFy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Inv, Surface_CFz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Inv, Surface_CMx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Inv, Surface_CMy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Inv, Surface_CMz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Inv, Surface_CL_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Inv, Surface_CD_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Inv, Surface_CSF_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Inv, Surface_CFx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Inv, Surface_CFy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Inv, Surface_CFz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Inv, Surface_CMx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Inv, Surface_CMy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Inv, Surface_CMz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
+
delete [] MySurface_CL_Inv; delete [] MySurface_CD_Inv; delete [] MySurface_CSF_Inv;
delete [] MySurface_CEff_Inv; delete [] MySurface_CFx_Inv; delete [] MySurface_CFy_Inv;
delete [] MySurface_CFz_Inv; delete [] MySurface_CMx_Inv; delete [] MySurface_CMy_Inv;
@@ -4056,23 +4103,25 @@ void CIncEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) {
MyAllBound_CQ_Mnt = AllBound_CQ_Mnt; AllBound_CQ_Mnt = 0.0;
AllBound_CMerit_Mnt = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Mnt, &AllBound_CD_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Mnt, &AllBound_CL_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Mnt, &AllBound_CSF_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Mnt, &AllBound_CMx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Mnt, &AllBound_CMy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Mnt, &AllBound_CMz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Mnt, &AllBound_CFx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Mnt, &AllBound_CFy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Mnt, &AllBound_CFz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Mnt, &AllBound_CoPx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Mnt, &AllBound_CoPy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Mnt, &AllBound_CoPz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Mnt, &AllBound_CT_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Mnt, &AllBound_CQ_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Mnt = AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Mnt, &AllBound_CD_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Mnt, &AllBound_CL_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Mnt, &AllBound_CSF_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Mnt, &AllBound_CMx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Mnt, &AllBound_CMy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Mnt, &AllBound_CMz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Mnt, &AllBound_CFx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Mnt, &AllBound_CFy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Mnt, &AllBound_CFz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Mnt, &AllBound_CoPx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Mnt, &AllBound_CoPy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Mnt, &AllBound_CoPz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Mnt, &AllBound_CT_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Mnt, &AllBound_CQ_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Mnt = AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS);
+ }
+
/*--- Add the forces on the surfaces using all the nodes ---*/
MySurface_CL_Mnt = new su2double[config->GetnMarker_Monitoring()];
@@ -4110,18 +4159,20 @@ void CIncEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) {
Surface_CMz_Mnt[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Mnt, Surface_CL_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Mnt, Surface_CD_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Mnt, Surface_CSF_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Mnt, Surface_CFx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Mnt, Surface_CFy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Mnt, Surface_CFz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Mnt, Surface_CMx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Mnt, Surface_CMy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Mnt, Surface_CMz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Mnt, Surface_CL_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Mnt, Surface_CD_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Mnt, Surface_CSF_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Mnt, Surface_CFx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Mnt, Surface_CFy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Mnt, Surface_CFz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Mnt, Surface_CMx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Mnt, Surface_CMy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Mnt, Surface_CMz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
+
delete [] MySurface_CL_Mnt; delete [] MySurface_CD_Mnt; delete [] MySurface_CSF_Mnt;
delete [] MySurface_CEff_Mnt; delete [] MySurface_CFx_Mnt; delete [] MySurface_CFy_Mnt;
delete [] MySurface_CFz_Mnt;
@@ -4183,7 +4234,8 @@ void CIncEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver
/*--- Update the solution ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
Delta = node[iPoint]->GetDelta_Time() / Vol;
Res_TruncError = node[iPoint]->GetResTruncError();
@@ -4204,7 +4256,8 @@ void CIncEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -4228,7 +4281,8 @@ void CIncEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
/*--- Update the solution ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
Delta = node[iPoint]->GetDelta_Time() / Vol;
local_Res_TruncError = node[iPoint]->GetResTruncError();
@@ -4250,7 +4304,8 @@ void CIncEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -4283,7 +4338,8 @@ void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
/*--- Read the volume ---*/
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
/*--- Apply the preconditioner and add to the diagonal. ---*/
@@ -4345,9 +4401,15 @@ void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **sol
}
}
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ }
+
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
@@ -4359,7 +4421,7 @@ void CIncEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *con
unsigned long iPoint, jPoint, iEdge, iVertex;
unsigned short iDim, iVar, iMarker;
su2double *PrimVar_Vertex, *PrimVar_i, *PrimVar_j, PrimVar_Average,
- Partial_Gradient, Partial_Res, *Normal;
+ Partial_Gradient, Partial_Res, *Normal, Vol;
/*--- Incompressible flow, primitive variables nDim+4, (P, vx, vy, vz, T, rho, beta) ---*/
@@ -4396,8 +4458,8 @@ void CIncEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *con
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY &&
- config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
if (geometry->node[iPoint]->GetDomain()) {
@@ -4413,36 +4475,52 @@ void CIncEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, CConfig *con
}
}
}
+ }
+ }
+
+ /*--- Correct the gradient values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_GG);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_GG);
}
/*--- Update gradient value ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
+
+ /*--- Get the volume, which may include periodic components. ---*/
+
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
+
for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
- Partial_Gradient = node[iPoint]->GetGradient_Primitive(iVar, iDim) / (geometry->node[iPoint]->GetVolume());
+ Partial_Gradient = node[iPoint]->GetGradient_Primitive(iVar, iDim)/Vol;
node[iPoint]->SetGradient_Primitive(iVar, iDim, Partial_Gradient);
}
}
}
+ /*--- Communicate the gradient values via MPI. ---*/
+
+ InitiateComms(geometry, config, PRIMITIVE_GRADIENT);
+ CompleteComms(geometry, config, PRIMITIVE_GRADIENT);
+
delete [] PrimVar_Vertex;
delete [] PrimVar_i;
delete [] PrimVar_j;
- Set_MPI_Primitive_Gradient(geometry, config);
-
}
void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *config) {
unsigned short iVar, iDim, jDim, iNeigh;
unsigned long iPoint, jPoint;
- su2double *PrimVar_i, *PrimVar_j, *Coord_i, *Coord_j, r11, r12, r13, r22, r23, r23_a,
- r23_b, r33, weight, product, z11, z12, z13, z22, z23, z33, detR2;
+ su2double *PrimVar_i, *PrimVar_j, *Coord_i, *Coord_j;
+ su2double r11, r12, r13, r22, r23, r23_a, r23_b, r33, weight;
+ su2double z11, z12, z13, z22, z23, z33, detR2;
bool singular;
- /*--- Incompressible flow, primitive variables nDim+4, (P, vx, vy, vz, T, rho, beta) ---*/
-
/*--- Loop over points of the grid ---*/
for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
@@ -4464,12 +4542,11 @@ void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *con
for (iDim = 0; iDim < nDim; iDim++)
Cvector[iVar][iDim] = 0.0;
- r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
- r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+ /*--- Clear Rmatrix, which could eventually be computed once
+ and stored for static meshes, as well as the prim gradient. ---*/
- AD::StartPreacc();
- AD::SetPreaccIn(PrimVar_i, nPrimVarGrad);
- AD::SetPreaccIn(Coord_i, nDim);
+ node[iPoint]->SetRmatrixZero();
+ node[iPoint]->SetGradient_PrimitiveZero(nPrimVarGrad);
for (iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); iNeigh++) {
jPoint = geometry->node[iPoint]->GetPoint(iNeigh);
@@ -4477,9 +4554,6 @@ void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *con
PrimVar_j = node[jPoint]->GetPrimitive();
- AD::SetPreaccIn(Coord_j, nDim);
- AD::SetPreaccIn(PrimVar_j, nPrimVarGrad);
-
weight = 0.0;
for (iDim = 0; iDim < nDim; iDim++)
weight += (Coord_j[iDim]-Coord_i[iDim])*(Coord_j[iDim]-Coord_i[iDim]);
@@ -4488,34 +4562,63 @@ void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *con
if (weight != 0.0) {
- r11 += (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight;
- r12 += (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight;
- r22 += (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight;
+ node[iPoint]->AddRmatrix(0, 0, (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight);
+ node[iPoint]->AddRmatrix(0, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight);
+ node[iPoint]->AddRmatrix(1, 1, (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight);
if (nDim == 3) {
- r13 += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r23_a += (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight;
- r23_b += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r33 += (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight;
+ node[iPoint]->AddRmatrix(0, 2, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(1, 2, (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 2, (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight);
}
/*--- Entries of c:= transpose(A)*b ---*/
- for (iVar = 0; iVar < nPrimVarGrad; iVar++)
- for (iDim = 0; iDim < nDim; iDim++)
- Cvector[iVar][iDim] += (Coord_j[iDim]-Coord_i[iDim])*(PrimVar_j[iVar]-PrimVar_i[iVar])/weight;
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->AddGradient_Primitive(iVar,iDim, (Coord_j[iDim]-Coord_i[iDim])*(PrimVar_j[iVar]-PrimVar_i[iVar])/weight);
+ }
+ }
}
-
}
+ }
+
+ /*--- Correct the gradient values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_LS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_PRIM_LS);
+ }
+
+ /*--- Second loop over points of the grid to compute final gradient ---*/
+
+ for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
+
+ /*--- Set the value of the singular ---*/
+
+ singular = false;
/*--- Entries of upper triangular matrix R ---*/
+ r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
+ r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+
+ r11 = node[iPoint]->GetRmatrix(0,0);
+ r12 = node[iPoint]->GetRmatrix(0,1);
+ r22 = node[iPoint]->GetRmatrix(1,1);
+
if (r11 >= 0.0) r11 = sqrt(r11); else r11 = 0.0;
if (r11 != 0.0) r12 = r12/r11; else r12 = 0.0;
if (r22-r12*r12 >= 0.0) r22 = sqrt(r22-r12*r12); else r22 = 0.0;
if (nDim == 3) {
+ r13 = node[iPoint]->GetRmatrix(0,2);
+ r23_a = node[iPoint]->GetRmatrix(1,2);
+ r23_b = node[iPoint]->GetRmatrix(2,1);
+ r33 = node[iPoint]->GetRmatrix(2,2);
+
if (r11 != 0.0) r13 = r13/r11; else r13 = 0.0;
if ((r22 != 0.0) && (r11*r22 != 0.0)) r23 = r23_a/r22 - r23_b*r12/(r11*r22); else r23 = 0.0;
if (r33-r23*r23-r13*r13 >= 0.0) r33 = sqrt(r33-r23*r23-r13*r13); else r33 = 0.0;
@@ -4562,20 +4665,25 @@ void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, CConfig *con
/*--- Computation of the gradient: S*c ---*/
for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
- product = 0.0;
+ Cvector[iVar][iDim] = 0.0;
for (jDim = 0; jDim < nDim; jDim++) {
- product += Smatrix[iDim][jDim]*Cvector[iVar][jDim];
+ Cvector[iVar][iDim] += Smatrix[iDim][jDim]*node[iPoint]->GetGradient_Primitive(iVar, jDim);
}
-
- node[iPoint]->SetGradient_Primitive(iVar, iDim, product);
}
}
- AD::SetPreaccOut(node[iPoint]->GetGradient_Primitive(), nPrimVarGrad, nDim);
- AD::EndPreacc();
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->SetGradient_Primitive(iVar, iDim, Cvector[iVar][iDim]);
+ }
+ }
+
}
- Set_MPI_Primitive_Gradient(geometry, config);
+ /*--- Communicate the gradient values via MPI. ---*/
+
+ InitiateComms(geometry, config, PRIMITIVE_GRADIENT);
+ CompleteComms(geometry, config, PRIMITIVE_GRADIENT);
}
@@ -4639,6 +4747,13 @@ void CIncEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config)
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_1);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_1);
+ }
+
}
@@ -4750,15 +4865,17 @@ void CIncEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config)
}
+ if (config->GetKind_SlopeLimit_Flow() == VENKATAKRISHNAN_WANG) {
#ifdef HAVE_MPI
- SU2_MPI::Allreduce(LocalMinPrimitive, GlobalMinPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(LocalMaxPrimitive, GlobalMaxPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMinPrimitive, GlobalMinPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMaxPrimitive, GlobalMaxPrimitive, nPrimVarGrad, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
#else
- for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
- GlobalMinPrimitive[iVar] = LocalMinPrimitive[iVar];
- GlobalMaxPrimitive[iVar] = LocalMaxPrimitive[iVar];
- }
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ GlobalMinPrimitive[iVar] = LocalMinPrimitive[iVar];
+ GlobalMaxPrimitive[iVar] = LocalMaxPrimitive[iVar];
+ }
#endif
+ }
for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) {
@@ -4835,9 +4952,17 @@ void CIncEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config)
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_2);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_PRIM_2);
+ }
+
/*--- Limiter MPI ---*/
- Set_MPI_Primitive_Limiter(geometry, config);
+ InitiateComms(geometry, config, PRIMITIVE_LIMITER);
+ CompleteComms(geometry, config, PRIMITIVE_LIMITER);
}
@@ -6449,6 +6574,23 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c
delete [] Normal;
delete [] PrimVar_i;
delete [] PrimVar_j;
+
+}
+
+void CIncEulerSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config) {
+
+ /*--- Complete residuals for periodic boundary conditions. We loop over
+ the periodic BCs in matching pairs so that, in the event that there are
+ adjacent periodic markers, the repeated points will have their residuals
+ accumulated correctly during the communications. For implicit calculations,
+ the Jacobians and linear system are also correctly adjusted here. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ }
+
}
void CIncEulerSolver::BC_Custom(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short val_marker) { }
@@ -6469,7 +6611,9 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver
bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT);
bool grid_movement = config->GetGrid_Movement();
-
+ bool variable_density = (config->GetKind_DensityModel() == VARIABLE);
+ bool energy = config->GetEnergy_Equation();
+
/*--- Store the physical time step ---*/
TimeStep = config->GetDelta_UnstTimeND();
@@ -6540,22 +6684,87 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver
+1.0*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep);
}
+ if (!energy) Residual[nDim+1] = 0.0;
+
/*--- Store the residual and compute the Jacobian contribution due
to the dual time source term. ---*/
LinSysRes.AddBlock(iPoint, Residual);
+
if (implicit) {
- for (iVar = 1; iVar < nVar; iVar++) {
- if (config->GetUnsteady_Simulation() == DT_STEPPING_1ST)
- Jacobian_i[iVar][iVar] = Volume_nP1 / TimeStep;
- if (config->GetUnsteady_Simulation() == DT_STEPPING_2ND)
- Jacobian_i[iVar][iVar] = (Volume_nP1*3.0)/(2.0*TimeStep);
- }
+
+ unsigned short iDim, jDim;
+
+ su2double BetaInc2, Density, dRhodT, Temperature, Cp;
+ su2double Velocity[3] = {0.0,0.0,0.0};
+
+ /*--- Access the primitive variables at this node. ---*/
+
+ Density = node[iPoint]->GetDensity();
+ BetaInc2 = node[iPoint]->GetBetaInc2();
+ Cp = node[iPoint]->GetSpecificHeatCp();
+ Temperature = node[iPoint]->GetTemperature();
+
for (iDim = 0; iDim < nDim; iDim++)
- Jacobian_i[iDim+1][iDim+1] = Density*Jacobian_i[iDim+1][iDim+1];
- Jacobian_i[nDim+1][nDim+1] = Density*Cp*Jacobian_i[nDim+1][nDim+1];
+ Velocity[iDim] = node[iPoint]->GetVelocity(iDim);
+
+ /*--- We need the derivative of the equation of state to build the
+ preconditioning matrix. For now, the only option is the ideal gas
+ law, but in the future, dRhodT should be in the fluid model. ---*/
+
+ if (variable_density) {
+ dRhodT = -Density/Temperature;
+ } else {
+ dRhodT = 0.0;
+ }
+
+ /*--- Calculating the inverse of the preconditioning matrix
+ that multiplies the time derivative during time integration. ---*/
+
+ /*--- For implicit calculations, we multiply the preconditioner
+ by the cell volume over the time step and add to the Jac diagonal. ---*/
+
+ Jacobian_i[0][0] = 1.0/BetaInc2;
+ for (iDim = 0; iDim < nDim; iDim++)
+ Jacobian_i[iDim+1][0] = Velocity[iDim]/BetaInc2;
+
+ if (energy) Jacobian_i[nDim+1][0] = Cp*Temperature/BetaInc2;
+ else Jacobian_i[nDim+1][0] = 0.0;
+
+ for (jDim = 0; jDim < nDim; jDim++) {
+ Jacobian_i[0][jDim+1] = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++) {
+ if (iDim == jDim) Jacobian_i[iDim+1][jDim+1] = Density;
+ else Jacobian_i[iDim+1][jDim+1] = 0.0;
+ }
+ Jacobian_i[nDim+1][jDim+1] = 0.0;
+ }
+
+ Jacobian_i[0][nDim+1] = dRhodT;
+ for (iDim = 0; iDim < nDim; iDim++)
+ Jacobian_i[iDim+1][nDim+1] = Velocity[iDim]*dRhodT;
+
+ if (energy) Jacobian_i[nDim+1][nDim+1] = Cp*(dRhodT*Temperature + Density);
+ else Jacobian_i[nDim+1][nDim+1] = 1.0;
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (jVar = 0; jVar < nVar; jVar++) {
+ if (config->GetUnsteady_Simulation() == DT_STEPPING_1ST)
+ Jacobian_i[iVar][jVar] *= Volume_nP1 / TimeStep;
+ if (config->GetUnsteady_Simulation() == DT_STEPPING_2ND)
+ Jacobian_i[iVar][jVar] *= (Volume_nP1*3.0)/(2.0*TimeStep);
+ }
+ }
+ if (!energy) {
+ for (iVar = 0; iVar < nVar; iVar++) {
+ Jacobian_i[iVar][nDim+1] = 0.0;
+ Jacobian_i[nDim+1][iVar] = 0.0;
+ }
+ }
+
Jacobian.AddBlock(iPoint, iPoint, Jacobian_i);
+
}
}
@@ -6635,6 +6844,8 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver
/*--- Loop over the boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Initialize the Residual / Jacobian container to zero. ---*/
@@ -6677,6 +6888,7 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver
LinSysRes.AddBlock(iPoint, Residual);
}
+ }
}
/*--- Loop over all nodes (excluding halos) to compute the remainder
@@ -7179,7 +7391,9 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
on the fine level in order to have all necessary quantities updated,
especially if this is a turbulent simulation (eddy viscosity). ---*/
- solver[MESH_0][FLOW_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
+ solver[MESH_0][FLOW_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
+ solver[MESH_0][FLOW_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
+
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
@@ -7198,9 +7412,9 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
}
solver[iMesh][FLOW_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver[iMesh][FLOW_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
+ solver[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
-
}
/*--- Update the geometry for flows on dynamic meshes ---*/
@@ -7209,8 +7423,11 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
- geometry[MESH_0]->Set_MPI_Coord(config);
- geometry[MESH_0]->Set_MPI_GridVel(config);
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
+
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, GRID_VELOCITY);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, GRID_VELOCITY);
/*--- Recompute the edges and dual mesh control volumes in the
domain and on the boundaries. ---*/
@@ -7237,7 +7454,8 @@ void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
- geometry[MESH_0]->Set_MPI_Coord(config);
+ geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
+ geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
/*--- Recompute the edges and dual mesh control volumes in the
domain and on the boundaries. ---*/
@@ -7858,10 +8076,23 @@ CIncNSSolver::CIncNSSolver(CGeometry *geometry, CConfig *config, unsigned short
if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true;
else least_squares = false;
+ /*--- Communicate and store volume and the number of neighbors for
+ any dual CVs that lie on on periodic markers. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
+ }
+ SetImplicitPeriodic(euler_implicit);
+ if (iMesh == MESH_0) SetRotatePeriodic(true);
+
/*--- Perform the MPI communication of the solution ---*/
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
+
}
CIncNSSolver::~CIncNSSolver(void) {
@@ -8010,7 +8241,7 @@ void CIncNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container
/*--- Error message ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0;
@@ -8162,6 +8393,8 @@ void CIncNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Point identification, Normal vector and area ---*/
@@ -8210,6 +8443,7 @@ void CIncNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
if (geometry->node[iPoint]->GetDomain()) node[iPoint]->AddMax_Lambda_Visc(Lambda);
}
+ }
}
/*--- Each element uses their own speed, steady state simulation ---*/
@@ -8236,7 +8470,7 @@ void CIncNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container,
}
/*--- Compute the max and the min dt (in parallel) ---*/
- if (config->GetConsole_Output_Verb() == VERB_HIGH) {
+ if (config->GetComm_Level() == COMM_FULL) {
#ifdef HAVE_MPI
su2double rbuf_time, sbuf_time;
sbuf_time = Min_Delta_Time;
@@ -8679,26 +8913,28 @@ void CIncNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
MyAllBound_HF_Visc = AllBound_HF_Visc; AllBound_HF_Visc = 0.0;
MyAllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, MaxNorm); AllBound_MaxHF_Visc = 0.0;
- SU2_MPI::Allreduce(&MyAllBound_CD_Visc, &AllBound_CD_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CL_Visc, &AllBound_CL_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CSF_Visc, &AllBound_CSF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS);
- SU2_MPI::Allreduce(&MyAllBound_CMx_Visc, &AllBound_CMx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMy_Visc, &AllBound_CMy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CMz_Visc, &AllBound_CMz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFx_Visc, &AllBound_CFx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFy_Visc, &AllBound_CFy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CFz_Visc, &AllBound_CFz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPx_Visc, &AllBound_CoPx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPy_Visc, &AllBound_CoPy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CoPz_Visc, &AllBound_CoPz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CT_Visc, &AllBound_CT_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_CQ_Visc, &AllBound_CQ_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS);
- SU2_MPI::Allreduce(&MyAllBound_HF_Visc, &AllBound_HF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&MyAllBound_MaxHF_Visc, &AllBound_MaxHF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(&MyAllBound_CD_Visc, &AllBound_CD_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CL_Visc, &AllBound_CL_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CSF_Visc, &AllBound_CSF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_CMx_Visc, &AllBound_CMx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMy_Visc, &AllBound_CMy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CMz_Visc, &AllBound_CMz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFx_Visc, &AllBound_CFx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFy_Visc, &AllBound_CFy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CFz_Visc, &AllBound_CFz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPx_Visc, &AllBound_CoPx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPy_Visc, &AllBound_CoPy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CoPz_Visc, &AllBound_CoPz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CT_Visc, &AllBound_CT_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_CQ_Visc, &AllBound_CQ_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS);
+ SU2_MPI::Allreduce(&MyAllBound_HF_Visc, &AllBound_HF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&MyAllBound_MaxHF_Visc, &AllBound_MaxHF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm);
+ }
+
/*--- Add the forces on the surfaces using all the nodes ---*/
MySurface_CL_Visc = new su2double[config->GetnMarker_Monitoring()];
@@ -8743,20 +8979,22 @@ void CIncNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) {
Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0;
}
- SU2_MPI::Allreduce(MySurface_CL_Visc, Surface_CL_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CD_Visc, Surface_CD_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CSF_Visc, Surface_CSF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
- Surface_CEff_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring] / (Surface_CD_Visc[iMarker_Monitoring] + EPS);
- SU2_MPI::Allreduce(MySurface_CFx_Visc, Surface_CFx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFy_Visc, Surface_CFy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CFz_Visc, Surface_CFz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMx_Visc, Surface_CMx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMy_Visc, Surface_CMy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_CMz_Visc, Surface_CMz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_HF_Visc, Surface_HF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(MySurface_MaxHF_Visc, Surface_MaxHF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
-
+ if (config->GetComm_Level() == COMM_FULL) {
+ SU2_MPI::Allreduce(MySurface_CL_Visc, Surface_CL_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CD_Visc, Surface_CD_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CSF_Visc, Surface_CSF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++)
+ Surface_CEff_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring] / (Surface_CD_Visc[iMarker_Monitoring] + EPS);
+ SU2_MPI::Allreduce(MySurface_CFx_Visc, Surface_CFx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFy_Visc, Surface_CFy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CFz_Visc, Surface_CFz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMx_Visc, Surface_CMx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMy_Visc, Surface_CMy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_CMz_Visc, Surface_CMz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_HF_Visc, Surface_HF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(MySurface_MaxHF_Visc, Surface_MaxHF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ }
+
delete [] MySurface_CL_Visc; delete [] MySurface_CD_Visc; delete [] MySurface_CSF_Visc;
delete [] MySurface_CEff_Visc; delete [] MySurface_CFx_Visc; delete [] MySurface_CFy_Visc;
delete [] MySurface_CFz_Visc; delete [] MySurface_CMx_Visc; delete [] MySurface_CMy_Visc;
diff --git a/SU2_CFD/src/solver_direct_transition.cpp b/SU2_CFD/src/solver_direct_transition.cpp
index 872f993ae1e6..88d7c00fd830 100644
--- a/SU2_CFD/src/solver_direct_transition.cpp
+++ b/SU2_CFD/src/solver_direct_transition.cpp
@@ -265,8 +265,9 @@ void CTransLMSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solv
}
/*--- MPI solution ---*/
-
- Set_MPI_Solution(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION);
+ CompleteComms(geometry, config, SOLUTION);
/*--- Compute the root mean square residual ---*/
diff --git a/SU2_CFD/src/solver_direct_turbulent.cpp b/SU2_CFD/src/solver_direct_turbulent.cpp
index a21577720b12..ac88f2e3b8ce 100644
--- a/SU2_CFD/src/solver_direct_turbulent.cpp
+++ b/SU2_CFD/src/solver_direct_turbulent.cpp
@@ -68,9 +68,9 @@ CTurbSolver::CTurbSolver(CGeometry* geometry, CConfig *config) : CSolver() {
}
CTurbSolver::~CTurbSolver(void) {
-
+
if (Inlet_TurbVars != NULL) {
- for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
+ for (unsigned short iMarker = 0; iMarker < nMarker; iMarker++) {
if (Inlet_TurbVars[iMarker] != NULL) {
for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
delete [] Inlet_TurbVars[iMarker][iVertex];
@@ -87,7 +87,6 @@ CTurbSolver::~CTurbSolver(void) {
if (upperlimit != NULL) delete [] upperlimit;
if (nVertex != NULL) delete [] nVertex;
-
}
void CTurbSolver::Set_MPI_Solution(CGeometry *geometry, CConfig *config) {
@@ -686,6 +685,22 @@ void CTurbSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, CNum
}
}
+void CTurbSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container,
+ CNumerics *numerics, CConfig *config) {
+
+ /*--- Complete residuals for periodic boundary conditions. We loop over
+ the periodic BCs in matching pairs so that, in the event that there are
+ adjacent periodic markers, the repeated points will have their residuals
+ accumulated corectly during the communications. For implicit calculations
+ the Jacobians and linear system are also correctly adjusted here. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
+ }
+
+}
+
void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) {
unsigned short iVar;
@@ -709,7 +724,8 @@ void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_
/*--- Read the volume ---*/
- Vol = geometry->node[iPoint]->GetVolume();
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
/*--- Modify matrix diagonal to assure diagonal dominance ---*/
@@ -789,10 +805,15 @@ void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_
}
}
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
+ }
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_EDDY);
+ CompleteComms(geometry, config, SOLUTION_EDDY);
/*--- Compute the root mean square residual ---*/
@@ -969,7 +990,8 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con
/*--- Loop over the boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
/*--- Get the index for node i plus the boundary face normal ---*/
@@ -1004,6 +1026,8 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con
Residual[iVar] = U_time_n[iVar]*Residual_GCL;
}
LinSysRes.AddBlock(iPoint, Residual);
+
+ }
}
}
@@ -1189,11 +1213,10 @@ void CTurbSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *
}
/*--- MPI solution and compute the eddy viscosity ---*/
-
-//TODO fix order of comunication the periodic should be first otherwise you have wrong values on the halo cell after restart.
- solver[MESH_0][TURB_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
- solver[MESH_0][TURB_SOL]->Set_MPI_Solution(geometry[MESH_0], config);
-
+
+ solver[MESH_0][TURB_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION_EDDY);
+ solver[MESH_0][TURB_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION_EDDY);
+
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
solver[MESH_0][TURB_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0);
@@ -1213,7 +1236,8 @@ void CTurbSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *
}
solver[iMesh][TURB_SOL]->node[iPoint]->SetSolution(Solution);
}
- solver[iMesh][TURB_SOL]->Set_MPI_Solution(geometry[iMesh], config);
+ solver[iMesh][TURB_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION_EDDY);
+ solver[iMesh][TURB_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION_EDDY);
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
solver[iMesh][TURB_SOL]->Postprocessing(geometry[iMesh], solver[iMesh], config, iMesh);
}
@@ -1404,10 +1428,9 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor
/*--- MPI solution ---*/
-//TODO fix order of comunication the periodic should be first otherwise you have wrong values on the halo cell after restart
- Set_MPI_Solution(geometry, config);
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_EDDY);
+ CompleteComms(geometry, config, SOLUTION_EDDY);
+
/*--- Initializate quantities for SlidingMesh Interface ---*/
unsigned long iMarker;
@@ -1447,6 +1470,11 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor
Inlet_TurbVars[iMarker][iVertex][0] = nu_tilde_Inf;
}
}
+
+ /*--- The turbulence models are always solved implicitly, so set the
+ implicit flag in case we have periodic BCs. ---*/
+
+ SetImplicitPeriodic(true);
}
@@ -3738,10 +3766,9 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh
/*--- MPI solution ---*/
-//TODO fix order of comunication the periodic should be first otherwise you have wrong values on the halo cell after restart
- Set_MPI_Solution(geometry, config);
- Set_MPI_Solution(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_EDDY);
+ CompleteComms(geometry, config, SOLUTION_EDDY);
+
/*--- Initializate quantities for SlidingMesh Interface ---*/
unsigned long iMarker;
@@ -3771,7 +3798,7 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh
}
/*-- Allocation of inlets has to happen in derived classes (not CTurbSolver),
- * due to arbitrary number of turbulence variables ---*/
+ due to arbitrary number of turbulence variables ---*/
Inlet_TurbVars = new su2double**[nMarker];
for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
@@ -3783,6 +3810,11 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh
}
}
+ /*--- The turbulence models are always solved implicitly, so set the
+ implicit flag in case we have periodic BCs. ---*/
+
+ SetImplicitPeriodic(true);
+
}
CTurbSSTSolver::~CTurbSSTSolver(void) {
@@ -3826,6 +3858,7 @@ void CTurbSSTSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain
bool limiter_flow = ((config->GetKind_SlopeLimit_Flow() != NO_LIMITER) && (ExtIter <= config->GetLimiterIter()) && !(disc_adjoint && config->GetFrozen_Limiter_Disc()));
bool limiter_turb = ((config->GetKind_SlopeLimit_Turb() != NO_LIMITER) && (ExtIter <= config->GetLimiterIter()) && !(disc_adjoint && config->GetFrozen_Limiter_Disc()));
+
for (iPoint = 0; iPoint < nPoint; iPoint ++) {
/*--- Initialize the residual vector ---*/
diff --git a/SU2_CFD/src/solver_structure.cpp b/SU2_CFD/src/solver_structure.cpp
index 97fc32ed4bd2..e888d9888b5f 100644
--- a/SU2_CFD/src/solver_structure.cpp
+++ b/SU2_CFD/src/solver_structure.cpp
@@ -75,6 +75,8 @@ CSolver::CSolver(void) {
Jacobian_ij = NULL;
Jacobian_ji = NULL;
Jacobian_jj = NULL;
+ iPoint_UndLapl = NULL;
+ jPoint_UndLapl = NULL;
Smatrix = NULL;
Cvector = NULL;
Restart_Vars = NULL;
@@ -90,7 +92,14 @@ CSolver::CSolver(void) {
Inlet_Data = NULL;
/*--- Variable initialization to avoid valgrid warnings when not used. ---*/
+
IterLinSolver = 0;
+
+ /*--- Flags for the periodic BC communications. ---*/
+
+ rotate_periodic = false;
+ implicit_periodic = false;
+
}
CSolver::~CSolver(void) {
@@ -151,6 +160,8 @@ CSolver::~CSolver(void) {
if (Res_Visc_i != NULL) delete [] Res_Visc_i;
if (Res_Visc_j != NULL) delete [] Res_Visc_j;
+ if (iPoint_UndLapl != NULL) delete [] iPoint_UndLapl;
+ if (jPoint_UndLapl != NULL) delete [] jPoint_UndLapl;
if (Jacobian_i != NULL) {
for (iVar = 0; iVar < nVar; iVar++)
@@ -193,21 +204,1954 @@ CSolver::~CSolver(void) {
delete [] Smatrix[iDim];
delete [] Smatrix;
}
-
- if (Cvector != NULL) {
- for (iVar = 0; iVar < nVarGrad; iVar++)
- delete [] Cvector[iVar];
- delete [] Cvector;
+
+ if (Cvector != NULL) {
+ for (iVar = 0; iVar < nVarGrad; iVar++)
+ delete [] Cvector[iVar];
+ delete [] Cvector;
+ }
+
+ if (Restart_Vars != NULL) {delete [] Restart_Vars; Restart_Vars = NULL;}
+ if (Restart_Data != NULL) {delete [] Restart_Data; Restart_Data = NULL;}
+
+ if (nRowCum_InletFile != NULL) {delete [] nRowCum_InletFile; nRowCum_InletFile = NULL;}
+ if (nRow_InletFile != NULL) {delete [] nRow_InletFile; nRow_InletFile = NULL;}
+ if (nCol_InletFile != NULL) {delete [] nCol_InletFile; nCol_InletFile = NULL;}
+ if (Inlet_Data != NULL) {delete [] Inlet_Data; Inlet_Data = NULL;}
+
+}
+
+void CSolver::InitiatePeriodicComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short val_periodic_index,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ bool boundary_i, boundary_j;
+
+ unsigned short iVar, jVar, iDim;
+ unsigned short iNeighbor, nNeighbor = 0;
+ unsigned short COUNT_PER_POINT = 0;
+ unsigned short MPI_TYPE = 0;
+ unsigned short ICOUNT = nVar;
+ unsigned short JCOUNT = nVar;
+
+ int iMessage, iSend, nSend;
+
+ unsigned long iPoint, jPoint, offset, buf_offset, iPeriodic, Neighbor_Point;
+
+ su2double *Diff = new su2double[nVar];
+ su2double *Und_Lapl = new su2double[nVar];
+ su2double *Sol_Min = new su2double[nPrimVarGrad];
+ su2double *Sol_Max = new su2double[nPrimVarGrad];
+ su2double *rotPrim_i = new su2double[nPrimVar];
+ su2double *rotPrim_j = new su2double[nPrimVar];
+
+ su2double Sensor_i = 0.0, Sensor_j = 0.0, Pressure_i, Pressure_j;
+ su2double *Coord_i, *Coord_j, r11, r12, r13, r22, r23_a, r23_b, r33, weight;
+ su2double *center, *angles, translation[3]={0.0,0.0,0.0}, *trans, dx, dy, dz;
+ su2double rotMatrix[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
+ su2double Theta, Phi, Psi, cosTheta, sinTheta, cosPhi, sinPhi, cosPsi, sinPsi;
+ su2double rotCoord_i[3] = {0.0, 0.0, 0.0}, rotCoord_j[3] = {0.0, 0.0, 0.0};
+
+ string Marker_Tag;
+
+ /*--- Set the size of the data packet and type depending on quantity. ---*/
+
+ switch (commType) {
+ case PERIODIC_VOLUME:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_NEIGHBORS:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_UNSIGNED_SHORT;
+ break;
+ case PERIODIC_RESIDUAL:
+ COUNT_PER_POINT = nVar + nVar*nVar + 1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_IMPLICIT:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_LAPLACIAN:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_MAX_EIG:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_SENSOR:
+ COUNT_PER_POINT = 2;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_SOL_GG:
+ COUNT_PER_POINT = nVar*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_PRIM_GG:
+ COUNT_PER_POINT = nPrimVarGrad*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ ICOUNT = nPrimVarGrad;
+ break;
+ case PERIODIC_SOL_LS:
+ COUNT_PER_POINT = nDim*nDim + nVar*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_PRIM_LS:
+ COUNT_PER_POINT = nDim*nDim + nPrimVarGrad*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_LIM_PRIM_1:
+ COUNT_PER_POINT = nPrimVarGrad*2;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_LIM_PRIM_2:
+ COUNT_PER_POINT = nPrimVarGrad;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_LIM_SOL_1:
+ COUNT_PER_POINT = nVar*2;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PERIODIC_LIM_SOL_2:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for periodic communication.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ su2double **jacBlock = new su2double*[ICOUNT];
+ su2double **rotBlock = new su2double*[ICOUNT];
+ for (iVar = 0; iVar < ICOUNT; iVar++) {
+ jacBlock[iVar] = new su2double[JCOUNT];
+ rotBlock[iVar] = new su2double[JCOUNT];
+ }
+
+ /*--- Check to make sure we have created a large enough buffer
+ for these comms during preprocessing. It will be reallocated whenever
+ we find a larger count per point than currently exists. After the
+ first cycle of comms, this should be inactive. ---*/
+
+ if (COUNT_PER_POINT > geometry->countPerPeriodicPoint) {
+ geometry->AllocatePeriodicComms(COUNT_PER_POINT);
+ }
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDSend = geometry->bufD_PeriodicSend;
+
+ unsigned short *bufSSend = geometry->bufS_PeriodicSend;
+
+ /*--- Load the specified quantity from the solver into the generic
+ communication buffer in the geometry class. ---*/
+
+ if (geometry->nPeriodicSend > 0) {
+
+ /*--- Post all non-blocking recvs first before sends. ---*/
+
+ geometry->PostPeriodicRecvs(geometry, config, MPI_TYPE);
+
+ for (iMessage = 0; iMessage < geometry->nPeriodicSend; iMessage++) {
+
+ /*--- Get our location in the send buffer. ---*/
+
+ offset = geometry->nPoint_PeriodicSend[iMessage];
+
+ /*--- Get the number of periodic points we need to
+ communicate on the current periodic marker. ---*/
+
+ nSend = (geometry->nPoint_PeriodicSend[iMessage+1] -
+ geometry->nPoint_PeriodicSend[iMessage]);
+
+ for (iSend = 0; iSend < nSend; iSend++) {
+
+ /*--- Get the local index for this communicated data. We need
+ both the node and periodic face index (for rotations). ---*/
+
+ iPoint = geometry->Local_Point_PeriodicSend[offset + iSend];
+ iPeriodic = geometry->Local_Marker_PeriodicSend[offset + iSend];
+
+ /*--- Retrieve the supplied periodic information. ---*/
+
+ Marker_Tag = config->GetMarker_All_TagBound(iPeriodic);
+ center = config->GetPeriodicRotCenter(Marker_Tag);
+ angles = config->GetPeriodicRotAngles(Marker_Tag);
+ trans = config->GetPeriodicTranslation(Marker_Tag);
+
+ /*--- Store (center+trans) as it is constant and will be added. ---*/
+
+ translation[0] = center[0] + trans[0];
+ translation[1] = center[1] + trans[1];
+ translation[2] = center[2] + trans[2];
+
+ /*--- Store angles separately for clarity. Compute sines/cosines. ---*/
+
+ Theta = angles[0]; Phi = angles[1]; Psi = angles[2];
+ cosTheta = cos(Theta); cosPhi = cos(Phi); cosPsi = cos(Psi);
+ sinTheta = sin(Theta); sinPhi = sin(Phi); sinPsi = sin(Psi);
+
+ /*--- 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;
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iSend)*geometry->countPerPeriodicPoint;
+
+ /*--- Load the send buffers depending on the particular value
+ that has been requested for communication. ---*/
+
+ switch (commType) {
+
+ case PERIODIC_VOLUME:
+
+ /*--- Load the volume of the current periodic CV so that
+ we can accumulate the total control volume size on all
+ periodic faces. ---*/
+
+ bufDSend[buf_offset] = geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume();
+
+ break;
+
+ case PERIODIC_NEIGHBORS:
+
+ nNeighbor = 0;
+ for (iNeighbor = 0; iNeighbor < geometry->node[iPoint]->GetnPoint(); iNeighbor++) {
+ Neighbor_Point = geometry->node[iPoint]->GetPoint(iNeighbor);
+
+ /*--- Check if this neighbor lies on the periodic face so
+ that we avoid double counting neighbors on both sides. If
+ not, increment the count of neighbors for the donor. ---*/
+
+ if (!geometry->node[Neighbor_Point]->GetPeriodicBoundary())
+ nNeighbor++;
+
+ }
+
+ /*--- Store the number of neighbors in bufffer. ---*/
+
+ bufSSend[buf_offset] = nNeighbor;
+
+ break;
+
+ case PERIODIC_RESIDUAL:
+
+ /*--- Communicate the residual from our partial control
+ volume to the other side of the periodic face. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = LinSysRes.GetBlock(iPoint, iVar);
+ }
+
+ /*--- Rotate the momentum components of the residual array. ---*/
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes.GetBlock(iPoint, 1) +
+ rotMatrix[0][1]*LinSysRes.GetBlock(iPoint, 2));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes.GetBlock(iPoint, 1) +
+ rotMatrix[1][1]*LinSysRes.GetBlock(iPoint, 2));
+ } else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes.GetBlock(iPoint, 1) +
+ rotMatrix[0][1]*LinSysRes.GetBlock(iPoint, 2) +
+ rotMatrix[0][2]*LinSysRes.GetBlock(iPoint, 3));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes.GetBlock(iPoint, 1) +
+ rotMatrix[1][1]*LinSysRes.GetBlock(iPoint, 2) +
+ rotMatrix[1][2]*LinSysRes.GetBlock(iPoint, 3));
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*LinSysRes.GetBlock(iPoint, 1) +
+ rotMatrix[2][1]*LinSysRes.GetBlock(iPoint, 2) +
+ rotMatrix[2][2]*LinSysRes.GetBlock(iPoint, 3));
+ }
+ }
+ buf_offset += nVar;
+
+ /*--- Load the time step for the current point. ---*/
+
+ bufDSend[buf_offset] = node[iPoint]->GetDelta_Time();
+ buf_offset++;
+
+ /*--- For implicit calculations, we will communicate the
+ contributions to the Jacobian block diagonal, i.e., the
+ impact of the point upon itself, J_ii. ---*/
+
+ if (implicit_periodic) {
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (jVar = 0; jVar < nVar; jVar++) {
+ jacBlock[iVar][jVar] = Jacobian.GetBlock(iPoint, iPoint, iVar, jVar);
+ }
+ }
+
+ /*--- Rotate the momentum columns of the Jacobian. ---*/
+
+ if (rotate_periodic) {
+ for (iVar = 0; iVar < nVar; iVar++) {
+ if (nDim == 2) {
+ jacBlock[1][iVar] = (rotMatrix[0][0]*Jacobian.GetBlock(iPoint, iPoint, 1, iVar) +
+ rotMatrix[0][1]*Jacobian.GetBlock(iPoint, iPoint, 2, iVar));
+ jacBlock[2][iVar] = (rotMatrix[1][0]*Jacobian.GetBlock(iPoint, iPoint, 1, iVar) +
+ rotMatrix[1][1]*Jacobian.GetBlock(iPoint, iPoint, 2, iVar));
+ } else {
+
+ jacBlock[1][iVar] = (rotMatrix[0][0]*Jacobian.GetBlock(iPoint, iPoint, 1, iVar) +
+ rotMatrix[0][1]*Jacobian.GetBlock(iPoint, iPoint, 2, iVar) +
+ rotMatrix[0][2]*Jacobian.GetBlock(iPoint, iPoint, 3, iVar));
+ jacBlock[2][iVar] = (rotMatrix[1][0]*Jacobian.GetBlock(iPoint, iPoint, 1, iVar) +
+ rotMatrix[1][1]*Jacobian.GetBlock(iPoint, iPoint, 2, iVar) +
+ rotMatrix[1][2]*Jacobian.GetBlock(iPoint, iPoint, 3, iVar));
+ jacBlock[3][iVar] = (rotMatrix[2][0]*Jacobian.GetBlock(iPoint, iPoint, 1, iVar) +
+ rotMatrix[2][1]*Jacobian.GetBlock(iPoint, iPoint, 2, iVar) +
+ rotMatrix[2][2]*Jacobian.GetBlock(iPoint, iPoint, 3, iVar));
+ }
+ }
+ }
+
+ /*--- Load the Jacobian terms into the buffer for sending. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (jVar = 0; jVar < nVar; jVar++) {
+ bufDSend[buf_offset] = jacBlock[iVar][jVar];
+ buf_offset++;
+ }
+ }
+ }
+
+ break;
+
+ case PERIODIC_IMPLICIT:
+
+ /*--- Communicate the solution from our master set of periodic
+ nodes (from the linear solver perspective) to the passive
+ periodic nodes on the matching face. This is done at the
+ end of the iteration to synchronize the solution after the
+ linear solve. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution(iVar);
+ }
+
+ /*--- Rotate the momentum components of the solution array. ---*/
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[iPoint]->GetSolution(2));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[iPoint]->GetSolution(2));
+ } else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[0][2]*node[iPoint]->GetSolution(3));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[1][2]*node[iPoint]->GetSolution(3));
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[2][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[2][2]*node[iPoint]->GetSolution(3));
+ }
+ }
+
+ break;
+
+ case PERIODIC_LAPLACIAN:
+
+ /*--- For JST, the undivided Laplacian must be computed
+ consistently by using the complete control volume info
+ from both sides of the periodic face. ---*/
+
+ for (iVar = 0; iVar< nVar; iVar++)
+ Und_Lapl[iVar] = 0.0;
+
+ for (iNeighbor = 0; iNeighbor < geometry->node[iPoint]->GetnPoint(); iNeighbor++) {
+ jPoint = geometry->node[iPoint]->GetPoint(iNeighbor);
+
+ /*--- Avoid periodic boundary points so that we do not
+ duplicate edges on both sides of the periodic BC. ---*/
+
+ if (!geometry->node[jPoint]->GetPeriodicBoundary()) {
+
+ /*--- Solution differences ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ Diff[iVar] = (node[iPoint]->GetSolution(iVar) -
+ node[jPoint]->GetSolution(iVar));
+
+ /*--- Correction for compressible flows (use enthalpy) ---*/
+
+ if (!(config->GetKind_Regime() == INCOMPRESSIBLE)) {
+ Pressure_i = node[iPoint]->GetPressure();
+ Pressure_j = node[jPoint]->GetPressure();
+ Diff[nVar-1] = ((node[iPoint]->GetSolution(nVar-1) + Pressure_i) -
+ (node[jPoint]->GetSolution(nVar-1) + Pressure_j));
+ }
+
+ boundary_i = geometry->node[iPoint]->GetPhysicalBoundary();
+ boundary_j = geometry->node[jPoint]->GetPhysicalBoundary();
+
+ /*--- Both points inside the domain, or both in the boundary ---*/
+
+ if ((!boundary_i && !boundary_j) ||
+ ( boundary_i && boundary_j)) {
+ if (geometry->node[iPoint]->GetDomain()) {
+ for (iVar = 0; iVar< nVar; iVar++)
+ Und_Lapl[iVar] -= Diff[iVar];
+ }
+ }
+
+ /*--- iPoint inside the domain, jPoint on the boundary ---*/
+
+ if (!boundary_i && boundary_j)
+ if (geometry->node[iPoint]->GetDomain()){
+ for (iVar = 0; iVar< nVar; iVar++)
+ Und_Lapl[iVar] -= Diff[iVar];
+ }
+
+ }
+ }
+
+ /*--- Store the components to be communicated in the buffer. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = Und_Lapl[iVar];
+
+ /*--- Rotate the momentum components of the Laplacian. ---*/
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Und_Lapl[1] +
+ rotMatrix[0][1]*Und_Lapl[2]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Und_Lapl[1] +
+ rotMatrix[1][1]*Und_Lapl[2]);
+ }
+ else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Und_Lapl[1] +
+ rotMatrix[0][1]*Und_Lapl[2] +
+ rotMatrix[0][2]*Und_Lapl[3]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Und_Lapl[1] +
+ rotMatrix[1][1]*Und_Lapl[2] +
+ rotMatrix[1][2]*Und_Lapl[3]);
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*Und_Lapl[1] +
+ rotMatrix[2][1]*Und_Lapl[2] +
+ rotMatrix[2][2]*Und_Lapl[3]);
+ }
+ }
+
+ break;
+
+ case PERIODIC_MAX_EIG:
+
+ /*--- Simple summation of eig calc on both periodic faces. ---*/
+
+ bufDSend[buf_offset] = node[iPoint]->GetLambda();
+
+ break;
+
+ case PERIODIC_SENSOR:
+
+ /*--- For the centered schemes, the sensor must be computed
+ consistently using info from the entire control volume
+ on both sides of the periodic face. ---*/
+
+ Sensor_i = 0.0; Sensor_j = 0.0;
+ for (iNeighbor = 0; iNeighbor < geometry->node[iPoint]->GetnPoint(); iNeighbor++) {
+ jPoint = geometry->node[iPoint]->GetPoint(iNeighbor);
+
+ /*--- Avoid halos and boundary points so that we don't
+ duplicate edges on both sides of the periodic BC. ---*/
+
+ if (!geometry->node[jPoint]->GetPeriodicBoundary()) {
+
+ /*--- Use density instead of pressure for incomp. flows. ---*/
+
+ if ((config->GetKind_Regime() == INCOMPRESSIBLE)) {
+ Pressure_i = node[iPoint]->GetDensity();
+ Pressure_j = node[jPoint]->GetDensity();
+ } else {
+ Pressure_i = node[iPoint]->GetPressure();
+ Pressure_j = node[jPoint]->GetPressure();
+ }
+
+ boundary_i = geometry->node[iPoint]->GetPhysicalBoundary();
+ boundary_j = geometry->node[jPoint]->GetPhysicalBoundary();
+
+ /*--- Both points inside domain, or both on boundary ---*/
+
+ if ((!boundary_i && !boundary_j) ||
+ (boundary_i && boundary_j)) {
+ if (geometry->node[iPoint]->GetDomain()) {
+ Sensor_i += Pressure_j - Pressure_i;
+ Sensor_j += Pressure_i + Pressure_j;
+ }
+ }
+
+ /*--- iPoint inside the domain, jPoint on the boundary ---*/
+
+ if (!boundary_i && boundary_j) {
+ if (geometry->node[iPoint]->GetDomain()) {
+ Sensor_i += (Pressure_j - Pressure_i);
+ Sensor_j += (Pressure_i + Pressure_j);
+
+ }
+ }
+
+ }
+ }
+
+ /*--- Store the sensor increments to buffer. After summing
+ all contributions, these will be divided. ---*/
+
+ bufDSend[buf_offset] = Sensor_i;
+ buf_offset++;
+ bufDSend[buf_offset] = Sensor_j;
+
+ break;
+
+ case PERIODIC_SOL_GG:
+
+ /*--- Access and rotate the partial G-G gradient. These will be
+ summed on both sides of the periodic faces before dividing
+ by the volume to complete the Green-Gauss gradient calc. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ jacBlock[iVar][iDim] = node[iPoint]->GetGradient(iVar, iDim);
+ rotBlock[iVar][iDim] = node[iPoint]->GetGradient(iVar, iDim);
+ }
+ }
+
+ /*--- Rotate the gradients in x,y,z space for all variables. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ if (nDim == 2) {
+ rotBlock[iVar][0] = (rotMatrix[0][0]*jacBlock[iVar][0] +
+ rotMatrix[0][1]*jacBlock[iVar][1]);
+ rotBlock[iVar][1] = (rotMatrix[1][0]*jacBlock[iVar][0] +
+ rotMatrix[1][1]*jacBlock[iVar][1]);
+ } else {
+
+ rotBlock[iVar][0] = (rotMatrix[0][0]*jacBlock[iVar][0] +
+ rotMatrix[0][1]*jacBlock[iVar][1] +
+ rotMatrix[0][2]*jacBlock[iVar][2]);
+ rotBlock[iVar][1] = (rotMatrix[1][0]*jacBlock[iVar][0] +
+ rotMatrix[1][1]*jacBlock[iVar][1] +
+ rotMatrix[1][2]*jacBlock[iVar][2]);
+ rotBlock[iVar][2] = (rotMatrix[2][0]*jacBlock[iVar][0] +
+ rotMatrix[2][1]*jacBlock[iVar][1] +
+ rotMatrix[2][2]*jacBlock[iVar][2]);
+ }
+ }
+
+ /*--- Store the partial gradient in the buffer. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset+iVar*nDim+iDim] = rotBlock[iVar][iDim];
+ }
+ }
+
+ break;
+
+ case PERIODIC_PRIM_GG:
+
+ /*--- Access and rotate the partial G-G gradient. These will be
+ summed on both sides of the periodic faces before dividing
+ by the volume to complete the Green-Gauss gradient calc. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++){
+ jacBlock[iVar][iDim] = node[iPoint]->GetGradient_Primitive(iVar, iDim);
+ rotBlock[iVar][iDim] = node[iPoint]->GetGradient_Primitive(iVar, iDim);
+ }
+ }
+
+ /*--- Rotate the partial gradients in space for all variables. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ if (nDim == 2) {
+ rotBlock[iVar][0] = (rotMatrix[0][0]*jacBlock[iVar][0] +
+ rotMatrix[0][1]*jacBlock[iVar][1]);
+ rotBlock[iVar][1] = (rotMatrix[1][0]*jacBlock[iVar][0] +
+ rotMatrix[1][1]*jacBlock[iVar][1]);
+ } else {
+ rotBlock[iVar][0] = (rotMatrix[0][0]*jacBlock[iVar][0] +
+ rotMatrix[0][1]*jacBlock[iVar][1] +
+ rotMatrix[0][2]*jacBlock[iVar][2]);
+ rotBlock[iVar][1] = (rotMatrix[1][0]*jacBlock[iVar][0] +
+ rotMatrix[1][1]*jacBlock[iVar][1] +
+ rotMatrix[1][2]*jacBlock[iVar][2]);
+ rotBlock[iVar][2] = (rotMatrix[2][0]*jacBlock[iVar][0] +
+ rotMatrix[2][1]*jacBlock[iVar][1] +
+ rotMatrix[2][2]*jacBlock[iVar][2]);
+ }
+ }
+
+ /*--- Store the partial gradient in the buffer. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset+iVar*nDim+iDim] = rotBlock[iVar][iDim];
+ }
+ }
+
+ break;
+
+ case PERIODIC_SOL_LS:
+
+ /*--- For L-S gradient calculations with rotational periodicity,
+ we will need to rotate the x,y,z components. To make the process
+ easier, we choose to rotate the initial periodic point and their
+ neighbor points into their location on the donor marker before
+ computing the terms that we need to communicate. ---*/
+
+ /*--- Get coordinates for the current point. ---*/
+
+ Coord_i = geometry->node[iPoint]->GetCoord();
+
+ /*--- Get the position vector from rotation center to point. ---*/
+
+ dx = Coord_i[0] - center[0];
+ dy = Coord_i[1] - center[1];
+ if (nDim == 3) dz = Coord_i[2] - center[2];
+ else dz = 0.0;
+
+ /*--- Compute transformed point coordinates. ---*/
+
+ rotCoord_i[0] = (rotMatrix[0][0]*dx +
+ rotMatrix[0][1]*dy +
+ rotMatrix[0][2]*dz + translation[0]);
+
+ rotCoord_i[1] = (rotMatrix[1][0]*dx +
+ rotMatrix[1][1]*dy +
+ rotMatrix[1][2]*dz + translation[1]);
+
+ rotCoord_i[2] = (rotMatrix[2][0]*dx +
+ rotMatrix[2][1]*dy +
+ rotMatrix[2][2]*dz + translation[2]);
+
+ /*--- Get conservative solution and rotate if necessary. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ rotPrim_i[iVar] = node[iPoint]->GetSolution(iVar);
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ rotPrim_i[1] = (rotMatrix[0][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[iPoint]->GetSolution(2));
+ rotPrim_i[2] = (rotMatrix[1][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[iPoint]->GetSolution(2));
+ }
+ else {
+ rotPrim_i[1] = (rotMatrix[0][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[0][2]*node[iPoint]->GetSolution(3));
+ rotPrim_i[2] = (rotMatrix[1][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[1][2]*node[iPoint]->GetSolution(3));
+ rotPrim_i[3] = (rotMatrix[2][0]*node[iPoint]->GetSolution(1) +
+ rotMatrix[2][1]*node[iPoint]->GetSolution(2) +
+ rotMatrix[2][2]*node[iPoint]->GetSolution(3));
+ }
+ }
+
+ /*--- Inizialization of variables ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ Cvector[iVar][iDim] = 0.0;
+
+ r11 = 0.0; r12 = 0.0; r22 = 0.0;
+ r13 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+
+ for (iNeighbor = 0; iNeighbor < geometry->node[iPoint]->GetnPoint(); iNeighbor++) {
+ jPoint = geometry->node[iPoint]->GetPoint(iNeighbor);
+
+ /*--- Avoid periodic boundary points so that we do not
+ duplicate edges on both sides of the periodic BC. ---*/
+
+ if (!geometry->node[jPoint]->GetPeriodicBoundary()) {
+
+ /*--- Get coordinates for the neighbor point. ---*/
+
+ Coord_j = geometry->node[jPoint]->GetCoord();
+
+ /*--- Get the position vector from rotation center. ---*/
+
+ dx = Coord_j[0] - center[0];
+ dy = Coord_j[1] - center[1];
+ if (nDim == 3) dz = Coord_j[2] - center[2];
+ else dz = 0.0;
+
+ /*--- Compute transformed point coordinates. ---*/
+
+ rotCoord_j[0] = (rotMatrix[0][0]*dx +
+ rotMatrix[0][1]*dy +
+ rotMatrix[0][2]*dz + translation[0]);
+
+ rotCoord_j[1] = (rotMatrix[1][0]*dx +
+ rotMatrix[1][1]*dy +
+ rotMatrix[1][2]*dz + translation[1]);
+
+ rotCoord_j[2] = (rotMatrix[2][0]*dx +
+ rotMatrix[2][1]*dy +
+ rotMatrix[2][2]*dz + translation[2]);
+
+ /*--- Get conservative solution and rotte if necessary. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ rotPrim_j[iVar] = node[jPoint]->GetSolution(iVar);
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ rotPrim_j[1] = (rotMatrix[0][0]*node[jPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[jPoint]->GetSolution(2));
+ rotPrim_j[2] = (rotMatrix[1][0]*node[jPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[jPoint]->GetSolution(2));
+ }
+ else {
+ rotPrim_j[1] = (rotMatrix[0][0]*node[jPoint]->GetSolution(1) +
+ rotMatrix[0][1]*node[jPoint]->GetSolution(2) +
+ rotMatrix[0][2]*node[jPoint]->GetSolution(3));
+ rotPrim_j[2] = (rotMatrix[1][0]*node[jPoint]->GetSolution(1) +
+ rotMatrix[1][1]*node[jPoint]->GetSolution(2) +
+ rotMatrix[1][2]*node[jPoint]->GetSolution(3));
+ rotPrim_j[3] = (rotMatrix[2][0]*node[jPoint]->GetSolution(1) +
+ rotMatrix[2][1]*node[jPoint]->GetSolution(2) +
+ rotMatrix[2][2]*node[jPoint]->GetSolution(3));
+ }
+ }
+
+ weight = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++) {
+ weight += ((rotCoord_j[iDim]-rotCoord_i[iDim])*
+ (rotCoord_j[iDim]-rotCoord_i[iDim]));
+ }
+
+ /*--- Sumations for entries of upper triangular matrix R ---*/
+
+ if (weight != 0.0) {
+
+ r11 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[0]-rotCoord_i[0])/weight);
+ r12 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[1]-rotCoord_i[1])/weight);
+ r22 += ((rotCoord_j[1]-rotCoord_i[1])*
+ (rotCoord_j[1]-rotCoord_i[1])/weight);
+
+ if (nDim == 3) {
+ r13 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r23_a += ((rotCoord_j[1]-rotCoord_i[1])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r23_b += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r33 += ((rotCoord_j[2]-rotCoord_i[2])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ }
+
+ /*--- Entries of c:= transpose(A)*b ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ Cvector[iVar][iDim] += ((rotCoord_j[iDim]-rotCoord_i[iDim])*
+ (rotPrim_j[iVar]-rotPrim_i[iVar])/weight);
+
+ }
+ }
+ }
+
+ /*--- We store and communicate the increments for the matching
+ upper triangular matrix (weights) and the r.h.s. vector.
+ These will be accumulated before completing the L-S gradient
+ calculation for each periodic point. ---*/
+
+ if (nDim == 2) {
+ bufDSend[buf_offset] = r11; buf_offset++;
+ bufDSend[buf_offset] = r12; buf_offset++;
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r22; buf_offset++;
+ }
+ if (nDim == 3) {
+ bufDSend[buf_offset] = r11; buf_offset++;
+ bufDSend[buf_offset] = r12; buf_offset++;
+ bufDSend[buf_offset] = r13; buf_offset++;
+
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r22; buf_offset++;
+ bufDSend[buf_offset] = r23_a; buf_offset++;
+
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r23_b; buf_offset++;
+ bufDSend[buf_offset] = r33; buf_offset++;
+ }
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset] = Cvector[iVar][iDim];
+ buf_offset++;
+ }
+ }
+
+ break;
+
+ case PERIODIC_PRIM_LS:
+
+ /*--- For L-S gradient calculations with rotational periodicity,
+ we will need to rotate the x,y,z components. To make the process
+ easier, we choose to rotate the initial periodic point and their
+ neighbor points into their location on the donor marker before
+ computing the terms that we need to communicate. ---*/
+
+ /*--- Get coordinates ---*/
+
+ Coord_i = geometry->node[iPoint]->GetCoord();
+
+ /*--- Get the position vector from rot center to point. ---*/
+
+ dx = Coord_i[0] - center[0];
+ dy = Coord_i[1] - center[1];
+ if (nDim == 3) dz = Coord_i[2] - center[2];
+ else dz = 0.0;
+
+ /*--- Compute transformed point coordinates. ---*/
+
+ rotCoord_i[0] = (rotMatrix[0][0]*dx +
+ rotMatrix[0][1]*dy +
+ rotMatrix[0][2]*dz + translation[0]);
+
+ rotCoord_i[1] = (rotMatrix[1][0]*dx +
+ rotMatrix[1][1]*dy +
+ rotMatrix[1][2]*dz + translation[1]);
+
+ rotCoord_i[2] = (rotMatrix[2][0]*dx +
+ rotMatrix[2][1]*dy +
+ rotMatrix[2][2]*dz + translation[2]);
+
+ /*--- Get primitives and rotate if necessary. ---*/
+
+ for (iVar = 0; iVar < nPrimVar; iVar++)
+ rotPrim_i[iVar] = node[iPoint]->GetPrimitive(iVar);
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ rotPrim_i[1] = (rotMatrix[0][0]*node[iPoint]->GetPrimitive(1) +
+ rotMatrix[0][1]*node[iPoint]->GetPrimitive(2));
+ rotPrim_i[2] = (rotMatrix[1][0]*node[iPoint]->GetPrimitive(1) +
+ rotMatrix[1][1]*node[iPoint]->GetPrimitive(2));
+ }
+ else {
+ rotPrim_i[1] = (rotMatrix[0][0]*node[iPoint]->GetPrimitive(1) +
+ rotMatrix[0][1]*node[iPoint]->GetPrimitive(2) +
+ rotMatrix[0][2]*node[iPoint]->GetPrimitive(3));
+ rotPrim_i[2] = (rotMatrix[1][0]*node[iPoint]->GetPrimitive(1) +
+ rotMatrix[1][1]*node[iPoint]->GetPrimitive(2) +
+ rotMatrix[1][2]*node[iPoint]->GetPrimitive(3));
+ rotPrim_i[3] = (rotMatrix[2][0]*node[iPoint]->GetPrimitive(1) +
+ rotMatrix[2][1]*node[iPoint]->GetPrimitive(2) +
+ rotMatrix[2][2]*node[iPoint]->GetPrimitive(3));
+ }
+ }
+
+ /*--- Inizialization of variables ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ Cvector[iVar][iDim] = 0.0;
+
+ r11 = 0.0; r12 = 0.0; r22 = 0.0;
+ r13 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+
+ for (iNeighbor = 0; iNeighbor < geometry->node[iPoint]->GetnPoint(); iNeighbor++) {
+ jPoint = geometry->node[iPoint]->GetPoint(iNeighbor);
+
+ /*--- Avoid periodic boundary points so that we do not
+ duplicate edges on both sides of the periodic BC. ---*/
+
+ if (!geometry->node[jPoint]->GetPeriodicBoundary()) {
+
+ /*--- Get coordinates for the neighbor point. ---*/
+
+ Coord_j = geometry->node[jPoint]->GetCoord();
+
+ /*--- Get the position vector from rotation center. ---*/
+
+ dx = Coord_j[0] - center[0];
+ dy = Coord_j[1] - center[1];
+ if (nDim == 3) dz = Coord_j[2] - center[2];
+ else dz = 0.0;
+
+ /*--- Compute transformed point coordinates. ---*/
+
+ rotCoord_j[0] = (rotMatrix[0][0]*dx +
+ rotMatrix[0][1]*dy +
+ rotMatrix[0][2]*dz + translation[0]);
+
+ rotCoord_j[1] = (rotMatrix[1][0]*dx +
+ rotMatrix[1][1]*dy +
+ rotMatrix[1][2]*dz + translation[1]);
+
+ rotCoord_j[2] = (rotMatrix[2][0]*dx +
+ rotMatrix[2][1]*dy +
+ rotMatrix[2][2]*dz + translation[2]);
+
+ /*--- Get primitives from CVariable ---*/
+
+ for (iVar = 0; iVar < nPrimVar; iVar++)
+ rotPrim_j[iVar] = node[jPoint]->GetPrimitive(iVar);
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ rotPrim_j[1] = (rotMatrix[0][0]*node[jPoint]->GetPrimitive(1) +
+ rotMatrix[0][1]*node[jPoint]->GetPrimitive(2));
+ rotPrim_j[2] = (rotMatrix[1][0]*node[jPoint]->GetPrimitive(1) +
+ rotMatrix[1][1]*node[jPoint]->GetPrimitive(2));
+ }
+ else {
+ rotPrim_j[1] = (rotMatrix[0][0]*node[jPoint]->GetPrimitive(1) +
+ rotMatrix[0][1]*node[jPoint]->GetPrimitive(2) +
+ rotMatrix[0][2]*node[jPoint]->GetPrimitive(3));
+ rotPrim_j[2] = (rotMatrix[1][0]*node[jPoint]->GetPrimitive(1) +
+ rotMatrix[1][1]*node[jPoint]->GetPrimitive(2) +
+ rotMatrix[1][2]*node[jPoint]->GetPrimitive(3));
+ rotPrim_j[3] = (rotMatrix[2][0]*node[jPoint]->GetPrimitive(1) +
+ rotMatrix[2][1]*node[jPoint]->GetPrimitive(2) +
+ rotMatrix[2][2]*node[jPoint]->GetPrimitive(3));
+ }
+ }
+
+ weight = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++)
+ weight += ((rotCoord_j[iDim]-rotCoord_i[iDim])*
+ (rotCoord_j[iDim]-rotCoord_i[iDim]));
+
+ /*--- Sumations for entries of upper triangular matrix R ---*/
+
+ if (weight != 0.0) {
+
+ r11 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[0]-rotCoord_i[0])/weight);
+ r12 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[1]-rotCoord_i[1])/weight);
+ r22 += ((rotCoord_j[1]-rotCoord_i[1])*
+ (rotCoord_j[1]-rotCoord_i[1])/weight);
+
+ if (nDim == 3) {
+ r13 += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r23_a += ((rotCoord_j[1]-rotCoord_i[1])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r23_b += ((rotCoord_j[0]-rotCoord_i[0])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ r33 += ((rotCoord_j[2]-rotCoord_i[2])*
+ (rotCoord_j[2]-rotCoord_i[2])/weight);
+ }
+
+ /*--- Entries of c:= transpose(A)*b ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ Cvector[iVar][iDim] += ((rotCoord_j[iDim]-rotCoord_i[iDim])*
+ (rotPrim_j[iVar]-rotPrim_i[iVar])/weight);
+
+ }
+ }
+ }
+
+ /*--- We store and communicate the increments for the matching
+ upper triangular matrix (weights) and the r.h.s. vector.
+ These will be accumulated before completing the L-S gradient
+ calculation for each periodic point. ---*/
+
+ if (nDim == 2) {
+ bufDSend[buf_offset] = r11; buf_offset++;
+ bufDSend[buf_offset] = r12; buf_offset++;
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r22; buf_offset++;
+ }
+ if (nDim == 3) {
+ bufDSend[buf_offset] = r11; buf_offset++;
+ bufDSend[buf_offset] = r12; buf_offset++;
+ bufDSend[buf_offset] = r13; buf_offset++;
+
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r22; buf_offset++;
+ bufDSend[buf_offset] = r23_a; buf_offset++;
+
+ bufDSend[buf_offset] = 0.0; buf_offset++;
+ bufDSend[buf_offset] = r23_b; buf_offset++;
+ bufDSend[buf_offset] = r33; buf_offset++;
+ }
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ bufDSend[buf_offset] = Cvector[iVar][iDim];
+ buf_offset++;
+ }
+ }
+
+ break;
+
+ case PERIODIC_LIM_PRIM_1:
+
+ /*--- The first phase of the periodic limiter calculation
+ ensures that the proper min and max of the solution are found
+ among all nodes adjacent to periodic faces. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ Sol_Min[iVar] = node[iPoint]->GetSolution_Min(iVar);
+ Sol_Max[iVar] = node[iPoint]->GetSolution_Max(iVar);
+
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_Min(iVar);
+ bufDSend[buf_offset+nPrimVarGrad+iVar] = node[iPoint]->GetSolution_Max(iVar);
+ }
+
+ /*--- Rotate the momentum components of the min/max. ---*/
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Sol_Min[1] +
+ rotMatrix[0][1]*Sol_Min[2]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Sol_Min[1] +
+ rotMatrix[1][1]*Sol_Min[2]);
+
+ bufDSend[buf_offset+nPrimVarGrad+1] = (rotMatrix[0][0]*Sol_Max[1] +
+ rotMatrix[0][1]*Sol_Max[2]);
+ bufDSend[buf_offset+nPrimVarGrad+2] = (rotMatrix[1][0]*Sol_Max[1] +
+ rotMatrix[1][1]*Sol_Max[2]);
+
+ } else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Sol_Min[1] +
+ rotMatrix[0][1]*Sol_Min[2] +
+ rotMatrix[0][2]*Sol_Min[3]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Sol_Min[1] +
+ rotMatrix[1][1]*Sol_Min[2] +
+ rotMatrix[1][2]*Sol_Min[3]);
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*Sol_Min[1] +
+ rotMatrix[2][1]*Sol_Min[2] +
+ rotMatrix[2][2]*Sol_Min[3]);
+
+ bufDSend[buf_offset+nPrimVarGrad+1] = (rotMatrix[0][0]*Sol_Max[1] +
+ rotMatrix[0][1]*Sol_Max[2] +
+ rotMatrix[0][2]*Sol_Max[3]);
+ bufDSend[buf_offset+nPrimVarGrad+2] = (rotMatrix[1][0]*Sol_Max[1] +
+ rotMatrix[1][1]*Sol_Max[2] +
+ rotMatrix[1][2]*Sol_Max[3]);
+ bufDSend[buf_offset+nPrimVarGrad+3] = (rotMatrix[2][0]*Sol_Max[1] +
+ rotMatrix[2][1]*Sol_Max[2] +
+ rotMatrix[2][2]*Sol_Max[3]);
+ }
+ }
+
+ break;
+
+ case PERIODIC_LIM_PRIM_2:
+
+ /*--- The second phase of the periodic limiter calculation
+ ensures that the correct minimum value of the limiter is
+ found for a node on a periodic face and stores it. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetLimiter_Primitive(iVar);
+ }
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetLimiter_Primitive(1) +
+ rotMatrix[0][1]*node[iPoint]->GetLimiter_Primitive(2));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetLimiter_Primitive(1) +
+ rotMatrix[1][1]*node[iPoint]->GetLimiter_Primitive(2));
+
+ }
+ else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetLimiter_Primitive(1) +
+ rotMatrix[0][1]*node[iPoint]->GetLimiter_Primitive(2) +
+ rotMatrix[0][2]*node[iPoint]->GetLimiter_Primitive(3));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetLimiter_Primitive(1) +
+ rotMatrix[1][1]*node[iPoint]->GetLimiter_Primitive(2) +
+ rotMatrix[1][2]*node[iPoint]->GetLimiter_Primitive(3));
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*node[iPoint]->GetLimiter_Primitive(1) +
+ rotMatrix[2][1]*node[iPoint]->GetLimiter_Primitive(2) +
+ rotMatrix[2][2]*node[iPoint]->GetLimiter_Primitive(3));
+ }
+ }
+
+ break;
+
+ case PERIODIC_LIM_SOL_1:
+
+ /*--- The first phase of the periodic limiter calculation
+ ensures that the proper min and max of the solution are found
+ among all nodes adjacent to periodic faces. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ Sol_Min[iVar] = node[iPoint]->GetSolution_Min(iVar);
+ Sol_Max[iVar] = node[iPoint]->GetSolution_Max(iVar);
+
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_Min(iVar);
+ bufDSend[buf_offset+nVar+iVar] = node[iPoint]->GetSolution_Max(iVar);
+ }
+
+ /*--- Rotate the momentum components of the min/max. ---*/
+
+ if (rotate_periodic) {
+
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Sol_Min[1] +
+ rotMatrix[0][1]*Sol_Min[2]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Sol_Min[1] +
+ rotMatrix[1][1]*Sol_Min[2]);
+
+ bufDSend[buf_offset+nVar+1] = (rotMatrix[0][0]*Sol_Max[1] +
+ rotMatrix[0][1]*Sol_Max[2]);
+ bufDSend[buf_offset+nVar+2] = (rotMatrix[1][0]*Sol_Max[1] +
+ rotMatrix[1][1]*Sol_Max[2]);
+
+ }
+ else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*Sol_Min[1] +
+ rotMatrix[0][1]*Sol_Min[2] +
+ rotMatrix[0][2]*Sol_Min[3]);
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*Sol_Min[1] +
+ rotMatrix[1][1]*Sol_Min[2] +
+ rotMatrix[1][2]*Sol_Min[3]);
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*Sol_Min[1] +
+ rotMatrix[2][1]*Sol_Min[2] +
+ rotMatrix[2][2]*Sol_Min[3]);
+
+ bufDSend[buf_offset+nVar+1] = (rotMatrix[0][0]*Sol_Max[1] +
+ rotMatrix[0][1]*Sol_Max[2] +
+ rotMatrix[0][2]*Sol_Max[3]);
+ bufDSend[buf_offset+nVar+2] = (rotMatrix[1][0]*Sol_Max[1] +
+ rotMatrix[1][1]*Sol_Max[2] +
+ rotMatrix[1][2]*Sol_Max[3]);
+ bufDSend[buf_offset+nVar+3] = (rotMatrix[2][0]*Sol_Max[1] +
+ rotMatrix[2][1]*Sol_Max[2] +
+ rotMatrix[2][2]*Sol_Max[3]);
+
+ }
+ }
+
+ break;
+
+ case PERIODIC_LIM_SOL_2:
+
+ /*--- The second phase of the periodic limiter calculation
+ ensures that the correct minimum value of the limiter is
+ found for a node on a periodic face and stores it. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetLimiter(iVar);
+ }
+
+ if (rotate_periodic) {
+ if (nDim == 2) {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetLimiter(1) +
+ rotMatrix[0][1]*node[iPoint]->GetLimiter(2));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetLimiter(1) +
+ rotMatrix[1][1]*node[iPoint]->GetLimiter(2));
+
+ }
+ else {
+ bufDSend[buf_offset+1] = (rotMatrix[0][0]*node[iPoint]->GetLimiter(1) +
+ rotMatrix[0][1]*node[iPoint]->GetLimiter(2) +
+ rotMatrix[0][2]*node[iPoint]->GetLimiter(3));
+ bufDSend[buf_offset+2] = (rotMatrix[1][0]*node[iPoint]->GetLimiter(1) +
+ rotMatrix[1][1]*node[iPoint]->GetLimiter(2) +
+ rotMatrix[1][2]*node[iPoint]->GetLimiter(3));
+ bufDSend[buf_offset+3] = (rotMatrix[2][0]*node[iPoint]->GetLimiter(1) +
+ rotMatrix[2][1]*node[iPoint]->GetLimiter(2) +
+ rotMatrix[2][2]*node[iPoint]->GetLimiter(3));
+ }
+ }
+
+ break;
+
+ default:
+ SU2_MPI::Error("Unrecognized quantity for periodic communication.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+
+ /*--- Launch the point-to-point MPI send for this message. ---*/
+
+ geometry->PostPeriodicSends(geometry, config, MPI_TYPE, iMessage);
+
+ }
+ }
+
+ delete [] Diff;
+ delete [] Und_Lapl;
+ delete [] Sol_Min;
+ delete [] Sol_Max;
+ delete [] rotPrim_i;
+ delete [] rotPrim_j;
+
+ for (iVar = 0; iVar < ICOUNT; iVar++) {
+ delete [] jacBlock[iVar];
+ delete [] rotBlock[iVar];
+ }
+ delete [] jacBlock;
+ delete [] rotBlock;
+
+}
+
+void CSolver::CompletePeriodicComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short val_periodic_index,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short nPeriodic = config->GetnMarker_Periodic();
+ unsigned short iDim, jDim, iVar, jVar, iPeriodic, nNeighbor;
+
+ unsigned long iPoint, iRecv, nRecv, offset, buf_offset, total_index;
+
+ int source, iMessage, jRecv;
+
+ SU2_MPI::Status status;
+
+ su2double *Diff = new su2double[nVar];
+
+ su2double Time_Step, Volume, Solution_Min, Solution_Max, Limiter_Min;
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDRecv = geometry->bufD_PeriodicRecv;
+
+ unsigned short *bufSRecv = geometry->bufS_PeriodicRecv;
+
+ /*--- Store the data that was communicated into the appropriate
+ location within the local class data structures. ---*/
+
+ if (geometry->nPeriodicRecv > 0) {
+
+ for (iMessage = 0; iMessage < geometry->nPeriodicRecv; iMessage++) {
+
+ /*--- For efficiency, recv the messages dynamically based on
+ the order they arrive. ---*/
+
+#ifdef HAVE_MPI
+ /*--- Once we have recv'd a message, get the source rank. ---*/
+ int ind;
+ SU2_MPI::Waitany(geometry->nPeriodicRecv,
+ geometry->req_PeriodicRecv,
+ &ind, &status);
+ source = status.MPI_SOURCE;
+#else
+ /*--- For serial calculations, we know the rank. ---*/
+ source = rank;
+#endif
+
+ /*--- We know the offsets based on the source rank. ---*/
+
+ jRecv = geometry->PeriodicRecv2Neighbor[source];
+
+ /*--- Get the point offset for the start of this message. ---*/
+
+ offset = geometry->nPoint_PeriodicRecv[jRecv];
+
+ /*--- Get the number of packets to be received in this message. ---*/
+
+ nRecv = (geometry->nPoint_PeriodicRecv[jRecv+1] -
+ geometry->nPoint_PeriodicRecv[jRecv]);
+
+ for (iRecv = 0; iRecv < nRecv; iRecv++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_PeriodicRecv[offset + iRecv];
+ iPeriodic = geometry->Local_Marker_PeriodicRecv[offset + iRecv];
+
+ /*--- While all periodic face data was accumulated, we only store
+ the values for the current pair of periodic faces. This is slightly
+ inefficient when we have multiple pairs of periodic faces, but
+ it simplifies the communications. ---*/
+
+ if ((iPeriodic == val_periodic_index) ||
+ (iPeriodic == val_periodic_index + nPeriodic/2)) {
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iRecv)*geometry->countPerPeriodicPoint;
+
+ /*--- Store the data correctly depending on the quantity. ---*/
+
+ switch (commType) {
+
+ case PERIODIC_VOLUME:
+
+ /*--- The periodic points need to keep track of their
+ total volume spread across the periodic faces. ---*/
+
+ Volume = (bufDRecv[buf_offset] +
+ geometry->node[iPoint]->GetPeriodicVolume());
+ geometry->node[iPoint]->SetPeriodicVolume(Volume);
+
+ break;
+
+ case PERIODIC_NEIGHBORS:
+
+ /*--- Store the extra neighbors on the periodic face. ---*/
+
+ nNeighbor = (geometry->node[iPoint]->GetnNeighbor() +
+ bufSRecv[buf_offset]);
+ geometry->node[iPoint]->SetnNeighbor(nNeighbor);
+
+ break;
+
+ case PERIODIC_RESIDUAL:
+
+ /*--- Access the residual from the donor. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ Residual[iVar] = bufDRecv[buf_offset];
+ buf_offset++;
+ }
+
+ /*--- Check the computed time step against the donor
+ value and keep the minimum in order to be conservative. ---*/
+
+ Time_Step = node[iPoint]->GetDelta_Time();
+ if (bufDRecv[buf_offset] < Time_Step)
+ node[iPoint]->SetDelta_Time(bufDRecv[buf_offset]);
+ buf_offset++;
+
+ /*--- Access the Jacobian from the donor if implicit. ---*/
+
+ if (implicit_periodic) {
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (jVar = 0; jVar < nVar; jVar++) {
+ Jacobian_i[iVar][jVar] = bufDRecv[buf_offset];
+ buf_offset++;
+ }
+ }
+ }
+
+ /*--- Add contributions to total residual. ---*/
+
+ LinSysRes.AddBlock(iPoint, Residual);
+
+ /*--- For implicit integration, we choose the first
+ periodic face of each pair to be the master/owner of
+ the solution for the linear system while fixing the
+ solution at the matching face during the solve. Here,
+ we remove the Jacobian and residual contributions from
+ the passive face such that it does not participate in
+ the linear solve. ---*/
+
+ if (implicit_periodic) {
+
+ Jacobian.AddBlock(iPoint, iPoint, Jacobian_i);
+
+ if (iPeriodic == val_periodic_index + nPeriodic/2) {
+ for (iVar = 0; iVar < nVar; iVar++) {
+ LinSysRes.SetBlock_Zero(iPoint, iVar);
+ total_index = iPoint*nVar+iVar;
+ Jacobian.DeleteValsRowi(total_index);
+ }
+ }
+
+ }
+
+ break;
+
+ case PERIODIC_IMPLICIT:
+
+ /*--- For implicit integration, we choose the first
+ periodic face of each pair to be the master/owner of
+ the solution for the linear system while fixing the
+ solution at the matching face during the solve. Here,
+ we are updating the solution at the passive nodes
+ using the new solution from the master. ---*/
+
+ if ((implicit_periodic) &&
+ (iPeriodic == val_periodic_index + nPeriodic/2)) {
+
+ /*--- Access the solution from the donor. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ Solution[iVar] = bufDRecv[buf_offset];
+ buf_offset++;
+ }
+
+ /*--- Directly set the solution on the passive periodic
+ face that is provided from the master. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ node[iPoint]->SetSolution(iVar, Solution[iVar]);
+ node[iPoint]->SetSolution_Old(iVar, Solution[iVar]);
+ }
+
+ }
+
+ break;
+
+ case PERIODIC_LAPLACIAN:
+
+ /*--- Adjust the undivided Laplacian. The accumulation was
+ with a subtraction before communicating, so now just add. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ Diff[iVar] = bufDRecv[buf_offset+iVar];
+
+ node[iPoint]->AddUnd_Lapl(Diff);
+
+ break;
+
+ case PERIODIC_MAX_EIG:
+
+ /*--- Simple accumulation of the max eig on periodic faces. ---*/
+
+ node[iPoint]->AddLambda(bufDRecv[buf_offset]);
+
+ break;
+
+ case PERIODIC_SENSOR:
+
+ /*--- Simple accumulation of the sensors on periodic faces. ---*/
+
+ iPoint_UndLapl[iPoint] += bufDRecv[buf_offset]; buf_offset++;
+ jPoint_UndLapl[iPoint] += bufDRecv[buf_offset];
+
+ break;
+
+ case PERIODIC_SOL_GG:
+
+ /*--- For G-G, we accumulate partial gradients then compute
+ the final value using the entire volume of the periodic cell. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetGradient(iVar, iDim, bufDRecv[buf_offset+iVar*nDim+iDim] + node[iPoint]->GetGradient(iVar, iDim));
+
+ break;
+
+ case PERIODIC_PRIM_GG:
+
+ /*--- For G-G, we accumulate partial gradients then compute
+ the final value using the entire volume of the periodic cell. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetGradient_Primitive(iVar, iDim, bufDRecv[buf_offset+iVar*nDim+iDim] + node[iPoint]->GetGradient_Primitive(iVar, iDim));
+ break;
+
+ case PERIODIC_SOL_LS:
+
+ /*--- For L-S, we build the upper triangular matrix and the
+ r.h.s. vector by accumulating from all periodic partial
+ control volumes. ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (jDim = 0; jDim < nDim; jDim++) {
+ node[iPoint]->AddRmatrix(iDim,jDim,bufDRecv[buf_offset]);
+ buf_offset++;
+ }
+ }
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->AddGradient(iVar, iDim, bufDRecv[buf_offset]);
+ buf_offset++;
+ }
+ }
+
+ break;
+
+ case PERIODIC_PRIM_LS:
+
+ /*--- For L-S, we build the upper triangular matrix and the
+ r.h.s. vector by accumulating from all periodic partial
+ control volumes. ---*/
+
+ for (iDim = 0; iDim < nDim; iDim++) {
+ for (jDim = 0; jDim < nDim; jDim++) {
+ node[iPoint]->AddRmatrix(iDim,jDim,bufDRecv[buf_offset]);
+ buf_offset++;
+ }
+ }
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->AddGradient_Primitive(iVar, iDim, bufDRecv[buf_offset]);
+ buf_offset++;
+ }
+ }
+
+ break;
+
+ case PERIODIC_LIM_PRIM_1:
+
+ /*--- Check the min and max values found on the matching
+ perioic faces for the solution, and store the proper min
+ and max for this point. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ node[iPoint]->SetSolution_Min(iVar, min(node[iPoint]->GetSolution_Min(iVar), bufDRecv[buf_offset+iVar]));
+ node[iPoint]->SetSolution_Max(iVar, max(node[iPoint]->GetSolution_Max(iVar), bufDRecv[buf_offset+nPrimVarGrad+iVar]));
+ }
+
+ break;
+
+ case PERIODIC_LIM_PRIM_2:
+
+ /*--- Check the min values found on the matching periodic
+ faces for the limiter, and store the proper min value. ---*/
+
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++) {
+ node[iPoint]->SetLimiter_Primitive(iVar, min(node[iPoint]->GetLimiter_Primitive(iVar), bufDRecv[buf_offset+iVar]));
+ }
+
+ break;
+
+ case PERIODIC_LIM_SOL_1:
+
+ /*--- Check the min and max values found on the matching
+ perioic faces for the solution, and store the proper min
+ and max for this point. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+
+ /*--- Solution minimum. ---*/
+
+ Solution_Min = min(node[iPoint]->GetSolution_Min(iVar),
+ bufDRecv[buf_offset+iVar]);
+ node[iPoint]->SetSolution_Min(iVar, Solution_Min);
+
+ /*--- Solution maximum. ---*/
+
+ Solution_Max = max(node[iPoint]->GetSolution_Max(iVar),
+ bufDRecv[buf_offset+nVar+iVar]);
+ node[iPoint]->SetSolution_Max(iVar, Solution_Max);
+
+ }
+
+ break;
+
+ case PERIODIC_LIM_SOL_2:
+
+ /*--- Check the min values found on the matching periodic
+ faces for the limiter, and store the proper min value. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ Limiter_Min = min(node[iPoint]->GetLimiter_Primitive(iVar),
+ bufDRecv[buf_offset+iVar]);
+ node[iPoint]->SetLimiter_Primitive(iVar, Limiter_Min);
+ }
+
+ break;
+
+ default:
+
+ SU2_MPI::Error("Unrecognized quantity for periodic communication.",
+ CURRENT_FUNCTION);
+ break;
+
+ }
+ }
+ }
+ }
+
+ /*--- Verify that all non-blocking point-to-point sends have finished.
+ Note that this should be satisfied, as we have received all of the
+ data in the loop above at this point. ---*/
+
+#ifdef HAVE_MPI
+ SU2_MPI::Waitall(geometry->nPeriodicSend,
+ geometry->req_PeriodicSend,
+ MPI_STATUS_IGNORE);
+#endif
+
+ }
+
+ delete [] Diff;
+
+}
+
+void CSolver::InitiateComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iVar, iDim;
+ unsigned short COUNT_PER_POINT = 0;
+ unsigned short MPI_TYPE = 0;
+
+ unsigned long iPoint, offset, buf_offset;
+
+ int iMessage, iSend, nSend;
+
+ /*--- Set the size of the data packet and type depending on quantity. ---*/
+
+ switch (commType) {
+ case SOLUTION:
+ case SOLUTION_OLD:
+ case UNDIVIDED_LAPLACIAN:
+ case SOLUTION_LIMITER:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case MAX_EIGENVALUE:
+ case SENSOR:
+ COUNT_PER_POINT = 1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_GRADIENT:
+ COUNT_PER_POINT = nVar*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PRIMITIVE_GRADIENT:
+ COUNT_PER_POINT = nPrimVarGrad*nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case PRIMITIVE_LIMITER:
+ COUNT_PER_POINT = nPrimVarGrad;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_EDDY:
+ COUNT_PER_POINT = nVar+1;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_FEA:
+ if (config->GetDynamic_Analysis() == DYNAMIC)
+ COUNT_PER_POINT = nVar*3;
+ else
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_FEA_OLD:
+ COUNT_PER_POINT = nVar*3;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_DISPONLY:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_PRED:
+ COUNT_PER_POINT = nVar;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case SOLUTION_PRED_OLD:
+ COUNT_PER_POINT = nVar*3;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ case AUXVAR_GRADIENT:
+ COUNT_PER_POINT = nDim;
+ MPI_TYPE = COMM_TYPE_DOUBLE;
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+
+ /*--- Check to make sure we have created a large enough buffer
+ for these comms during preprocessing. This is only for the su2double
+ buffer. It will be reallocated whenever we find a larger count
+ per point. After the first cycle of comms, this should be inactive. ---*/
+
+ if (COUNT_PER_POINT > geometry->countPerPoint) {
+ geometry->AllocateP2PComms(COUNT_PER_POINT);
+ }
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDSend = geometry->bufD_P2PSend;
+
+ /*--- Load the specified quantity from the solver into the generic
+ communication buffer in the geometry class. ---*/
+
+ if (geometry->nP2PSend > 0) {
+
+ /*--- Post all non-blocking recvs first before sends. ---*/
+
+ geometry->PostP2PRecvs(geometry, config, MPI_TYPE, false);
+
+ for (iMessage = 0; iMessage < geometry->nP2PSend; iMessage++) {
+
+ /*--- Compute our location in the send buffer. ---*/
+
+ offset = geometry->nPoint_P2PSend[iMessage];
+
+ /*--- Total count can include multiple pieces of data per element. ---*/
+
+ nSend = (geometry->nPoint_P2PSend[iMessage+1] -
+ geometry->nPoint_P2PSend[iMessage]);
+
+ for (iSend = 0; iSend < nSend; iSend++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PSend[offset + iSend];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iSend)*geometry->countPerPoint;
+
+ switch (commType) {
+ case SOLUTION:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution(iVar);
+ break;
+ case SOLUTION_OLD:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_Old(iVar);
+ break;
+ case SOLUTION_EDDY:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution(iVar);
+ bufDSend[buf_offset+nVar] = node[iPoint]->GetmuT();
+ break;
+ case UNDIVIDED_LAPLACIAN:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetUndivided_Laplacian(iVar);
+ break;
+ case SOLUTION_LIMITER:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetLimiter(iVar);
+ break;
+ case MAX_EIGENVALUE:
+ bufDSend[buf_offset] = node[iPoint]->GetLambda();
+ break;
+ case SENSOR:
+ bufDSend[buf_offset] = node[iPoint]->GetSensor();
+ break;
+ case SOLUTION_GRADIENT:
+ for (iVar = 0; iVar < nVar; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ bufDSend[buf_offset+iVar*nDim+iDim] = node[iPoint]->GetGradient(iVar, iDim);
+ break;
+ case PRIMITIVE_GRADIENT:
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ bufDSend[buf_offset+iVar*nDim+iDim] = node[iPoint]->GetGradient_Primitive(iVar, iDim);
+ break;
+ case PRIMITIVE_LIMITER:
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetLimiter_Primitive(iVar);
+ break;
+ case AUXVAR_GRADIENT:
+ for (iDim = 0; iDim < nDim; iDim++)
+ bufDSend[buf_offset+iDim] = node[iPoint]->GetAuxVarGradient(iDim);
+ break;
+ case SOLUTION_FEA:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution(iVar);
+ if (config->GetDynamic_Analysis() == DYNAMIC) {
+ bufDSend[buf_offset+nVar+iVar] = node[iPoint]->GetSolution_Vel(iVar);
+ bufDSend[buf_offset+nVar*2+iVar] = node[iPoint]->GetSolution_Accel(iVar);
+ }
+ }
+ break;
+ case SOLUTION_FEA_OLD:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_time_n(iVar);
+ bufDSend[buf_offset+nVar+iVar] = node[iPoint]->GetSolution_Vel_time_n(iVar);
+ bufDSend[buf_offset+nVar*2+iVar] = node[iPoint]->GetSolution_Accel_time_n(iVar);
+ }
+ break;
+ case SOLUTION_DISPONLY:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution(iVar);
+ break;
+ case SOLUTION_PRED:
+ for (iVar = 0; iVar < nVar; iVar++)
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_Pred(iVar);
+ break;
+ case SOLUTION_PRED_OLD:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ bufDSend[buf_offset+iVar] = node[iPoint]->GetSolution_Old(iVar);
+ bufDSend[buf_offset+nVar+iVar] = node[iPoint]->GetSolution_Pred(iVar);
+ bufDSend[buf_offset+nVar*2+iVar] = node[iPoint]->GetSolution_Pred_Old(iVar);
+ }
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+
+ /*--- Launch the point-to-point MPI send for this message. ---*/
+
+ geometry->PostP2PSends(geometry, config, MPI_TYPE, iMessage, false);
+
+ }
+ }
+
+}
+void CSolver::CompleteComms(CGeometry *geometry,
+ CConfig *config,
+ unsigned short commType) {
+
+ /*--- Local variables ---*/
+
+ unsigned short iDim, iVar;
+ unsigned long iPoint, iRecv, nRecv, offset, buf_offset;
+
+ int ind, source, iMessage, jRecv;
+ SU2_MPI::Status status;
+
+ /*--- Set some local pointers to make access simpler. ---*/
+
+ su2double *bufDRecv = geometry->bufD_P2PRecv;
+
+ /*--- Store the data that was communicated into the appropriate
+ location within the local class data structures. ---*/
+
+ if (geometry->nP2PRecv > 0) {
+
+ for (iMessage = 0; iMessage < geometry->nP2PRecv; iMessage++) {
+
+ /*--- For efficiency, recv the messages dynamically based on
+ the order they arrive. ---*/
+
+ SU2_MPI::Waitany(geometry->nP2PRecv, geometry->req_P2PRecv,
+ &ind, &status);
+
+ /*--- Once we have recv'd a message, get the source rank. ---*/
+
+ source = status.MPI_SOURCE;
+
+ /*--- We know the offsets based on the source rank. ---*/
+
+ jRecv = geometry->P2PRecv2Neighbor[source];
+
+ /*--- Get the point offset for the start of this message. ---*/
+
+ offset = geometry->nPoint_P2PRecv[jRecv];
+
+ /*--- Get the number of packets to be received in this message. ---*/
+
+ nRecv = (geometry->nPoint_P2PRecv[jRecv+1] -
+ geometry->nPoint_P2PRecv[jRecv]);
+
+ for (iRecv = 0; iRecv < nRecv; iRecv++) {
+
+ /*--- Get the local index for this communicated data. ---*/
+
+ iPoint = geometry->Local_Point_P2PRecv[offset + iRecv];
+
+ /*--- Compute the offset in the recv buffer for this point. ---*/
+
+ buf_offset = (offset + iRecv)*geometry->countPerPoint;
+
+ /*--- Store the data correctly depending on the quantity. ---*/
+
+ switch (commType) {
+ case SOLUTION:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetSolution(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case SOLUTION_OLD:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetSolution_Old(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case SOLUTION_EDDY:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetSolution(iVar, bufDRecv[buf_offset+iVar]);
+ node[iPoint]->SetmuT(bufDRecv[offset+nVar]);
+ break;
+ case UNDIVIDED_LAPLACIAN:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetUndivided_Laplacian(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case SOLUTION_LIMITER:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetLimiter(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case MAX_EIGENVALUE:
+ node[iPoint]->SetLambda(bufDRecv[buf_offset]);
+ break;
+ case SENSOR:
+ node[iPoint]->SetSensor(bufDRecv[buf_offset]);
+ break;
+ case SOLUTION_GRADIENT:
+ for (iVar = 0; iVar < nVar; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetGradient(iVar, iDim, bufDRecv[buf_offset+iVar*nDim+iDim]);
+ break;
+ case PRIMITIVE_GRADIENT:
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetGradient_Primitive(iVar, iDim, bufDRecv[buf_offset+iVar*nDim+iDim]);
+ break;
+ case PRIMITIVE_LIMITER:
+ for (iVar = 0; iVar < nPrimVarGrad; iVar++)
+ node[iPoint]->SetLimiter_Primitive(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case AUXVAR_GRADIENT:
+ for (iDim = 0; iDim < nDim; iDim++)
+ node[iPoint]->SetAuxVarGradient(iDim, bufDRecv[buf_offset+iDim]);
+ break;
+ case SOLUTION_FEA:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ node[iPoint]->SetSolution(iVar, bufDRecv[buf_offset+iVar]);
+ if (config->GetDynamic_Analysis() == DYNAMIC) {
+ node[iPoint]->SetSolution_Vel(iVar, bufDRecv[buf_offset+nVar+iVar]);
+ node[iPoint]->SetSolution_Accel(iVar, bufDRecv[buf_offset+nVar*2+iVar]);
+ }
+ }
+ break;
+ case SOLUTION_FEA_OLD:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ node[iPoint]->SetSolution_time_n(iVar, bufDRecv[buf_offset+iVar]);
+ node[iPoint]->SetSolution_Vel_time_n(iVar, bufDRecv[buf_offset+nVar+iVar]);
+ node[iPoint]->SetSolution_Accel_time_n(iVar, bufDRecv[buf_offset+nVar*2+iVar]);
+ }
+ break;
+ case SOLUTION_DISPONLY:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetSolution(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case SOLUTION_PRED:
+ for (iVar = 0; iVar < nVar; iVar++)
+ node[iPoint]->SetSolution_Pred(iVar, bufDRecv[buf_offset+iVar]);
+ break;
+ case SOLUTION_PRED_OLD:
+ for (iVar = 0; iVar < nVar; iVar++) {
+ node[iPoint]->SetSolution_Old(iVar, bufDRecv[buf_offset+iVar]);
+ node[iPoint]->SetSolution_Pred(iVar, bufDRecv[buf_offset+nVar+iVar]);
+ node[iPoint]->SetSolution_Pred_Old(iVar, bufDRecv[buf_offset+nVar*2+iVar]);
+ }
+ break;
+ default:
+ SU2_MPI::Error("Unrecognized quantity for point-to-point MPI comms.",
+ CURRENT_FUNCTION);
+ break;
+ }
+ }
+ }
+
+ /*--- Verify that all non-blocking point-to-point sends have finished.
+ Note that this should be satisfied, as we have received all of the
+ data in the loop above at this point. ---*/
+
+#ifdef HAVE_MPI
+ SU2_MPI::Waitall(geometry->nP2PSend, geometry->req_P2PSend, MPI_STATUS_IGNORE);
+#endif
+
}
-
- if (Restart_Vars != NULL) {delete [] Restart_Vars; Restart_Vars = NULL;}
- if (Restart_Data != NULL) {delete [] Restart_Data; Restart_Data = NULL;}
-
- if (nRowCum_InletFile != NULL) {delete [] nRowCum_InletFile; nRowCum_InletFile = NULL;}
- if (nRow_InletFile != NULL) {delete [] nRow_InletFile; nRow_InletFile = NULL;}
- if (nCol_InletFile != NULL) {delete [] nCol_InletFile; nCol_InletFile = NULL;}
- if (Inlet_Data != NULL) {delete [] Inlet_Data; Inlet_Data = NULL;}
-
+
}
void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) {
@@ -230,7 +2174,7 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) {
int nProcessor = size, iProcessor;
su2double *sbuf_residual, *rbuf_residual, *sbuf_coord, *rbuf_coord, *Coord;
- unsigned long *sbuf_point, *rbuf_point, Local_nPointDomain, Global_nPointDomain;
+ unsigned long *sbuf_point, *rbuf_point, Global_nPointDomain;
unsigned short iDim;
/*--- Set the L2 Norm residual in all the processors ---*/
@@ -239,11 +2183,21 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) {
rbuf_residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) rbuf_residual[iVar] = 0.0;
for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = GetRes_RMS(iVar);
- Local_nPointDomain = geometry->GetnPointDomain();
-
- SU2_MPI::Allreduce(sbuf_residual, rbuf_residual, nVar, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(&Local_nPointDomain, &Global_nPointDomain, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ unsigned long Local_nPointDomain = geometry->GetnPointDomain();
+ SU2_MPI::Allreduce(sbuf_residual, rbuf_residual, nVar, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(&Local_nPointDomain, &Global_nPointDomain, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
+
+ } else {
+
+ /*--- Reduced MPI comms have been requested. Use a local residual only. ---*/
+
+ for (iVar = 0; iVar < nVar; iVar++) rbuf_residual[iVar] = sbuf_residual[iVar];
+ Global_nPointDomain = geometry->GetnPointDomain();
+
+ }
for (iVar = 0; iVar < nVar; iVar++) {
@@ -260,41 +2214,46 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) {
delete [] rbuf_residual;
/*--- Set the Maximum residual in all the processors ---*/
- sbuf_residual = new su2double [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = 0.0;
- sbuf_point = new unsigned long [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_point[iVar] = 0;
- sbuf_coord = new su2double[nVar*nDim]; for (iVar = 0; iVar < nVar*nDim; iVar++) sbuf_coord[iVar] = 0.0;
-
- rbuf_residual = new su2double [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_residual[iVar] = 0.0;
- rbuf_point = new unsigned long [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_point[iVar] = 0;
- rbuf_coord = new su2double[nProcessor*nVar*nDim]; for (iVar = 0; iVar < nProcessor*nVar*nDim; iVar++) rbuf_coord[iVar] = 0.0;
-
- for (iVar = 0; iVar < nVar; iVar++) {
- sbuf_residual[iVar] = GetRes_Max(iVar);
- sbuf_point[iVar] = GetPoint_Max(iVar);
- Coord = GetPoint_Max_Coord(iVar);
- for (iDim = 0; iDim < nDim; iDim++)
- sbuf_coord[iVar*nDim+iDim] = Coord[iDim];
- }
- SU2_MPI::Allgather(sbuf_residual, nVar, MPI_DOUBLE, rbuf_residual, nVar, MPI_DOUBLE, MPI_COMM_WORLD);
- SU2_MPI::Allgather(sbuf_point, nVar, MPI_UNSIGNED_LONG, rbuf_point, nVar, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
- SU2_MPI::Allgather(sbuf_coord, nVar*nDim, MPI_DOUBLE, rbuf_coord, nVar*nDim, MPI_DOUBLE, MPI_COMM_WORLD);
-
- for (iVar = 0; iVar < nVar; iVar++) {
- for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
- AddRes_Max(iVar, rbuf_residual[iProcessor*nVar+iVar], rbuf_point[iProcessor*nVar+iVar], &rbuf_coord[iProcessor*nVar*nDim+iVar*nDim]);
+ if (config->GetComm_Level() == COMM_FULL) {
+
+ sbuf_residual = new su2double [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = 0.0;
+ sbuf_point = new unsigned long [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_point[iVar] = 0;
+ sbuf_coord = new su2double[nVar*nDim]; for (iVar = 0; iVar < nVar*nDim; iVar++) sbuf_coord[iVar] = 0.0;
+
+ rbuf_residual = new su2double [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_residual[iVar] = 0.0;
+ rbuf_point = new unsigned long [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_point[iVar] = 0;
+ rbuf_coord = new su2double[nProcessor*nVar*nDim]; for (iVar = 0; iVar < nProcessor*nVar*nDim; iVar++) rbuf_coord[iVar] = 0.0;
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ sbuf_residual[iVar] = GetRes_Max(iVar);
+ sbuf_point[iVar] = GetPoint_Max(iVar);
+ Coord = GetPoint_Max_Coord(iVar);
+ for (iDim = 0; iDim < nDim; iDim++)
+ sbuf_coord[iVar*nDim+iDim] = Coord[iDim];
+ }
+
+ SU2_MPI::Allgather(sbuf_residual, nVar, MPI_DOUBLE, rbuf_residual, nVar, MPI_DOUBLE, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(sbuf_point, nVar, MPI_UNSIGNED_LONG, rbuf_point, nVar, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
+ SU2_MPI::Allgather(sbuf_coord, nVar*nDim, MPI_DOUBLE, rbuf_coord, nVar*nDim, MPI_DOUBLE, MPI_COMM_WORLD);
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
+ AddRes_Max(iVar, rbuf_residual[iProcessor*nVar+iVar], rbuf_point[iProcessor*nVar+iVar], &rbuf_coord[iProcessor*nVar*nDim+iVar*nDim]);
+ }
}
+
+ delete [] sbuf_residual;
+ delete [] rbuf_residual;
+
+ delete [] sbuf_point;
+ delete [] rbuf_point;
+
+ delete [] sbuf_coord;
+ delete [] rbuf_coord;
+
}
- delete [] sbuf_residual;
- delete [] rbuf_residual;
-
- delete [] sbuf_point;
- delete [] rbuf_point;
-
- delete [] sbuf_coord;
- delete [] rbuf_coord;
-
#endif
}
@@ -390,75 +2349,82 @@ void CSolver::SetResidual_BGS(CGeometry *geometry, CConfig *config) {
}
-void CSolver::SetGrid_Movement_Residual (CGeometry *geometry, CConfig *config) {
+void CSolver::SetRotatingFrame_GCL(CGeometry *geometry, CConfig *config) {
unsigned short iDim, nDim = geometry->GetnDim(), iVar, nVar = GetnVar(), iMarker;
unsigned long iVertex, iEdge;
su2double ProjGridVel, *Normal;
-
+
/*--- Loop interior edges ---*/
-
+
for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) {
-
+
const unsigned long iPoint = geometry->edge[iEdge]->GetNode(0);
const unsigned long jPoint = geometry->edge[iEdge]->GetNode(1);
-
+
/*--- Solution at each edge point ---*/
-
+
su2double *Solution_i = node[iPoint]->GetSolution();
su2double *Solution_j = node[jPoint]->GetSolution();
-
+
for (iVar = 0; iVar < nVar; iVar++)
Solution[iVar] = 0.5* (Solution_i[iVar] + Solution_j[iVar]);
-
+
/*--- Grid Velocity at each edge point ---*/
-
+
su2double *GridVel_i = geometry->node[iPoint]->GetGridVel();
su2double *GridVel_j = geometry->node[jPoint]->GetGridVel();
for (iDim = 0; iDim < nDim; iDim++)
Vector[iDim] = 0.5* (GridVel_i[iDim] + GridVel_j[iDim]);
-
+
Normal = geometry->edge[iEdge]->GetNormal();
-
+
ProjGridVel = 0.0;
for (iDim = 0; iDim < nDim; iDim++)
ProjGridVel += Vector[iDim]*Normal[iDim];
-
+
for (iVar = 0; iVar < nVar; iVar++)
- Residual[iVar] = ProjGridVel*Solution[iVar];
-
- LinSysRes.SubtractBlock(iPoint, Residual);
- LinSysRes.AddBlock(jPoint, Residual);
-
+ Residual[iVar] = ProjGridVel*Solution_i[iVar];
+
+ LinSysRes.AddBlock(iPoint, Residual);
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ Residual[iVar] = ProjGridVel*Solution_j[iVar];
+
+ LinSysRes.SubtractBlock(jPoint, Residual);
+
}
-
+
/*--- Loop boundary edges ---*/
-
+
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
- for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
- const unsigned long Point = geometry->vertex[iMarker][iVertex]->GetNode();
-
- /*--- Solution at each edge point ---*/
-
- su2double *Solution = node[Point]->GetSolution();
-
- /*--- Grid Velocity at each edge point ---*/
-
- su2double *GridVel = geometry->node[Point]->GetGridVel();
-
- /*--- Summed normal components ---*/
-
- Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
-
- ProjGridVel = 0.0;
- for (iDim = 0; iDim < nDim; iDim++)
- ProjGridVel -= GridVel[iDim]*Normal[iDim];
-
- for (iVar = 0; iVar < nVar; iVar++)
- Residual[iVar] = ProjGridVel*Solution[iVar];
-
- LinSysRes.AddBlock(Point, Residual);
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
+ for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
+ const unsigned long Point = geometry->vertex[iMarker][iVertex]->GetNode();
+
+ /*--- Solution at each edge point ---*/
+
+ su2double *Solution = node[Point]->GetSolution();
+
+ /*--- Grid Velocity at each edge point ---*/
+
+ su2double *GridVel = geometry->node[Point]->GetGridVel();
+
+ /*--- Summed normal components ---*/
+
+ Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
+
+ ProjGridVel = 0.0;
+ for (iDim = 0; iDim < nDim; iDim++)
+ ProjGridVel += GridVel[iDim]*Normal[iDim];
+
+ for (iVar = 0; iVar < nVar; iVar++)
+ Residual[iVar] = ProjGridVel*Solution[iVar];
+
+ LinSysRes.SubtractBlock(Point, Residual);
+
+ }
}
}
@@ -620,7 +2586,8 @@ void CSolver::SetAuxVar_Gradient_GG(CGeometry *geometry, CConfig *config) {
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
AuxVar_Vertex = node[Point]->GetAuxVar();
@@ -630,6 +2597,7 @@ void CSolver::SetAuxVar_Gradient_GG(CGeometry *geometry, CConfig *config) {
node[Point]->SubtractAuxVarGradient(iDim, Partial_Res);
}
}
+ }
for (iPoint=0; iPointGetnPoint(); iPoint++)
for (iDim = 0; iDim < nDim; iDim++) {
@@ -641,8 +2609,9 @@ void CSolver::SetAuxVar_Gradient_GG(CGeometry *geometry, CConfig *config) {
/*--- Gradient MPI ---*/
- Set_MPI_AuxVar_Gradient(geometry, config);
-
+ InitiateComms(geometry, config, AUXVAR_GRADIENT);
+ CompleteComms(geometry, config, AUXVAR_GRADIENT);
+
}
void CSolver::SetAuxVar_Gradient_LS(CGeometry *geometry, CConfig *config) {
@@ -766,15 +2735,16 @@ void CSolver::SetAuxVar_Gradient_LS(CGeometry *geometry, CConfig *config) {
/*--- Gradient MPI ---*/
- Set_MPI_AuxVar_Gradient(geometry, config);
+ InitiateComms(geometry, config, AUXVAR_GRADIENT);
+ CompleteComms(geometry, config, AUXVAR_GRADIENT);
}
void CSolver::SetSolution_Gradient_GG(CGeometry *geometry, CConfig *config) {
unsigned long Point = 0, iPoint = 0, jPoint = 0, iEdge, iVertex;
unsigned short iVar, iDim, iMarker;
- su2double *Solution_Vertex, *Solution_i, *Solution_j, Solution_Average, **Gradient, DualArea,
- Partial_Res, Grad_Val, *Normal;
+ su2double *Solution_Vertex, *Solution_i, *Solution_j, Solution_Average, **Gradient,
+ Partial_Res, Grad_Val, *Normal, Vol;
/*--- Set Gradient to Zero ---*/
for (iPoint = 0; iPoint < geometry->GetnPointDomain(); iPoint++)
@@ -802,8 +2772,8 @@ void CSolver::SetSolution_Gradient_GG(CGeometry *geometry, CConfig *config) {
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY &&
- config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
Solution_Vertex = node[Point]->GetSolution();
@@ -816,19 +2786,37 @@ void CSolver::SetSolution_Gradient_GG(CGeometry *geometry, CConfig *config) {
}
}
}
+ }
+
+ /*--- Correct the gradient values for any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SOL_GG);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SOL_GG);
+ }
/*--- Compute gradient ---*/
- for (iPoint = 0; iPoint < geometry->GetnPointDomain(); iPoint++)
- for (iVar = 0; iVar < nVar; iVar++)
+ for (iPoint = 0; iPoint < geometry->GetnPointDomain(); iPoint++) {
+
+ /*--- Get the volume, which may include periodic components. ---*/
+
+ Vol = (geometry->node[iPoint]->GetVolume() +
+ geometry->node[iPoint]->GetPeriodicVolume());
+
+ for (iVar = 0; iVar < nVar; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
Gradient = node[iPoint]->GetGradient();
- DualArea = geometry->node[iPoint]->GetVolume();
- Grad_Val = Gradient[iVar][iDim] / (DualArea+EPS);
+ Grad_Val = Gradient[iVar][iDim] / (Vol+EPS);
node[iPoint]->SetGradient(iVar, iDim, Grad_Val);
}
+ }
+
+ }
/*--- Gradient MPI ---*/
- Set_MPI_Solution_Gradient(geometry, config);
+
+ InitiateComms(geometry, config, SOLUTION_GRADIENT);
+ CompleteComms(geometry, config, SOLUTION_GRADIENT);
}
@@ -836,9 +2824,9 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
unsigned short iDim, jDim, iVar, iNeigh;
unsigned long iPoint, jPoint;
- su2double *Coord_i, *Coord_j, *Solution_i, *Solution_j,
- r11, r12, r13, r22, r23, r23_a, r23_b, r33, weight, detR2, z11, z12, z13,
- z22, z23, z33, product;
+ su2double *Coord_i, *Coord_j, *Solution_i, *Solution_j;
+ su2double r11, r12, r13, r22, r23, r23_a, r23_b, r33, weight;
+ su2double detR2, z11, z12, z13, z22, z23, z33;
bool singular = false;
su2double **Cvector = new su2double* [nVar];
@@ -866,12 +2854,11 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
for (iDim = 0; iDim < nDim; iDim++)
Cvector[iVar][iDim] = 0.0;
- r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
- r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
-
- AD::StartPreacc();
- AD::SetPreaccIn(Solution_i, nVar);
- AD::SetPreaccIn(Coord_i, nDim);
+ /*--- Clear Rmatrix, which could eventually be computed once
+ and stored for static meshes, as well as the prim gradient. ---*/
+
+ node[iPoint]->SetRmatrixZero();
+ node[iPoint]->SetGradientZero();
for (iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); iNeigh++) {
jPoint = geometry->node[iPoint]->GetPoint(iNeigh);
@@ -879,9 +2866,6 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
Solution_j = node[jPoint]->GetSolution();
- AD::SetPreaccIn(Coord_j, nDim);
- AD::SetPreaccIn(Solution_j, nVar);
-
weight = 0.0;
for (iDim = 0; iDim < nDim; iDim++)
weight += (Coord_j[iDim]-Coord_i[iDim])*(Coord_j[iDim]-Coord_i[iDim]);
@@ -890,24 +2874,52 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
if (weight != 0.0) {
- r11 += (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight;
- r12 += (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight;
- r22 += (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight;
+ node[iPoint]->AddRmatrix(0, 0, (Coord_j[0]-Coord_i[0])*(Coord_j[0]-Coord_i[0])/weight);
+ node[iPoint]->AddRmatrix(0, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[1]-Coord_i[1])/weight);
+ node[iPoint]->AddRmatrix(1, 1, (Coord_j[1]-Coord_i[1])*(Coord_j[1]-Coord_i[1])/weight);
+
if (nDim == 3) {
- r13 += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r23_a += (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight;
- r23_b += (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight;
- r33 += (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight;
+ node[iPoint]->AddRmatrix(0, 2, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(1, 2, (Coord_j[1]-Coord_i[1])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 1, (Coord_j[0]-Coord_i[0])*(Coord_j[2]-Coord_i[2])/weight);
+ node[iPoint]->AddRmatrix(2, 2, (Coord_j[2]-Coord_i[2])*(Coord_j[2]-Coord_i[2])/weight);
}
/*--- Entries of c:= transpose(A)*b ---*/
- for (iVar = 0; iVar < nVar; iVar++)
- for (iDim = 0; iDim < nDim; iDim++)
- Cvector[iVar][iDim] += (Coord_j[iDim]-Coord_i[iDim])*(Solution_j[iVar]-Solution_i[iVar])/weight;
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->AddGradient(iVar,iDim, (Coord_j[iDim]-Coord_i[iDim])*(Solution_j[iVar]-Solution_i[iVar])/weight);
+ }
+ }
+
}
-
}
+ }
+
+ /*--- Correct the gradient values for any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SOL_LS);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SOL_LS);
+ }
+
+ /*--- Second loop over points of the grid to compute final gradient ---*/
+
+ for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
+
+ /*--- Set the value of the singular ---*/
+
+ singular = false;
+
+ /*--- Entries of upper triangular matrix R ---*/
+
+ r11 = 0.0; r12 = 0.0; r13 = 0.0; r22 = 0.0;
+ r23 = 0.0; r23_a = 0.0; r23_b = 0.0; r33 = 0.0;
+
+ r11 = node[iPoint]->GetRmatrix(0,0);
+ r12 = node[iPoint]->GetRmatrix(0,1);
+ r22 = node[iPoint]->GetRmatrix(1,1);
/*--- Entries of upper triangular matrix R ---*/
@@ -916,6 +2928,11 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
if (r22-r12*r12 >= 0.0) r22 = sqrt(r22-r12*r12); else r22 = 0.0;
if (nDim == 3) {
+ r13 = node[iPoint]->GetRmatrix(0,2);
+ r23_a = node[iPoint]->GetRmatrix(1,2);
+ r23_b = node[iPoint]->GetRmatrix(2,1);
+ r33 = node[iPoint]->GetRmatrix(2,2);
+
if (r11 != 0.0) r13 = r13/r11; else r13 = 0.0;
if ((r22 != 0.0) && (r11*r22 != 0.0)) r23 = r23_a/r22 - r23_b*r12/(r11*r22); else r23 = 0.0;
if (r33-r23*r23-r13*r13 >= 0.0) r33 = sqrt(r33-r23*r23-r13*r13); else r33 = 0.0;
@@ -963,15 +2980,19 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
for (iVar = 0; iVar < nVar; iVar++) {
for (iDim = 0; iDim < nDim; iDim++) {
- product = 0.0;
- for (jDim = 0; jDim < nDim; jDim++)
- product += Smatrix[iDim][jDim]*Cvector[iVar][jDim];
- node[iPoint]->SetGradient(iVar, iDim, product);
+ Cvector[iVar][iDim] = 0.0;
+ for (jDim = 0; jDim < nDim; jDim++) {
+ Cvector[iVar][iDim] += Smatrix[iDim][jDim]*node[iPoint]->GetGradient(iVar, jDim);
+ }
}
}
-
- AD::SetPreaccOut(node[iPoint]->GetGradient(), nVar, nDim);
- AD::EndPreacc();
+
+ for (iVar = 0; iVar < nVar; iVar++) {
+ for (iDim = 0; iDim < nDim; iDim++) {
+ node[iPoint]->SetGradient(iVar, iDim, Cvector[iVar][iDim]);
+ }
+ }
+
}
/*--- Deallocate memory ---*/
@@ -982,7 +3003,8 @@ void CSolver::SetSolution_Gradient_LS(CGeometry *geometry, CConfig *config) {
/*--- Gradient MPI ---*/
- Set_MPI_Solution_Gradient(geometry, config);
+ InitiateComms(geometry, config, SOLUTION_GRADIENT);
+ CompleteComms(geometry, config, SOLUTION_GRADIENT);
}
@@ -1273,6 +3295,13 @@ void CSolver::SetSolution_Limiter(CGeometry *geometry, CConfig *config) {
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_SOL_1);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_SOL_1);
+ }
+
}
/*--- Barth-Jespersen limiter with Venkatakrishnan modification ---*/
@@ -1383,15 +3412,17 @@ void CSolver::SetSolution_Limiter(CGeometry *geometry, CConfig *config) {
}
+ if (config->GetKind_SlopeLimit_Flow() == VENKATAKRISHNAN_WANG) {
#ifdef HAVE_MPI
- SU2_MPI::Allreduce(LocalMinSolution, GlobalMinSolution, nVar, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
- SU2_MPI::Allreduce(LocalMaxSolution, GlobalMaxSolution, nVar, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMinSolution, GlobalMinSolution, nVar, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
+ SU2_MPI::Allreduce(LocalMaxSolution, GlobalMaxSolution, nVar, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
#else
- for (iVar = 0; iVar < nVar; iVar++) {
- GlobalMinSolution[iVar] = LocalMinSolution[iVar];
- GlobalMaxSolution[iVar] = LocalMaxSolution[iVar];
- }
+ for (iVar = 0; iVar < nVar; iVar++) {
+ GlobalMinSolution[iVar] = LocalMinSolution[iVar];
+ GlobalMaxSolution[iVar] = LocalMaxSolution[iVar];
+ }
#endif
+ }
for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) {
@@ -1611,11 +3642,18 @@ void CSolver::SetSolution_Limiter(CGeometry *geometry, CConfig *config) {
}
}
+ /*--- Correct the limiter values across any periodic boundaries. ---*/
+
+ for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
+ InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_SOL_2);
+ CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LIM_SOL_2);
+ }
/*--- Limiter MPI ---*/
- Set_MPI_Solution_Limiter(geometry, config);
-
+ InitiateComms(geometry, config, SOLUTION_LIMITER);
+ CompleteComms(geometry, config, SOLUTION_LIMITER);
+
}
void CSolver::SetPressureLaplacian(CGeometry *geometry, CConfig *config, su2double *PressureLaplacian) {
@@ -1666,7 +3704,8 @@ void CSolver::SetPressureLaplacian(CGeometry *geometry, CConfig *config, su2doub
/*--- Loop boundary edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++)
- if (config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY)
+ if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
+ (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
Point = geometry->vertex[iMarker][iVertex]->GetNode();
Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
@@ -1683,6 +3722,7 @@ void CSolver::SetPressureLaplacian(CGeometry *geometry, CConfig *config, su2doub
Partial_Res = node[Point]->GetSolution(2) * Normal[1];
UyVar_Gradient[Point][1] -= Partial_Res;
}
+ }
for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
DualArea = geometry->node[iPoint]->GetVolume();
@@ -2184,8 +4224,9 @@ void CSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) {
}
/*--- It's necessary to communicate this information ---*/
-
- geometry->Set_MPI_OldCoord(config);
+
+ geometry->InitiateComms(geometry, config, COORDINATES_OLD);
+ geometry->CompleteComms(geometry, config, COORDINATES_OLD);
delete [] Coord;
@@ -4059,16 +6100,20 @@ void CBaselineSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf
/*--- MPI solution ---*/
- Set_MPI_Solution(geometry[iInst], config);
-
+ InitiateComms(geometry[iInst], config, SOLUTION);
+ CompleteComms(geometry[iInst], config, SOLUTION);
+
/*--- Update the geometry for flows on dynamic meshes ---*/
if (grid_movement && val_update_geo) {
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
- geometry[iInst]->Set_MPI_Coord(config);
- geometry[iInst]->Set_MPI_GridVel(config);
+ geometry[iInst]->InitiateComms(geometry[iInst], config, COORDINATES);
+ geometry[iInst]->CompleteComms(geometry[iInst], config, COORDINATES);
+
+ geometry[iInst]->InitiateComms(geometry[iInst], config, GRID_VELOCITY);
+ geometry[iInst]->CompleteComms(geometry[iInst], config, GRID_VELOCITY);
}
diff --git a/SU2_CFD/src/variable_structure.cpp b/SU2_CFD/src/variable_structure.cpp
index 68ad8ebfad2f..16692d613a0e 100644
--- a/SU2_CFD/src/variable_structure.cpp
+++ b/SU2_CFD/src/variable_structure.cpp
@@ -67,6 +67,7 @@ CVariable::CVariable(unsigned short val_nvar, CConfig *config) {
Solution_time_n = NULL;
Solution_time_n1 = NULL;
Gradient = NULL;
+ Rmatrix = NULL;
Limiter = NULL;
Solution_Max = NULL;
Solution_Min = NULL;
@@ -93,7 +94,7 @@ CVariable::CVariable(unsigned short val_nvar, CConfig *config) {
CVariable::CVariable(unsigned short val_nDim, unsigned short val_nvar, CConfig *config) {
- unsigned short iVar, iDim;
+ unsigned short iVar, iDim, jDim;
/*--- Array initialization ---*/
Solution = NULL;
@@ -101,6 +102,7 @@ CVariable::CVariable(unsigned short val_nDim, unsigned short val_nvar, CConfig *
Solution_time_n = NULL;
Solution_time_n1 = NULL;
Gradient = NULL;
+ Rmatrix = NULL;
Limiter = NULL;
Solution_Max = NULL;
Solution_Min = NULL;
@@ -146,10 +148,19 @@ CVariable::CVariable(unsigned short val_nDim, unsigned short val_nvar, CConfig *
Solution_Adj_Old = new su2double [nVar];
}
+ if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) {
+ Rmatrix = new su2double*[nDim];
+ for (iDim = 0; iDim < nDim; iDim++) {
+ Rmatrix[iDim] = new su2double[nDim];
+ for (jDim = 0; jDim < nDim; jDim++)
+ Rmatrix[iDim][jDim] = 0.0;
+ }
+ }
+
}
CVariable::~CVariable(void) {
- unsigned short iVar;
+ unsigned short iVar, iDim;
if (Solution != NULL) delete [] Solution;
if (Solution_Old != NULL) delete [] Solution_Old;
@@ -171,6 +182,12 @@ CVariable::~CVariable(void) {
delete [] Gradient;
}
+ if (Rmatrix != NULL) {
+ for (iDim = 0; iDim < nDim; iDim++)
+ delete [] Rmatrix[iDim];
+ delete [] Rmatrix;
+ }
+
}
void CVariable::AddUnd_Lapl(su2double *val_und_lapl) {
@@ -404,6 +421,14 @@ void CVariable::SetGradient(su2double **val_gradient) {
}
+void CVariable::SetRmatrixZero(void) {
+
+ for (unsigned short iDim = 0; iDim < nDim; iDim++)
+ for (unsigned short jDim = 0; jDim < nDim; jDim++)
+ Rmatrix[iDim][jDim] = 0.0;
+
+}
+
void CVariable::SetRes_TruncErrorZero(void) {
for (unsigned short iVar = 0; iVar < nVar; iVar++)
diff --git a/SU2_DEF/src/SU2_DEF.cpp b/SU2_DEF/src/SU2_DEF.cpp
index 226866f5efce..d257a9a43d7e 100644
--- a/SU2_DEF/src/SU2_DEF.cpp
+++ b/SU2_DEF/src/SU2_DEF.cpp
@@ -45,7 +45,6 @@ int main(int argc, char *argv[]) {
char config_file_name[MAX_STRING_SIZE];
int rank, size;
string str;
- bool periodic = false;
/*--- MPI initialization ---*/
@@ -82,7 +81,6 @@ int main(int argc, char *argv[]) {
config = new CConfig(config_file_name, SU2_DEF);
nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
/*--- Definition of the containers per zones ---*/
@@ -108,7 +106,7 @@ int main(int argc, char *argv[]) {
constructor, the input configuration file is parsed and all options are
read and stored. ---*/
- config_container[iZone] = new CConfig(config_file_name, SU2_DEF, iZone, nZone, 0, VERB_HIGH);
+ config_container[iZone] = new CConfig(config_file_name, SU2_DEF, iZone, nZone, 0, true);
config_container[iZone]->SetMPICommunicator(MPICommunicator);
/*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/
@@ -123,15 +121,9 @@ int main(int argc, char *argv[]) {
geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
-
- if (periodic) {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
- }
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
+
+ geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
/*--- Deallocate the memory of geometry_aux ---*/
@@ -193,6 +185,10 @@ int main(int argc, char *argv[]) {
}
+ /*--- Create the point-to-point MPI communication structures. ---*/
+
+ geometry_container[iZone]->PreprocessP2PComms(geometry_container[iZone], config_container[iZone]);
+
}
/*--- initialization of output structure ---*/
diff --git a/SU2_DOT/src/SU2_DOT.cpp b/SU2_DOT/src/SU2_DOT.cpp
index 967cae0961e9..59298cc5b653 100644
--- a/SU2_DOT/src/SU2_DOT.cpp
+++ b/SU2_DOT/src/SU2_DOT.cpp
@@ -46,7 +46,6 @@ int main(int argc, char *argv[]) {
char config_file_name[MAX_STRING_SIZE], *cstr = NULL;
ofstream Gradient_file;
bool fem_solver = false;
- bool periodic = false;
bool multizone = false;
su2double** Gradient;
@@ -89,7 +88,6 @@ int main(int argc, char *argv[]) {
config = new CConfig(config_file_name, SU2_DOT);
nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
/*--- Definition of the containers per zones ---*/
@@ -167,9 +165,7 @@ int main(int argc, char *argv[]) {
if ( fem_solver ) geometry_aux->SetColorFEMGrid_Parallel(config_container[iZone]);
else geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
if( fem_solver ) {
switch( config_container[iZone]->GetKind_FEM_Flow() ) {
@@ -180,11 +176,7 @@ int main(int argc, char *argv[]) {
}
}
else {
- if (periodic) {
- geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
- }
+ geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
}
/*--- Deallocate the memory of geometry_aux ---*/
@@ -276,6 +268,10 @@ int main(int argc, char *argv[]) {
if (rank == MASTER_NODE) cout << "Storing a mapping from global to local point index." << endl;
geometry_container[iZone][INST_0]->SetGlobal_to_Local_Point();
+ /*--- Create the point-to-point MPI communication structures. ---*/
+
+ geometry_container[iZone][INST_0]->PreprocessP2PComms(geometry_container[iZone][INST_0], config_container[iZone]);
+
/*--- Load the surface sensitivities from file. This is done only
once: if this is an unsteady problem, a time-average of the surface
sensitivities at each node is taken within this routine. ---*/
diff --git a/SU2_GEO/src/SU2_GEO.cpp b/SU2_GEO/src/SU2_GEO.cpp
index ceb97a9b9a44..94ba3882ef8c 100644
--- a/SU2_GEO/src/SU2_GEO.cpp
+++ b/SU2_GEO/src/SU2_GEO.cpp
@@ -64,7 +64,6 @@ int main(int argc, char *argv[]) {
char *cstr;
bool Local_MoveSurface, MoveSurface = false;
ofstream Gradient_file, ObjFunc_file;
- bool periodic = false;
int rank, size;
/*--- MPI initialization ---*/
@@ -100,7 +99,6 @@ int main(int argc, char *argv[]) {
config = new CConfig(config_file_name, SU2_GEO);
nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
/*--- Definition of the containers per zones ---*/
@@ -122,7 +120,7 @@ int main(int argc, char *argv[]) {
constructor, the input configuration file is parsed and all options are
read and stored. ---*/
- config_container[iZone] = new CConfig(config_file_name, SU2_GEO, iZone, nZone, 0, VERB_HIGH);
+ config_container[iZone] = new CConfig(config_file_name, SU2_GEO, iZone, nZone, 0, true);
config_container[iZone]->SetMPICommunicator(MPICommunicator);
/*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/
@@ -137,15 +135,9 @@ int main(int argc, char *argv[]) {
geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
- if (periodic) {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
- }
+ geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
/*--- Deallocate the memory of geometry_aux ---*/
@@ -239,6 +231,9 @@ int main(int argc, char *argv[]) {
if (rank == MASTER_NODE) cout << "Setting reference area and span." << endl;
geometry_container[ZONE_0]->SetPositive_ZArea(config_container[ZONE_0]);
+ /*--- Create the point-to-point MPI communication structures. ---*/
+ geometry_container[ZONE_0]->PreprocessP2PComms(geometry_container[ZONE_0], config_container[ZONE_0]);
+
/*--- Create plane structure ---*/
if (rank == MASTER_NODE) cout << "Set plane structure." << endl;
diff --git a/SU2_IDE/Xcode/SU2_CFD.xcodeproj/project.pbxproj b/SU2_IDE/Xcode/SU2_CFD.xcodeproj/project.pbxproj
index 2c137ad6f73c..303d78fbe7ce 100644
--- a/SU2_IDE/Xcode/SU2_CFD.xcodeproj/project.pbxproj
+++ b/SU2_IDE/Xcode/SU2_CFD.xcodeproj/project.pbxproj
@@ -146,7 +146,7 @@
05E6DB8917EB61E600FA1F7E /* config_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = config_structure.cpp; path = ../../Common/src/config_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
05E6DB8A17EB61E600FA1F7E /* dual_grid_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = dual_grid_structure.cpp; path = ../../Common/src/dual_grid_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
05E6DB8B17EB61E600FA1F7E /* geometry_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = geometry_structure.cpp; path = ../../Common/src/geometry_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
- 05E6DB8C17EB61E600FA1F7E /* grid_adaptation_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = grid_adaptation_structure.cpp; path = ../../Common/src/grid_adaptation_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
+ 05E6DB8C17EB61E600FA1F7E /* grid_adaptation_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = grid_adaptation_structure.cpp; path = ../../Common/src/grid_adaptation_structure.cpp; sourceTree = ""; };
05E6DB8D17EB61E600FA1F7E /* grid_movement_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = grid_movement_structure.cpp; path = ../../Common/src/grid_movement_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
05E6DB8E17EB61E600FA1F7E /* linear_solvers_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = linear_solvers_structure.cpp; path = ../../Common/src/linear_solvers_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
05E6DB8F17EB61E600FA1F7E /* matrix_structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = matrix_structure.cpp; path = ../../Common/src/matrix_structure.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
diff --git a/SU2_MSH/src/SU2_MSH.cpp b/SU2_MSH/src/SU2_MSH.cpp
index 09a57a3bc7ce..1a3e3ae1ed72 100644
--- a/SU2_MSH/src/SU2_MSH.cpp
+++ b/SU2_MSH/src/SU2_MSH.cpp
@@ -48,7 +48,6 @@ int main(int argc, char *argv[]) {
char file_name[MAX_STRING_SIZE];
int rank, size;
string str;
- bool periodic = false;
/*--- MPI initialization ---*/
@@ -81,7 +80,6 @@ int main(int argc, char *argv[]) {
config = new CConfig(config_file_name, SU2_MSH);
nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
/*--- Definition of the containers per zones ---*/
@@ -103,7 +101,7 @@ int main(int argc, char *argv[]) {
constructor, the input configuration file is parsed and all options are
read and stored. ---*/
- config_container[iZone] = new CConfig(config_file_name, SU2_MSH, iZone, nZone, 0, VERB_HIGH);
+ config_container[iZone] = new CConfig(config_file_name, SU2_MSH, iZone, nZone, 0, true);
config_container[iZone]->SetMPICommunicator(MPICommunicator);
/*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/
@@ -117,16 +115,10 @@ int main(int argc, char *argv[]) {
/*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/
geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
-
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
+
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
- if (periodic) {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
- }
+ geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
/*--- Deallocate the memory of geometry_aux ---*/
@@ -173,7 +165,10 @@ int main(int argc, char *argv[]) {
cout << "Set control volume structure." << endl;
geometry_container[ZONE_0]->SetControlVolume(config_container[ZONE_0], ALLOCATE); geometry_container[ZONE_0]->SetBoundControlVolume(config_container[ZONE_0], ALLOCATE);
-
+
+ /*--- Create the point-to-point MPI communication structures. ---*/
+
+ geometry_container[ZONE_0]->PreprocessP2PComms(geometry_container[ZONE_0], config_container[ZONE_0]);
if ((config_container[ZONE_0]->GetKind_Adaptation() != NONE) && (config_container[ZONE_0]->GetKind_Adaptation() != PERIODIC)) {
diff --git a/SU2_PY/remove_periodic_halos.py b/SU2_PY/remove_periodic_halos.py
new file mode 100755
index 000000000000..8c13133004dc
--- /dev/null
+++ b/SU2_PY/remove_periodic_halos.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+## \file remove_periodic_halos.py
+# \brief Python script to remove halo layers from SU2 native ascii
+# mesh file preprocessed by SU2_MSH for periodic calcs prior to v7.
+# \author T. Economon
+# \version 6.2.0 "Falcon"
+#
+# The current SU2 release has been coordinated by the
+# SU2 International Developers Society
+# with selected contributions from the open-source community.
+#
+# The main research teams contributing to the current release are:
+# - Prof. Juan J. Alonso's group at Stanford University.
+# - Prof. Piero Colonna's group at Delft University of Technology.
+# - Prof. Nicolas R. Gauger's group at Kaiserslautern University of Technology.
+# - Prof. Alberto Guardone's group at Polytechnic University of Milan.
+# - Prof. Rafael Palacios' group at Imperial College London.
+# - Prof. Vincent Terrapon's group at the University of Liege.
+# - Prof. Edwin van der Weide's group at the University of Twente.
+# - Lab. of New Concepts in Aeronautics at Tech. Institute of Aeronautics.
+#
+# Copyright 2012-2019, Francisco D. Palacios, Thomas D. Economon,
+# Tim Albring, and the SU2 contributors.
+#
+# 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 .
+
+from optparse import OptionParser
+
+parser=OptionParser()
+parser.add_option("-f", "--file", dest="filename",
+ help="read mesh file to remove halos", metavar="FILE")
+(options, args)=parser.parse_args()
+
+# Store the filename for the input mesh
+
+filename = options.filename
+
+# The first reading of the mesh is to isolate the number of periodic
+# points along with their global index values.
+
+periodic_points = []
+
+fid = open(filename,"r"); lines = fid.readlines(); fid.close()
+for ii in range(len(lines[:])):
+
+ # The periodic nodes are in the receive BC and will have an even index
+ if "SEND_RECEIVE" in lines[ii] and int(lines[ii+2].split("=")[1]) == -1:
+ nElems = int(lines[ii+1].split("=")[1])
+ kk = ii+3
+ for jj in range(nElems):
+ tokens = lines[kk].replace("\n","").split()
+ periodic = int(tokens[2])
+ if periodic % 2 == 0:
+ periodic_points.append(tokens[1])
+ kk += 1
+
+# Store the number of periodic points in an easier way
+
+nPeriodic = len(periodic_points)
+
+# Get the new counts for points, elems, and markers / boundary elems
+
+nDim = 0
+nPoint = 0
+nElems = 0
+nMarker = 0
+
+# Get nDim
+
+for ii in range(len(lines[:])):
+ if "NDIME=" in lines[ii]:
+ tokens = lines[ii].replace("\n","").split("=")
+ nDim = int(tokens[1])
+ break
+
+# To get point count just subtract the number of periodic points from total
+
+for ii in range(len(lines[:])):
+ if "NPOIN=" in lines[ii]:
+ tokens = lines[ii].replace("\n","").split()
+ nPoints = int(tokens[1]) - nPeriodic
+ break
+
+# Count up the interior elements, excluding the added halos
+
+for ii in range(len(lines[:])):
+ if "NELEM=" in lines[ii]:
+ tokens = lines[ii].replace("\n","").split("=")
+ nElemOld = int(tokens[1])
+ nElems = nElemOld
+ kk = ii+1
+ for jj in range(nElemOld):
+ element = lines[kk].replace("\n","").split()
+ conn = element[1:-1]
+ isHalo = False
+ for val in periodic_points:
+ if val in conn:
+ isHalo = True
+ if isHalo:
+ nElems -= 1
+ kk += 1
+ break
+
+# Simply subtract 2 from the marker count to remove SEND_RECEIVE BCs
+
+for ii in range(len(lines[:])):
+ if "NMARK=" in lines[ii]:
+ tokens = lines[ii].replace("\n","").split("=")
+ nMarker = int(tokens[1]) - 2
+ break
+
+# Begin writing the new mesh file
+
+fid = open("mesh_no_halo.su2","w");
+fid.write("NDIME= " + str(nDim) + "\n")
+
+# Write the points, excluding the periodic points at the end of the list
+
+for ii in range(len(lines[:])):
+ if "NPOIN=" in lines[ii]:
+ fid.write("NPOIN= " + str(nPoints) + "\n")
+ kk = ii+1
+ for jj in range(nPoints):
+ fid.write(lines[kk])
+ kk += 1
+ break
+
+# Write the element connectivity, excluding the periodic halos
+
+for ii in range(len(lines[:])):
+ if "NELEM=" in lines[ii]:
+ tokens = lines[ii].replace("\n","").split("=")
+ nElemOld = int(tokens[1])
+ fid.write("NELEM= " + str(nElems) + "\n")
+ kk = ii+1
+ for jj in range(nElemOld):
+ element = lines[kk].replace("\n","").split()
+ conn = element[1:-1]
+ isHalo = False
+ for val in periodic_points:
+ if val in conn:
+ isHalo = True
+ if not isHalo:
+ fid.write(lines[kk])
+ kk += 1
+ break
+
+# Write the markers, excluding an halo elements and the SEND_RECEIVE BCs
+
+for ii in range(len(lines[:])):
+ if "NMARK=" in lines[ii]:
+ fid.write("NMARK= " + str(nMarker) + "\n")
+ if "MARKER_TAG=" in lines[ii] and "SEND_RECEIVE" not in lines[ii]:
+ fid.write(lines[ii])
+ tokens = lines[ii+1].replace("\n","").split("=")
+ nElemOld = int(tokens[1])
+ nElems = nElemOld
+ kk = ii+2
+
+ # First count number of boundary elems to be removed
+
+ for jj in range(nElemOld):
+ element = lines[kk].replace("\n","").split()
+ conn = element[1:]
+ isHalo = False
+ for val in periodic_points:
+ if val in conn:
+ isHalo = True
+ if isHalo:
+ nElems -= 1
+ kk += 1
+
+ # Now write the list of boundary elems, excluding halos
+
+ kk = ii+2
+ fid.write("MARKER_ELEMS= " + str(nElems) + "\n")
+ for jj in range(nElemOld):
+ element = lines[kk].replace("\n","").split()
+ conn = element[1:]
+ isHalo = False
+ for val in periodic_points:
+ if val in conn:
+ isHalo = True
+ if not isHalo:
+ fid.write(lines[kk])
+ kk += 1
+
+# Close the file and exit
+
+fid.close()
diff --git a/SU2_SOL/src/SU2_SOL.cpp b/SU2_SOL/src/SU2_SOL.cpp
index 2fe936f744bb..c2ef3c67e039 100644
--- a/SU2_SOL/src/SU2_SOL.cpp
+++ b/SU2_SOL/src/SU2_SOL.cpp
@@ -48,7 +48,6 @@ int main(int argc, char *argv[]) {
int rank = MASTER_NODE;
int size = SINGLE_NODE;
bool fem_solver = false;
- bool periodic = false;
bool multizone = false;
/*--- MPI initialization ---*/
@@ -83,7 +82,6 @@ int main(int argc, char *argv[]) {
if (config->GetKind_Solver() == MULTIZONE) nZone = config->GetnConfigFiles();
else nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
- periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
/*--- Definition of the containers per zones ---*/
@@ -121,11 +119,12 @@ int main(int argc, char *argv[]) {
if (multizone){
strcpy(zone_file_name, driver_config->GetConfigFilename(iZone).c_str());
- config_container[iZone] = new CConfig(zone_file_name, SU2_SOL, iZone, nZone, 0, VERB_HIGH);
+ config_container[iZone] = new CConfig(zone_file_name, SU2_SOL, iZone, nZone, 0, true);
}
else{
- config_container[iZone] = new CConfig(config_file_name, SU2_SOL, iZone, nZone, 0, VERB_HIGH);
+ config_container[iZone] = new CConfig(config_file_name, SU2_SOL, iZone, nZone, 0, true);
}
+
config_container[iZone]->SetMPICommunicator(MPICommunicator);
}
@@ -183,9 +182,7 @@ int main(int argc, char *argv[]) {
geometry_container[iZone][iInst] = NULL;
- /*--- Until we finish the new periodic BC implementation, use the old
- partitioning routines for cases with periodic BCs. The old routines
- will be entirely removed eventually in favor of the new methods. ---*/
+ /*--- Build the grid data structures using the ParMETIS coloring. ---*/
if( fem_solver ) {
switch( config_container[iZone]->GetKind_FEM_Flow() ) {
@@ -196,11 +193,7 @@ int main(int argc, char *argv[]) {
}
}
else {
- if (periodic) {
- geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
- } else {
- geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
- }
+ geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
}
/*--- Deallocate the memory of geometry_aux ---*/
@@ -210,7 +203,7 @@ int main(int argc, char *argv[]) {
/*--- Add the Send/Receive boundaries ---*/
geometry_container[iZone][iInst]->SetSendReceive(config_container[iZone]);
-
+
/*--- Add the Send/Receive boundaries ---*/
geometry_container[iZone][iInst]->SetBoundaries(config_container[iZone]);
@@ -225,6 +218,10 @@ int main(int argc, char *argv[]) {
if (rank == MASTER_NODE) cout << "Storing a mapping from global to local point index." << endl;
geometry_container[iZone][iInst]->SetGlobal_to_Local_Point();
+ /*--- Create the point-to-point MPI communication structures for the fvm solver. ---*/
+
+ if (!fem_solver) geometry_container[iZone][iInst]->PreprocessP2PComms(geometry_container[iZone][iInst], config_container[iZone]);
+
/* Test for a fem solver, because some more work must be done. */
if (fem_solver) {
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 c4c57105bf9e..9013cf3a3006 100644
--- a/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg
+++ b/TestCases/disc_adj_turbomachinery/transonic_stator_2D/transonic_stator.cfg
@@ -389,7 +389,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= su2mesh_per_opt.su2
+MESH_FILENAME= mesh_stator_turb.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/navierstokes/poiseuille/lam_poiseuille.cfg b/TestCases/navierstokes/poiseuille/lam_poiseuille.cfg
index 56687dac7e60..28fcf0f7a322 100644
--- a/TestCases/navierstokes/poiseuille/lam_poiseuille.cfg
+++ b/TestCases/navierstokes/poiseuille/lam_poiseuille.cfg
@@ -23,7 +23,7 @@ KIND_TURB_MODEL= NONE
MATH_PROBLEM= DIRECT
%
% Restart solution (NO, YES)
-RESTART_SOL= YES
+RESTART_SOL= NO
%
% Write binary restart files (YES, NO)
WRT_BINARY_RESTART= NO
@@ -220,7 +220,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION ----------------------.su2
%
% Mesh input file
-MESH_FILENAME= mesh_poiseuille_periodic.su2
+MESH_FILENAME= mesh_poiseuille_51x51.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/nicf/LS89/turb_SA_PR.cfg b/TestCases/nicf/LS89/turb_SA_PR.cfg
index 8eba6e59cad7..f95803ab4779 100644
--- a/TestCases/nicf/LS89/turb_SA_PR.cfg
+++ b/TestCases/nicf/LS89/turb_SA_PR.cfg
@@ -249,15 +249,6 @@ TIME_DISCRE_TURB= EULER_IMPLICIT
% Reduction factor of the CFL coefficient in the turbulence problem
CFL_REDUCTION_TURB= 1.0
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC, FULL, FULL_FLOW, GRAD_FLOW, FULL_ADJOINT,
-% GRAD_ADJOINT, GRAD_FLOW_ADJ, ROBUST,
-% FULL_LINEAR, COMPUTABLE, COMPUTABLE_ROBUST,
-% REMAINING, WAKE, SMOOTHING, SUPERSONIC_SHOCK,
-% TWOPHASE)
-KIND_ADAPT= PERIODIC
-
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
%
% Convergence criteria (CAUCHY, RESIDUAL)
@@ -286,7 +277,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= mesh_vki_turbine.su2
+MESH_FILENAME= mesh_vki_turbine_prepbc.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/nicf/LS89/turb_SST_PR.cfg b/TestCases/nicf/LS89/turb_SST_PR.cfg
index 38483c7ccd9b..b367b52d236e 100644
--- a/TestCases/nicf/LS89/turb_SST_PR.cfg
+++ b/TestCases/nicf/LS89/turb_SST_PR.cfg
@@ -249,15 +249,6 @@ TIME_DISCRE_TURB= EULER_IMPLICIT
% Reduction factor of the CFL coefficient in the turbulence problem
CFL_REDUCTION_TURB= 1.0
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC, FULL, FULL_FLOW, GRAD_FLOW, FULL_ADJOINT,
-% GRAD_ADJOINT, GRAD_FLOW_ADJ, ROBUST,
-% FULL_LINEAR, COMPUTABLE, COMPUTABLE_ROBUST,
-% REMAINING, WAKE, SMOOTHING, SUPERSONIC_SHOCK,
-% TWOPHASE)
-KIND_ADAPT= PERIODIC
-
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
%
% Convergence criteria (CAUCHY, RESIDUAL)
@@ -286,7 +277,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= mesh_vki_turbine.su2
+MESH_FILENAME= mesh_vki_turbine_prepbc.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py
index 70dbb5eb4c19..8d0561f6c1ed 100644
--- a/TestCases/parallel_regression.py
+++ b/TestCases/parallel_regression.py
@@ -172,7 +172,7 @@ def main():
poiseuille.cfg_dir = "navierstokes/poiseuille"
poiseuille.cfg_file = "lam_poiseuille.cfg"
poiseuille.test_iter = 10
- poiseuille.test_vals = [-11.951416, -3.326795, 0.000001, 2.351005] #last 4 columns
+ poiseuille.test_vals = [-5.050864, 0.648220, 0.000349, 13.639525] #last 4 columns
poiseuille.su2_exec = "parallel_computation.py -f"
poiseuille.timeout = 1600
poiseuille.tol = 0.001
@@ -291,7 +291,7 @@ def main():
turb_naca0012_sst_restart_mg.cfg_file = "turb_NACA0012_sst_multigrid_restart.cfg"
turb_naca0012_sst_restart_mg.test_iter = 20
turb_naca0012_sst_restart_mg.ntest_vals = 5
- turb_naca0012_sst_restart_mg.test_vals = [-6.437400, -4.558626, 1.231779, -0.007820, 0.081480] #last 5 columns
+ turb_naca0012_sst_restart_mg.test_vals = [-6.437367, -4.558626, 1.231779, -0.007820, 0.081480] #last 5 columns
turb_naca0012_sst_restart_mg.su2_exec = "parallel_computation.py -f"
turb_naca0012_sst_restart_mg.timeout = 3200
turb_naca0012_sst_restart_mg.tol = 0.000001
@@ -795,7 +795,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.294362, 0.429473, 80.085570, 1.034776] #last 4 columns
+ Jones_tc.test_vals = [-5.301576, 0.418692, 78.467450, 0.990201] #last 4 columns
Jones_tc.su2_exec = "parallel_computation.py -f"
Jones_tc.timeout = 1600
Jones_tc.tol = 0.00001
@@ -806,7 +806,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.411257, -1.606960, 82.250600, 2.791316] #last 4 columns
+ Jones_tc_rst.test_vals = [-4.344743, -1.553291, 82.250600, 2.791916] #last 4 columns
Jones_tc_rst.su2_exec = "parallel_computation.py -f"
Jones_tc_rst.timeout = 1600
Jones_tc_rst.tol = 0.00001
@@ -817,7 +817,7 @@ def main():
axial_stage2D.cfg_dir = "turbomachinery/axial_stage_2D"
axial_stage2D.cfg_file = "Axial_stage2D.cfg"
axial_stage2D.test_iter = 20
- axial_stage2D.test_vals = [-1.835157, 5.788771, 73.679900, 0.888920] #last 4 columns
+ axial_stage2D.test_vals = [-1.789989, 5.695321, 73.361330, 0.904454] #last 4 columns
axial_stage2D.su2_exec = "parallel_computation.py -f"
axial_stage2D.timeout = 1600
axial_stage2D.tol = 0.00001
@@ -828,7 +828,7 @@ def main():
transonic_stator.cfg_dir = "turbomachinery/transonic_stator_2D"
transonic_stator.cfg_file = "transonic_stator.cfg"
transonic_stator.test_iter = 20
- transonic_stator.test_vals = [-1.106713, 6.115842, 67.308610, 0.071854] #last 4 columns
+ transonic_stator.test_vals = [-1.200053, 6.148389, 96.766110, 0.063114] #last 4 columns
transonic_stator.su2_exec = "parallel_computation.py -f"
transonic_stator.timeout = 1600
transonic_stator.tol = 0.00001
@@ -839,7 +839,7 @@ def main():
transonic_stator_rst.cfg_dir = "turbomachinery/transonic_stator_2D"
transonic_stator_rst.cfg_file = "transonic_stator_rst.cfg"
transonic_stator_rst.test_iter = 20
- transonic_stator_rst.test_vals = [-0.484635, 4.462656, 6.460177, 0.004009] #last 4 columns
+ transonic_stator_rst.test_vals = [-8.277744, -3.005768, 5.285371, 0.003100] #last 4 columns
transonic_stator_rst.su2_exec = "parallel_computation.py -f"
transonic_stator_rst.timeout = 1600
transonic_stator_rst.tol = 0.00001
@@ -926,7 +926,7 @@ def main():
bars_SST_2D.cfg_dir = "sliding_interface/bars_SST_2D"
bars_SST_2D.cfg_file = "bars.cfg"
bars_SST_2D.test_iter = 13
- bars_SST_2D.test_vals = [-2.133553, 1.644733, -0.000831, 0.117497] #last 4 columns
+ bars_SST_2D.test_vals = [-2.135568, 1.642185, -0.000830, 0.117498] #last 4 columns
bars_SST_2D.su2_exec = "SU2_CFD"
bars_SST_2D.timeout = 1600
bars_SST_2D.tol = 0.00001
diff --git a/TestCases/parallel_regression_AD.py b/TestCases/parallel_regression_AD.py
index c6648364d12e..4be85b76ba62 100644
--- a/TestCases/parallel_regression_AD.py
+++ b/TestCases/parallel_regression_AD.py
@@ -94,7 +94,7 @@ def main():
discadj_rans_naca0012_sa.cfg_dir = "disc_adj_rans/naca0012"
discadj_rans_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg"
discadj_rans_naca0012_sa.test_iter = 10
- discadj_rans_naca0012_sa.test_vals = [-1.751966, 0.485717, 0.183154, -0.000018] #last 4 columns
+ discadj_rans_naca0012_sa.test_vals = [-1.751966, 0.485697, 0.183154, -0.000018] #last 4 columns
discadj_rans_naca0012_sa.su2_exec = "parallel_computation.py -f"
discadj_rans_naca0012_sa.timeout = 1600
discadj_rans_naca0012_sa.tol = 0.00001
@@ -105,7 +105,7 @@ def main():
discadj_rans_naca0012_sst.cfg_dir = "disc_adj_rans/naca0012"
discadj_rans_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg"
discadj_rans_naca0012_sst.test_iter = 10
- discadj_rans_naca0012_sst.test_vals = [-1.654042, -0.500718, 0.154704, -0.000022] #last 4 columns
+ discadj_rans_naca0012_sst.test_vals = [-1.654042, -0.500944, 0.154703, -0.000022] #last 4 columns
discadj_rans_naca0012_sst.su2_exec = "parallel_computation.py -f"
discadj_rans_naca0012_sst.timeout = 1600
discadj_rans_naca0012_sst.tol = 0.00001
@@ -161,7 +161,7 @@ def main():
discadj_incomp_turb_NACA0012_sst.cfg_dir = "disc_adj_incomp_rans/naca0012"
discadj_incomp_turb_NACA0012_sst.cfg_file = "turb_naca0012_sst.cfg"
discadj_incomp_turb_NACA0012_sst.test_iter = 10
- discadj_incomp_turb_NACA0012_sst.test_vals = [-3.845805, -2.416675, 0.000000, 0.000000] #last 4 columns
+ discadj_incomp_turb_NACA0012_sst.test_vals = [-3.845805, -2.415680, 0.000000, 0.000000] #last 4 columns
discadj_incomp_turb_NACA0012_sst.su2_exec = "parallel_computation.py -f"
discadj_incomp_turb_NACA0012_sst.timeout = 1600
discadj_incomp_turb_NACA0012_sst.tol = 0.00001
@@ -208,7 +208,7 @@ def main():
discadj_trans_stator.cfg_dir = "disc_adj_turbomachinery/transonic_stator_2D"
discadj_trans_stator.cfg_file = "transonic_stator.cfg"
discadj_trans_stator.test_iter = 79
- discadj_trans_stator.test_vals = [-2.001082, -2.115018, -0.450986, -15.778292] #last 4 columns
+ discadj_trans_stator.test_vals = [-1.923943, -2.119689, -0.510185, -20.818664] #last 4 columns
discadj_trans_stator.su2_exec = "parallel_computation.py -f"
discadj_trans_stator.timeout = 1600
discadj_trans_stator.tol = 0.00001
@@ -238,7 +238,7 @@ def main():
discadj_heat.cfg_dir = "disc_adj_heat"
discadj_heat.cfg_file = "disc_adj_heat.cfg"
discadj_heat.test_iter = 10
- discadj_heat.test_vals = [3.183713, 0.923840, -223.197830, -2059.808372] #last 4 columns
+ discadj_heat.test_vals = [3.183906, 0.923840, -223.197830, -2059.808372] #last 4 columns
discadj_heat.su2_exec = "parallel_computation.py -f"
discadj_heat.timeout = 1600
discadj_heat.tol = 0.00001
diff --git a/TestCases/rans/vki_turbine/turb_vki.cfg b/TestCases/rans/vki_turbine/turb_vki.cfg
index c6ffca7e3995..23ec61bf5b2f 100644
--- a/TestCases/rans/vki_turbine/turb_vki.cfg
+++ b/TestCases/rans/vki_turbine/turb_vki.cfg
@@ -181,15 +181,6 @@ TIME_DISCRE_TURB= EULER_IMPLICIT
% Reduction factor of the CFL coefficient in the turbulence problem
CFL_REDUCTION_TURB= 1.0
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC, FULL, FULL_FLOW, GRAD_FLOW, FULL_ADJOINT,
-% GRAD_ADJOINT, GRAD_FLOW_ADJ, ROBUST,
-% FULL_LINEAR, COMPUTABLE, COMPUTABLE_ROBUST,
-% REMAINING, WAKE, SMOOTHING, SUPERSONIC_SHOCK,
-% TWOPHASE)
-KIND_ADAPT= PERIODIC
-
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
%
% Convergence criteria (CAUCHY, RESIDUAL)
@@ -218,7 +209,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= mesh_vki_turbine.su2
+MESH_FILENAME= mesh_vki_turbine_prepbc.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py
index 136002925bfa..121851b848f8 100644
--- a/TestCases/serial_regression.py
+++ b/TestCases/serial_regression.py
@@ -170,7 +170,7 @@ def main():
poiseuille.cfg_dir = "navierstokes/poiseuille"
poiseuille.cfg_file = "lam_poiseuille.cfg"
poiseuille.test_iter = 10
- poiseuille.test_vals = [-12.272146, -3.335311, 0.000001, 2.351005] #last 4 columns
+ poiseuille.test_vals = [-5.050732, 0.648355, 0.012273, 13.643219] #last 4 columns
poiseuille.su2_exec = "SU2_CFD"
poiseuille.timeout = 1600
poiseuille.tol = 0.00001
@@ -767,7 +767,7 @@ def main():
ls89_sa.cfg_dir = "nicf/LS89"
ls89_sa.cfg_file = "turb_SA_PR.cfg"
ls89_sa.test_iter = 20
- ls89_sa.test_vals = [-5.050658, -13.393664, 0.174911, 0.430700] #last 4 columns
+ ls89_sa.test_vals = [-5.046850, -13.386345, 0.174911, 0.430700] #last 4 columns
ls89_sa.su2_exec = "SU2_CFD"
ls89_sa.timeout = 1600
ls89_sa.tol = 0.00001
@@ -805,7 +805,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.304569, 0.419188, 80.085850, 1.034777] #last 4 columns
+ Jones_tc.test_vals = [-5.301588, 0.418684, 78.467650, 0.990182] #last 4 columns
Jones_tc.su2_exec = "SU2_CFD"
Jones_tc.timeout = 1600
Jones_tc.tol = 0.00001
@@ -816,7 +816,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.423322, -1.618510, 82.250600, 2.791319] #last 4 columns
+ Jones_tc_rst.test_vals = [-4.344742, -1.553279, 82.250600, 2.791916] #last 4 columns
Jones_tc_rst.su2_exec = "SU2_CFD"
Jones_tc_rst.timeout = 1600
Jones_tc_rst.tol = 0.00001
@@ -827,7 +827,7 @@ def main():
axial_stage2D.cfg_dir = "turbomachinery/axial_stage_2D"
axial_stage2D.cfg_file = "Axial_stage2D.cfg"
axial_stage2D.test_iter = 20
- axial_stage2D.test_vals = [-1.837052, 5.787185, 73.679900, 0.888919] #last 4 columns
+ axial_stage2D.test_vals = [-1.789990, 5.695319, 73.361330, 0.904458] #last 4 columns
axial_stage2D.su2_exec = "SU2_CFD"
axial_stage2D.timeout = 1600
axial_stage2D.tol = 0.00001
@@ -838,7 +838,7 @@ def main():
transonic_stator.cfg_dir = "turbomachinery/transonic_stator_2D"
transonic_stator.cfg_file = "transonic_stator.cfg"
transonic_stator.test_iter = 20
- transonic_stator.test_vals = [-1.114556, 6.120416, 67.101480, 0.070037] #last 4 columns
+ transonic_stator.test_vals = [-1.202869, 6.150690, 96.239500, 0.062740] #last 4 columns
transonic_stator.su2_exec = "SU2_CFD"
transonic_stator.timeout = 1600
transonic_stator.tol = 0.00001
@@ -849,7 +849,7 @@ def main():
transonic_stator_rst.cfg_dir = "turbomachinery/transonic_stator_2D"
transonic_stator_rst.cfg_file = "transonic_stator_rst.cfg"
transonic_stator_rst.test_iter = 20
- transonic_stator_rst.test_vals = [-0.486965, 4.460638, 6.455770, 0.004009] #last 4 columns
+ transonic_stator_rst.test_vals = [-8.277755, -3.005732, 5.285371, 0.003100] #last 4 columns
transonic_stator_rst.su2_exec = "SU2_CFD"
transonic_stator_rst.timeout = 1600
transonic_stator_rst.tol = 0.00001
@@ -937,7 +937,7 @@ def main():
bars_SST_2D.cfg_dir = "sliding_interface/bars_SST_2D"
bars_SST_2D.cfg_file = "bars.cfg"
bars_SST_2D.test_iter = 13
- bars_SST_2D.test_vals = [-2.138791, 1.639495, -0.000831, 0.117497] #last 4 columns
+ bars_SST_2D.test_vals = [-2.135568, 1.642185, -0.000830, 0.117498] #last 4 columns
bars_SST_2D.su2_exec = "SU2_CFD"
bars_SST_2D.timeout = 1600
bars_SST_2D.tol = 0.00001
diff --git a/TestCases/sliding_interface/bars_SST_2D/bars.cfg b/TestCases/sliding_interface/bars_SST_2D/bars.cfg
index b414130021bc..524b37b73836 100644
--- a/TestCases/sliding_interface/bars_SST_2D/bars.cfg
+++ b/TestCases/sliding_interface/bars_SST_2D/bars.cfg
@@ -255,19 +255,6 @@ TIME_DISCRE_TURB= EULER_IMPLICIT
% Reduction factor of the CFL coefficient in the turbulence problem
CFL_REDUCTION_TURB= 0.10
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC, FULL, FULL_FLOW, GRAD_FLOW, FULL_ADJOINT,
-% GRAD_ADJOINT, GRAD_FLOW_ADJ, ROBUST,
-% FULL_LINEAR, COMPUTABLE, COMPUTABLE_ROBUST,
-% REMAINING, WAKE, SMOOTHING, SUPERSONIC_SHOCK,
-% TWOPHASE)
-KIND_ADAPT= PERIODIC
-
-% --------------------------- PARTITIONING STRATEGY ---------------------------%
-% Write a tecplot/paraview file for each partition (NO, YES)
-%VISUALIZE_PART= YES
-
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
%
% Convergence criteria (CAUCHY, RESIDUAL)
@@ -301,7 +288,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= mesh_bars.su2
+MESH_FILENAME= mesh_bars_turb.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/sliding_interface/incompressible_steady/config.cfg b/TestCases/sliding_interface/incompressible_steady/config.cfg
index 3f0a2c81b071..9a0792a3e61e 100644
--- a/TestCases/sliding_interface/incompressible_steady/config.cfg
+++ b/TestCases/sliding_interface/incompressible_steady/config.cfg
@@ -19,4 +19,4 @@ MESH_FILENAME= meshCircle.su2
TIME_DOMAIN = NO
-OUTER_ITER = 20
+OUTER_ITER = 21
diff --git a/TestCases/turbomachinery/APU_turbocharger/Jones.cfg b/TestCases/turbomachinery/APU_turbocharger/Jones.cfg
index 171709d2d18e..f98025a5b4e5 100755
--- a/TestCases/turbomachinery/APU_turbocharger/Jones.cfg
+++ b/TestCases/turbomachinery/APU_turbocharger/Jones.cfg
@@ -180,13 +180,6 @@ AVERAGE_MACH_LIMIT= 0.05
% Marker(s) of the surface in the surface flow solution file
MARKER_PLOTTING= (BLADE1, BLADE2)
%
-%
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC)
-KIND_ADAPT= PERIODIC
-%
-%
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
%
% Dynamic mesh simulation (NO, YES)
@@ -327,7 +320,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= jones_turbine.su2
+MESH_FILENAME= mesh_jones_turbine.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/turbomachinery/APU_turbocharger/Jones_rst.cfg b/TestCases/turbomachinery/APU_turbocharger/Jones_rst.cfg
index a0898c32ae9f..5528a7a2c774 100755
--- a/TestCases/turbomachinery/APU_turbocharger/Jones_rst.cfg
+++ b/TestCases/turbomachinery/APU_turbocharger/Jones_rst.cfg
@@ -185,12 +185,6 @@ AVERAGE_MACH_LIMIT= 0.05
MARKER_PLOTTING= (BLADE1, BLADE2)
%
%
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC)
-KIND_ADAPT= PERIODIC
-%
-%
% ----------------------- DYNAMIC MESH DEFINITION -----------------------------%
%
% Dynamic mesh simulation (NO, YES)
@@ -331,7 +325,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= jones_turbine.su2
+MESH_FILENAME= mesh_jones_turbine.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg b/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
index d91cfaeaf61d..bcb864b7a7b9 100755
--- a/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
+++ b/TestCases/turbomachinery/axial_stage_2D/Axial_stage2D.cfg
@@ -171,13 +171,6 @@ AVERAGE_MACH_LIMIT= 0.05
% Marker(s) of the surface in the surface flow solution file
MARKER_PLOTTING= (wall1, wall2)
%
-%
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC)
-KIND_ADAPT= PERIODIC
-%
-%
% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------%
%
% Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES)
@@ -317,7 +310,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= axial_stage_2D.su2
+MESH_FILENAME= mesh_axial_stage_2d_turb.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
index 71ce29e8e224..06c2f86c0347 100644
--- a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
+++ b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator.cfg
@@ -184,13 +184,6 @@ MARKER_PLOTTING= (airfoil)
% Marker(s) of the surface where the non-dimensional coefficients are evaluated.
MARKER_MONITORING= (airfoil)
%
-%
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC)
-KIND_ADAPT= PERIODIC
-%
-%
% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------%
%
% Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES)
@@ -315,7 +308,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= su2mesh_per.su2
+MESH_FILENAME= mesh_stator_turb.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
diff --git a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
index b933d61ca7d2..e313fe53f200 100644
--- a/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
+++ b/TestCases/turbomachinery/transonic_stator_2D/transonic_stator_rst.cfg
@@ -189,13 +189,6 @@ MARKER_PLOTTING= (airfoil)
% Marker(s) of the surface where the non-dimensional coefficients are evaluated.
MARKER_MONITORING= (airfoil)
%
-%
-% ------------------------- GRID ADAPTATION STRATEGY --------------------------%
-%
-% Kind of grid adaptation (NONE, PERIODIC)
-KIND_ADAPT= PERIODIC
-%
-%
% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------%
%
% Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES)
@@ -320,7 +313,7 @@ CAUCHY_FUNC_FLOW= DRAG
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
%
% Mesh input file
-MESH_FILENAME= su2mesh_per.su2
+MESH_FILENAME= mesh_stator_turb.su2
%
% Mesh input file format (SU2, CGNS, NETCDF_ASCII)
MESH_FORMAT= SU2
@@ -329,7 +322,7 @@ MESH_FORMAT= SU2
MESH_OUT_FILENAME= su2mesh_per.su2
%
% Restart flow input file
-SOLUTION_FLOW_FILENAME= solution_flow.dat
+SOLUTION_FLOW_FILENAME= solution_flow_sst.dat
%
% Restart adjoint input file
SOLUTION_ADJ_FILENAME= solution_adj.dat