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
3334CRadialBasisFunctionInterpolation::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
279281void 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
355361void 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
497547void 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
535583void 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