Skip to content

Commit 636b611

Browse files
committed
working version parallel computation with greedy algorithm as data reduction
1 parent 6344d27 commit 636b611

3 files changed

Lines changed: 202 additions & 36 deletions

File tree

Common/include/grid_movement/CRadialBasisFunctionInterpolation.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ class CRadialBasisFunctionInterpolation : public CVolumetricMovement {
6161
bool dataReduction; /*!< \brief Determines whether data reduction is used. */
6262
unsigned long MaxErrorNode;
6363
su2double MaxError;
64-
64+
su2double GreedyTolerance;
65+
su2double GreedyCorrectionFactor;
6566

6667
unsigned long Global_nControlNodes{0};
6768
/*--- mpi related*/
@@ -71,6 +72,7 @@ class CRadialBasisFunctionInterpolation : public CVolumetricMovement {
7172

7273
// vector<su2double> LocalCoords;
7374
vector<su2double> GlobalCoords;
75+
7476

7577

7678

@@ -174,4 +176,10 @@ class CRadialBasisFunctionInterpolation : public CVolumetricMovement {
174176
void GetInitMaxErrorNode(CGeometry* geometry, CConfig* config);
175177

176178
void MPI_Operations(CGeometry* geometry);
179+
180+
su2double GetError(CGeometry* geometry, CConfig* config);
181+
182+
su2double* GetNodalError(CGeometry* geometry, CConfig* config, unsigned long iNode, su2double* localError);
183+
184+
void SetCorrection(CGeometry* geometry);
177185
};

Common/include/grid_movement/CRadialBasisFunctionNode.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ class CRadialBasisFunctionNode{
4141
unsigned short marker_idx; /*!< \brief Marker index. */
4242
unsigned long vertex_idx; /*!< \brief Vertex index. */
4343

44+
su2double error[3];
4445

45-
public:
46+
47+
public:
4648

4749
/*!
4850
* \brief Constructor of the class.
@@ -64,4 +66,10 @@ class CRadialBasisFunctionNode{
6466
*/
6567
inline unsigned short GetMarker(void){return marker_idx;}
6668

69+
inline void SetError(const su2double* val_error, unsigned short nDim) {
70+
for (unsigned short iDim = 0; iDim < nDim; iDim++) error[iDim] = val_error[iDim];
71+
}
72+
73+
inline su2double* GetError(void){ return error;}
74+
6775
};

Common/src/grid_movement/CRadialBasisFunctionInterpolation.cpp

Lines changed: 184 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "../../include/grid_movement/CRadialBasisFunctionInterpolation.hpp"
2929
#include "../../include/interface_interpolation/CRadialBasisFunction.hpp"
3030
#include "../../include/toolboxes/geometry_toolbox.hpp"
31+
#include "../../include/adt/CADTPointsOnlyClass.hpp"
3132

3233

3334
CRadialBasisFunctionInterpolation::CRadialBasisFunctionInterpolation(CGeometry* geometry, CConfig* config) : CVolumetricMovement(geometry) {
@@ -41,6 +42,8 @@ CRadialBasisFunctionInterpolation::CRadialBasisFunctionInterpolation(CGeometry*
4142

4243
if(dataReduction){
4344
controlNodes = &greedyNodes;
45+
GreedyTolerance = config->GetRBF_GreedyTolerance();
46+
GreedyCorrectionFactor = config->GetRBF_GreedyCorrectionFactor();
4447
}else{
4548
controlNodes = &boundaryNodes;
4649
}
@@ -135,7 +138,6 @@ void CRadialBasisFunctionInterpolation::GetInterpolationCoefficients(CGeometry*
135138

136139

137140
if(dataReduction){
138-
139141
GreedyIteration(geometry, config);
140142
}else{
141143
//TODO find more elegant way to assign this variable
@@ -277,7 +279,6 @@ void CRadialBasisFunctionInterpolation::SetInterpolationMatrix(CGeometry* geomet
277279
}
278280

279281
void CRadialBasisFunctionInterpolation::SetDeformationVector(CGeometry* geometry, CConfig* config){
280-
281282
/* --- Initialization of the deformation vector ---*/
282283
deformationVector.resize(controlNodes->size()*nDim, 0.0);
283284

@@ -289,14 +290,18 @@ void CRadialBasisFunctionInterpolation::SetDeformationVector(CGeometry* geometry
289290
/*--- Setting nonzero displacements of the moving markers ---*/
290291
for (auto i = 0; i < controlNodes->size(); i++) {
291292

292-
if (config->GetMarker_All_Moving((*controlNodes)[i]->GetMarker())) {
293+
if (config->GetMarker_All_Moving((*controlNodes)[i]->GetMarker())) {
294+
293295
for (auto iDim = 0; iDim < nDim; iDim++) {
294296
deformationVector[i+iDim*controlNodes->size()] = SU2_TYPE::GetValue(geometry->vertex[(*controlNodes)[i]->GetMarker()][(*controlNodes)[i]->GetVertex()]->GetVarCoord()[iDim] * VarIncrement);
295297
}
298+
}else{
299+
for (auto iDim = 0; iDim < nDim; iDim++) {
300+
deformationVector[i+iDim*controlNodes->size()] = 0.0;
301+
}
296302
}
297303
}
298304

299-
300305
#ifdef HAVE_MPI
301306

302307
/*--- Gathering all deformation vectors on the master node ---*/
@@ -350,6 +355,7 @@ void CRadialBasisFunctionInterpolation::SetDeformationVector(CGeometry* geometry
350355
}
351356

352357
#endif
358+
353359
}
354360

355361
void CRadialBasisFunctionInterpolation::SetInternalNodes(CGeometry* geometry, CConfig* config ){
@@ -443,14 +449,13 @@ void CRadialBasisFunctionInterpolation::UpdateGridCoord(CGeometry* geometry, CCo
443449
unsigned short iDim;
444450

445451
/*--- Vector for storing the coordinate variation ---*/
446-
su2double var_coord[nDim];
452+
su2double var_coord[nDim]{0.0};
447453

448454
/*--- Loop over the internal nodes ---*/
449455
for(iNode = 0; iNode < nInternalNodes; iNode++){
450-
451456
/*--- Loop for contribution of each control node ---*/
452457
for(cNode = 0; cNode < Global_nControlNodes; cNode++){
453-
458+
454459
/*--- Determine distance between considered internal and control node ---*/
455460
su2double dist;
456461

@@ -477,11 +482,52 @@ void CRadialBasisFunctionInterpolation::UpdateGridCoord(CGeometry* geometry, CCo
477482
var_coord[iDim] = 0;
478483
}
479484
}
485+
486+
if(dataReduction){
487+
// setting the coords of the boundary nodes (non-control) in case of greedy
488+
for(iNode = 0; iNode < nBoundaryNodes; iNode++){
489+
// cout << rank << " " << geometry->nodes->GetGlobalIndex(boundaryNodes[iNode]->GetIndex()) << endl;
490+
for(cNode = 0; cNode < Global_nControlNodes; cNode++){
491+
492+
493+
su2double dist;
494+
495+
#ifdef HAVE_MPI
496+
dist = 0;
497+
for ( iDim = 0; iDim < nDim; iDim++) dist += pow(GlobalCoords[cNode * nDim + iDim] - geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex())[iDim], 2);
498+
dist = sqrt(dist);
499+
#else
500+
dist = GeometryToolbox::Distance(nDim, geometry->nodes->GetCoord((*controlNodes)[cNode]->GetIndex()), geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex()));
501+
#endif
502+
503+
// auto dist = GeometryToolbox::Distance(nDim, geometry->nodes->GetCoord((*controlNodes)[cNode]->GetIndex()), geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex()));
504+
505+
auto rbf = SU2_TYPE::GetValue(CRadialBasisFunction::Get_RadialBasisValue(kindRBF, radius, dist));
506+
507+
for( iDim = 0; iDim < nDim; iDim++){
508+
var_coord[iDim] += rbf*coefficients[cNode + iDim*Global_nControlNodes];
509+
}
510+
}
511+
512+
for(iDim = 0; iDim < nDim; iDim++){
513+
geometry->nodes->AddCoord(boundaryNodes[iNode]->GetIndex(), iDim, var_coord[iDim]);
514+
var_coord[iDim] = 0;
515+
}
516+
517+
// auto err = boundaryNodes[iNode]->GetError();
518+
// // cout << boundaryNodes[iNode]->GetIndex() << '\t' << err[0] << '\t' << err[1] << endl;
519+
// for(iDim = 0; iDim < nDim; iDim++){
520+
// geometry->nodes->AddCoord(boundaryNodes[iNode]->GetIndex(), iDim, -err[iDim]);
521+
// }
522+
523+
}
524+
}
480525

481526
/*--- Applying the surface deformation, which are stored in the deformation vector ---*/
482527

483528
unsigned long nControlNodes = deformationVector.size()/nDim; // size on master_node is different in case of mpi
484-
for(cNode = 0; cNode < nControlNodes; cNode++){
529+
for(cNode = 0; cNode < Local_nControlNodes; cNode++){ //TODO for sequential computation Local_nControlNodes should be replaced by nControlNodes
530+
485531
if(config->GetMarker_All_Moving((*controlNodes)[cNode]->GetMarker())){
486532
for(iDim = 0; iDim < nDim; iDim++){
487533
#ifdef HAVE_MPI //TODO these are now the same statements
@@ -492,6 +538,10 @@ void CRadialBasisFunctionInterpolation::UpdateGridCoord(CGeometry* geometry, CCo
492538
}
493539
}
494540
}
541+
542+
if(dataReduction){
543+
SetCorrection(geometry);
544+
}
495545
}
496546

497547
void CRadialBasisFunctionInterpolation::GreedyIteration(CGeometry* geometry, CConfig* config) {
@@ -503,33 +553,31 @@ void CRadialBasisFunctionInterpolation::GreedyIteration(CGeometry* geometry, CCo
503553

504554
unsigned short greedyIter = 0;
505555

506-
// Gathering the init greedy nodes
507-
unsigned long MaxErrorNodes[size];
508-
SU2_MPI::Gather(&MaxErrorNode, 1, MPI_UNSIGNED_LONG, MaxErrorNodes, 1, MPI_UNSIGNED_LONG, MASTER_NODE, SU2_MPI::GetComm());
509-
556+
while(MaxError > GreedyTolerance){
510557

511-
//gathering the coordinates of the selected greedy nodes. This array should be available on the masternode throughout the greedy iteration.
512-
513-
vector<su2double> selectedCoords(nDim); // for now a single node is selected; can be an array?
514-
auto coord = geometry->nodes->GetCoord(boundaryNodes[MaxErrorNode]->GetIndex());
558+
if(rank == MASTER_NODE) cout << "Greedy iteration: " << ++greedyIter << ". Max error: " << MaxError << endl;
559+
// cout << "iteration: " << greedyIter << ". error: " << MaxError << endl;
515560

516-
for(auto iDim = 0; iDim < nDim; iDim++){
517-
selectedCoords[iDim] = coord[iDim];
518-
}
519-
vector<su2double> greedyCoords;
520-
if(rank==MASTER_NODE){
521-
greedyCoords.resize(nDim*size);
522-
}
523-
SU2_MPI::Gather(selectedCoords.data(), nDim, MPI_DOUBLE, greedyCoords.data(), nDim, MPI_DOUBLE, MASTER_NODE, SU2_MPI::GetComm());
524-
//TODO what if a different number of greedy nodes are selected?
561+
//--------------------
562+
//TODO collect next statements in AddNode function
563+
greedyNodes.push_back(move(boundaryNodes[MaxErrorNode]));
525564

526-
if (rank == MASTER_NODE){
527-
for(auto x : greedyCoords){cout << x << endl;}
528-
}
565+
boundaryNodes.erase(boundaryNodes.begin()+MaxErrorNode);
566+
nBoundaryNodes--;
567+
568+
MPI_Operations(geometry);
569+
570+
//-------------------
529571

572+
SetDeformationVector(geometry, config);
530573

531-
SU2_MPI::Barrier(SU2_MPI::GetComm());
532-
SU2_MPI::Abort(SU2_MPI::GetComm(), 0);
574+
SetInterpolationMatrix(geometry, config);
575+
576+
SolveRBF_System();
577+
578+
MaxError = GetError(geometry, config);
579+
580+
}
533581
}
534582

535583
void CRadialBasisFunctionInterpolation::GetInitMaxErrorNode(CGeometry* geometry, CConfig* config){
@@ -547,7 +595,11 @@ void CRadialBasisFunctionInterpolation::GetInitMaxErrorNode(CGeometry* geometry,
547595
}
548596
}
549597
MaxError = sqrt(maxDeformation) / ((su2double)config->GetGridDef_Nonlinear_Iter());
550-
// cout << "rank: " << rank << " Max error node: " << MaxErrorNode << endl;
598+
599+
#ifdef HAVE_MPI
600+
su2double localMaxError = MaxError;
601+
SU2_MPI::Reduce(&localMaxError, &MaxError, 1, MPI_DOUBLE, MPI_MAX, MASTER_NODE, SU2_MPI::GetComm());
602+
#endif
551603
}
552604

553605

@@ -595,8 +647,106 @@ void CRadialBasisFunctionInterpolation::MPI_Operations(CGeometry* geometry){
595647
}else{
596648
disps[x] = disps[x-1]+LocalCoordsSizes[x-1];
597649
}
598-
}
599-
650+
}
600651
/*--- making global control node coordinates available on all processes ---*/
601652
SU2_MPI::Allgatherv(LocalCoords.data(), localCoordsSize, MPI_DOUBLE, GlobalCoords.data(), LocalCoordsSizes, disps, MPI_DOUBLE, SU2_MPI::GetComm()); //TODO local coords can be deleted after this operation
602-
};
653+
654+
655+
};
656+
657+
658+
su2double CRadialBasisFunctionInterpolation::GetError(CGeometry* geometry, CConfig* config){
659+
unsigned long iNode;
660+
unsigned short iDim;
661+
su2double localError[nDim];
662+
663+
su2double error = 0.0, errorMagnitude;
664+
665+
for(iNode = 0; iNode < nBoundaryNodes; iNode++){
666+
667+
boundaryNodes[iNode]->SetError(GetNodalError(geometry, config, iNode, localError), nDim);
668+
669+
errorMagnitude = GeometryToolbox::Norm(nDim, localError);
670+
if(errorMagnitude > error){
671+
error = errorMagnitude;
672+
MaxErrorNode = iNode;
673+
}
674+
}
675+
return error;
676+
}
677+
678+
su2double* CRadialBasisFunctionInterpolation::GetNodalError(CGeometry* geometry, CConfig* config, unsigned long iNode, su2double* localError){
679+
unsigned short iDim;
680+
su2double* displacement;
681+
su2double VarIncrement = 1.0 / ((su2double)config->GetGridDef_Nonlinear_Iter());
682+
if(config->GetMarker_All_Moving(boundaryNodes[iNode]->GetMarker())){
683+
displacement = geometry->vertex[boundaryNodes[iNode]->GetMarker()][boundaryNodes[iNode]->GetVertex()]->GetVarCoord();
684+
// cout << boundaryNodes[iNode]->GetIndex() << '\t' << displacement[0] << '\t' << displacement[1] << endl;
685+
for(iDim = 0; iDim < nDim; iDim++){
686+
localError[iDim] = -displacement[iDim] * VarIncrement;
687+
}
688+
}else{
689+
for(iDim = 0; iDim < nDim; iDim++){
690+
localError[iDim] = 0;
691+
}
692+
}
693+
694+
for(auto cNode = 0; cNode < Global_nControlNodes; cNode++){ //TODO here
695+
su2double dist;
696+
697+
#ifdef HAVE_MPI
698+
dist = 0;
699+
for ( iDim = 0; iDim < nDim; iDim++) dist += pow(GlobalCoords[cNode * nDim + iDim] - geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex())[iDim], 2);
700+
dist = sqrt(dist);
701+
#else
702+
dist = GeometryToolbox::Distance(nDim, geometry->nodes->GetCoord((*controlNodes)[cNode]->GetIndex()), geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex()));
703+
#endif
704+
// auto dist = GeometryToolbox::Distance(nDim, geometry->nodes->GetCoord((*controlNodes)[cNode]->GetIndex()), geometry->nodes->GetCoord(boundaryNodes[iNode]->GetIndex()));
705+
706+
auto rbf = SU2_TYPE::GetValue(CRadialBasisFunction::Get_RadialBasisValue(kindRBF, radius, dist));
707+
708+
for( iDim = 0; iDim < nDim; iDim++){
709+
localError[iDim] += rbf*coefficients[cNode + iDim*Global_nControlNodes];
710+
}
711+
}
712+
// cout << boundaryNodes[iNode]->GetIndex() << '\t' << localError[0] << '\t' << localError[1] << endl;
713+
return localError;
714+
}
715+
716+
void CRadialBasisFunctionInterpolation::SetCorrection(CGeometry* geometry){
717+
unsigned long iVertex, iNode, iDim, i, j, pointID;
718+
unsigned long nVertexBound = nBoundaryNodes;
719+
su2double dist;
720+
vector<su2double> Coord_bound(nDim*nVertexBound);
721+
vector<unsigned long> PointIDs(nVertexBound);
722+
int rankID;
723+
724+
su2double CorrectionRadius = GreedyCorrectionFactor*MaxError;
725+
i = 0;
726+
j = 0;
727+
for(iVertex = 0; iVertex < nVertexBound; iVertex++){
728+
iNode = boundaryNodes[iVertex]->GetIndex();
729+
PointIDs[i++] = iVertex;
730+
for(iDim = 0; iDim < nDim; iDim++){
731+
Coord_bound[j++] = geometry->nodes->GetCoord(iNode, iDim);
732+
}
733+
}
734+
735+
CADTPointsOnlyClass BoundADT(nDim, nVertexBound, Coord_bound.data(), PointIDs.data(), true);
736+
737+
for(iNode = 0; iNode < nInternalNodes; iNode++){
738+
BoundADT.DetermineNearestNode(geometry->nodes->GetCoord(internalNodes[iNode]), dist, pointID, rankID);
739+
auto err = boundaryNodes[pointID]->GetError();
740+
auto rbf = SU2_TYPE::GetValue(CRadialBasisFunction::Get_RadialBasisValue(kindRBF, CorrectionRadius, dist));
741+
for(iDim = 0; iDim < nDim; iDim++){
742+
geometry->nodes->AddCoord(internalNodes[iNode], iDim, -rbf*err[iDim]);
743+
}
744+
}
745+
746+
for(iNode = 0; iNode < nBoundaryNodes; iNode++){
747+
auto err = boundaryNodes[iNode]->GetError();
748+
for(iDim = 0; iDim < nDim; iDim++){
749+
geometry->nodes->AddCoord(boundaryNodes[iNode]->GetIndex(), iDim, -err[iDim]);
750+
}
751+
}
752+
}

0 commit comments

Comments
 (0)