Loading...
Searching...
No Matches
rbf.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25#include <cassert>
26#include <cmath>
27#include <set>
28
29#include "bitpit_private_lapacke.hpp"
30
31#include "bitpit_common.hpp"
32#include "bitpit_operators.hpp"
33
34#include "rbf.hpp"
35
36namespace bitpit {
37
65 : m_supportRadii(1, 1.)
66{
67 m_nodes = 0;
68 m_fields = 0;
69
70 m_mode = RBFMode::INTERP;
71
72 m_maxFields = -1;
73 m_value.clear();
74 m_weight.clear();
75 m_activeNodes.clear();
76
78
79 m_polyEnabled = false;
80 m_polyActiveBasis.clear();
81 m_polynomial.clear();
82}
83
88 : m_fields(other.m_fields), m_mode(other.m_mode),
89 m_supportRadii(other.m_supportRadii), m_typef(other.m_typef),
90 m_fPtr(other.m_fPtr), m_error(other.m_error), m_value(other.m_value),
91 m_weight(other.m_weight), m_activeNodes(other.m_activeNodes),
92 m_maxFields(other.m_maxFields), m_nodes(other.m_nodes),
93 m_polyEnabled(other.m_polyEnabled), m_polyActiveBasis(other.m_polyActiveBasis),
94 m_polynomial(other.m_polynomial)
95{
96}
97
103void RBFKernel::swap(RBFKernel &other) noexcept
104{
105 std::swap(m_fields, other.m_fields);
106 std::swap(m_mode, other.m_mode);
107 std::swap(m_supportRadii, other.m_supportRadii);
108 std::swap(m_typef, other.m_typef);
109 std::swap(m_fPtr, other.m_fPtr);
110 std::swap(m_error, other.m_error);
111 std::swap(m_value, other.m_value);
112 std::swap(m_weight, other.m_weight);
113 std::swap(m_activeNodes, other.m_activeNodes);
114 std::swap(m_maxFields, other.m_maxFields);
115 std::swap(m_nodes, other.m_nodes);
116 std::swap(m_polyEnabled, other.m_polyEnabled);
117 std::swap(m_polyActiveBasis, other.m_polyActiveBasis);
118 std::swap(m_polynomial, other.m_polynomial);
119}
120
126{
127 switch(bfunc){
128
132 break;
133
136 m_typef = RBFBasisFunction::LINEAR;
137 break;
138
142 break;
143
147 break;
148
152 break;
153
156 m_typef = RBFBasisFunction::C1C0;
157 break;
158
161 m_typef = RBFBasisFunction::C2C0;
162 break;
163
166 m_typef = RBFBasisFunction::C0C1;
167 break;
168
171 m_typef = RBFBasisFunction::C1C1;
172 break;
173
176 m_typef = RBFBasisFunction::C2C1;
177 break;
178
181 m_typef = RBFBasisFunction::C0C2;
182 break;
183
186 m_typef = RBFBasisFunction::C1C2;
187 break;
188
191 m_typef = RBFBasisFunction::C2C2;
192 break;
193
197 break;
198
202 break;
203
204 default:
207 break;
208 }
209}
210
215void RBFKernel::setFunction( double (&bfunc)(double ) )
216{
217 m_fPtr = bfunc;
218 m_typef = RBFBasisFunction::CUSTOM;
219}
220
226{
227 return m_typef;
228}
229
237{
238 return m_fields;
239}
240
246{
247 int nActive(0);
248
249 for( bool active : m_activeNodes)
250 nActive += (int) active;
251
252 return nActive;
253}
254
259std::vector<int> RBFKernel::getActiveSet( )
260{
261 int i(0);
262 std::vector<int> activeSet;
263
264 activeSet.reserve( getActiveCount() );
265
266 for( bool active : m_activeNodes) {
267 if( active )
268 activeSet.push_back(i);
269 ++i;
270 }
271
272 return activeSet;
273}
274
281{
282 if(n<0 || n >= int(m_activeNodes.size())) {
283 return false;
284 }
285
286 return m_activeNodes[n];
287}
288
295{
296 bool check = false;
297 if(n>=0 && n<m_nodes) {
298 m_activeNodes[n] = true;
299 check = true;
300 }
301 return check;
302}
303
309bool RBFKernel::activateNode(const std::vector<int> & list)
310{
311 if(list.empty()) {
312 return false;
313 }
314
315 bool check = true;
316 for(int index : list) {
317 check = check && activateNode(index);
318 }
319 return check;
320}
321
326{
327 std::fill(m_activeNodes.begin(), m_activeNodes.end(), true);
328}
329
336{
337 bool check = false;
338 if(n>=0 && n<m_nodes) {
339 m_activeNodes[n] = false;
340 check= true;
341 }
342 return check;
343}
344
350bool RBFKernel::deactivateNode(const std::vector<int> & list)
351{
352 if(list.empty()) {
353 return false;
354 }
355
356 bool check = true;
357 for(int index : list) {
358 check = check && deactivateNode(index);
359 }
360 return check;
361}
362
367{
368 std::fill(m_activeNodes.begin(), m_activeNodes.end(), false);
369}
370
375void RBFKernel::setSupportRadius( double radius )
376{
377 m_supportRadii.resize(1);
378 m_supportRadii[0] = radius;
379}
380
385void RBFKernel::setSupportRadius( const std::vector<double> & radius )
386{
387 m_supportRadii = radius;
388}
389
398{
399 return m_supportRadii[0];
400}
401
410{
411 bool variableSupportRadius = (m_supportRadii.size() != 1);
412 if (!variableSupportRadius) {
413 return m_supportRadii[0];
414 }
415
416 return m_supportRadii[i];
417}
418
424{
425 return m_mode;
426}
427
433{
434 m_mode = mode;
435}
436
444void RBFKernel::setDataToNode( int id, const std::vector<double> &value )
445{
446 if(id<0 || id >= m_fields) {
447 return;
448 }
449
450 if((int)(value.size()) != m_fields) {
451 log::cout() << "Mismatch dimension between value vector size and number of data attached to rbf.";
452 log::cout() << "This may lead to nasty errors. Check it with getDataCount()!" << std::endl;
453 log::cout() << "Data could not be set" << std::endl;
454 return;
455 }
456
457 int i;
458 if(m_mode != RBFMode::PARAM) {
459 for( i=0; i<m_fields; ++i ) {
460 m_value[i][id] = value[i];
461 }
462 }else{
463 for( i=0; i<m_fields; ++i ) {
464 m_weight[i][id] = value[i];
465 }
466 }
467}
468
476void RBFKernel::setDataToAllNodes( int id, const std::vector<double> &value )
477{
478 if(id<0 || id >= m_fields) {
479 return;
480 }
481
482 int size = m_value[id].size();
483
484 if((int)(value.size()) != size) {
485 log::cout() << "Mismatch dimension between data vector and current data container. One or both does not match RBFKernel nodes count.";
486 log::cout() << "This may lead to nasty errors. Use fitDataToNodes to reshape container or fit your data vector first!" << std::endl;
487 log::cout() << "Data could not be set" << std::endl;
488 return;
489 }
490 if(m_mode != RBFMode::PARAM) {
491 m_value[id] = value;
492 }else{
493 m_weight[id] = value;
494 }
495}
496
505{
506 if(m_fields == m_maxFields) {
507 log::cout() << "Maximum number of data set reached" << std::endl;
508 return -1;
509 }
510 m_fields++;
511 fitDataToNodes(m_fields-1);
512 return m_fields;
513}
514
525int RBFKernel::addData( const std::vector<double> & data )
526{
527 if(m_fields == m_maxFields) {
528 log::cout() << "Maximum number of data set reached" << std::endl;
529 return -1;
530 }
531 if(m_mode == RBFMode::INTERP) m_value.push_back(data);
532 else m_weight.push_back(data);
533 m_fields++;
534
535 return m_fields;
536}
537
544{
545 if(id<0 || id >=m_fields) {
546 return false;
547 }
548
549 m_fields--;
550 if(m_mode == RBFMode::INTERP) m_value.erase(m_value.begin()+id);
551 else m_weight.erase(m_weight.begin()+id);
552
553 return(true);
554}
555
563bool RBFKernel::removeData(std::vector<int> & list)
564{
565 // List should be processed in reversed order because data
566 // are removed using their position in the storages.
567 std::sort(list.begin(), list.end(), std::greater<int>());
568
569 int nInitialFields = getDataCount();
570 for(int id : list) {
571 removeData(id);
572 }
573 int nFinalFields = getDataCount();
574
575 return ((nInitialFields - nFinalFields) == static_cast<int>(list.size()));
576}
577
583{
584 m_fields = 0;
585 if(m_mode == RBFMode::INTERP) m_value.clear();
586 else m_weight.clear();
587}
588
597std::vector<double> RBFKernel::evalRBF( const std::array<double,3> &point)
598{
599 std::vector<double> values(m_fields, 0.);
600 int i, j;
601 double dist, basis;
602
603 for( i=0; i<m_nodes; ++i ){
604 if( m_activeNodes[i] ) {
605 dist = calcDist(point, i) / getSupportRadius(i);
606 basis = evalBasis( dist );
607
608 for( j=0; j<m_fields; ++j) {
609 values[j] += basis * m_weight[j][i];
610 }
611 }
612 }
613
614 // If INTERP mode add the polynomial contribution
615 if (m_mode == RBFMode::INTERP && m_polyEnabled) {
616 for (j = 0; j < m_fields; ++j) {
617 double *polynomialCoefficients = m_polynomial.getCoefficients(j);
618 std::vector<double> basis = evalPolynomialBasis(point);
619 int z = 0;
620 for (int iactive : m_polyActiveBasis) {
621 values[j] += polynomialCoefficients[iactive] * basis[z];
622 z++;
623 }
624 }
625 }
626
627 return values;
628}
629
638std::vector<double> RBFKernel::evalRBF(int jnode)
639{
640 std::vector<double> values(m_fields, 0.);
641 int i, j;
642 double dist, basis;
643
644 if(jnode<0 || jnode>= m_nodes ) {
645 return values;
646 }
647
648 for( i=0; i<m_nodes; ++i ) {
649 if( m_activeNodes[i] ) {
650 dist = calcDist(jnode, i) / getSupportRadius(i);
651 basis = evalBasis( dist );
652
653 for( j=0; j<m_fields; ++j) {
654 values[j] += basis * m_weight[j][i];
655 }
656 }
657 }
658
659 // If INTERP mode add the polynomial contribution
660 if (m_mode == RBFMode::INTERP && m_polyEnabled) {
661 for (j = 0; j < m_fields; ++j) {
662 double *polynomialCoefficients = m_polynomial.getCoefficients(j);
663 std::vector<double> basis = evalPolynomialBasis(jnode);
664 int z = 0;
665 for (int iactive : m_polyActiveBasis) {
666 values[j] += polynomialCoefficients[iactive] * basis[z];
667 z++;
668 }
669 }
670 }
671
672 return values;
673}
674
683{
684 if(m_mode == RBFMode::PARAM) {
685 return -1;
686 }
687
688 if (m_polyEnabled) {
689 // Initialize polynomial
690 initializePolynomial();
691
692 // Check which parameter of the polynomial has to be activated
693 // in order to avoid undetermined system
694 initializePolynomialActiveBasis();
695 }
696
697 double dist;
698
699 std::vector<int> activeSet = getActiveSet();
700 int nActive = activeSet.size();
701
702 int nPoly = m_polyEnabled ? m_polyActiveBasis.size() : 0;
703 int nS = nActive + nPoly;
704 int nrhs = getDataCount();
705
706 int lda = nS;
707 int ldb = nS;
708 int info;
709
710 std::vector<int> ipiv(nS);
711
712
713 std::vector<double> A(lda * nS);
714 std::vector<double> b(ldb * nrhs);
715
716 for (int j = 0; j < nrhs; ++j) {
717 for (const auto &i : activeSet) {
718 int k = j * ldb + i;
719 b[k] = m_value[j][i];
720 }
721 }
722
723 int k = 0;
724 for (const auto &i : activeSet) {
725 for (const auto &j : activeSet) {
726 dist = calcDist(j, i) / getSupportRadius(i); //order by column!
727 int row = k % nActive;
728 int col = k / nActive;
729 A[(col * nS) + row] = evalBasis(dist);
730 k++;
731 }
732 }
733
734 // Filling terms given by the polynomial block.
735 // Symmetric terms set in the loop.
736 if (m_polyEnabled) {
737 for (int i = 0; i < nActive; ++i) {
738 std::vector<double> polynomialTerms = evalPolynomialBasis(activeSet[i]);
739 int j = 0;
740 for (const double &val : polynomialTerms) {
741 A[(j + nActive) * nS + i] = val;
742 A[i * nS + (j + nActive)] = val;
743 j++;
744 }
745 }
746 }
747
748 info = LAPACKE_dgesv(LAPACK_COL_MAJOR, nS, nrhs, A.data(), lda, ipiv.data(), b.data(), ldb);
749
750 if( info > 0 ) {
751 printf( "The diagonal element of the triangular factor of the linear system matrix \n" );
752 printf( "U(%i,%i) is zero, so that matrix is singular;\n", info, info );
753 printf( "the solution could not be computed.\n" );
754 return 1;
755 }
756
757 m_weight.resize(nrhs);
758
759 for (int j = 0; j < nrhs; ++j) {
760 m_weight[j].resize(m_nodes, 0);
761 int k = 0;
762 for (const auto &i : activeSet) {
763 m_weight[j][i] = b[j * ldb + k];
764 ++k;
765 }
766 }
767
768 if (m_polyEnabled) {
769 for (int j = 0; j < nrhs; ++j) {
770 double *polynomialCoefficients = m_polynomial.getCoefficients(j);
771 int i = 0;
772 for (int iactive : m_polyActiveBasis) {
773 polynomialCoefficients[iactive] = b[j * ldb + nActive + i];
774 i++;
775 }
776 }
777 }
778 return 0;
779}
780
788int RBFKernel::greedy( double tolerance)
789{
790 if(m_mode == RBFMode::PARAM) return -1;
791
792 int i, j;
793 double error(1.e18);
794 std::vector<double> local(m_fields);
795
796 m_error.resize(m_nodes);
797
799
800 for( i=0; i<m_nodes; ++i){
801
802 for( j=0; j<m_fields; ++j) {
803 local[j] = m_value[j][i];
804 }
805
806 m_error[i] = norm2(local);
807 }
808
809 std::ios::fmtflags streamFlags(log::cout().flags());
810
811 int errorFlag = 0;
812 while( error > tolerance) {
813 i = addGreedyPoint();
814
815 if( i != -1) {
816 m_activeNodes[i] = true;
817
818 //solve();
819 solveLSQ();
820
821 error = evalError();
822
823 log::cout() << std::scientific;
824 log::cout() << " error now " << error << " active nodes" << getActiveCount() << " / " << m_nodes << std::endl;
825 } else {
826 errorFlag = 1;
827 break;
828 }
829 }
830
831 log::cout().flags(streamFlags);
832
833 return errorFlag;
834}
835
842const std::vector<std::vector<double>> & RBFKernel::getWeights() const
843{
844 return m_weight;
845}
846
857{
858 for (int i=0;i<m_fields; ++i) {
860 }
861}
862
874{
875 if(m_mode != RBFMode::PARAM) m_value[id].resize(m_nodes, 0.0);
876 else m_weight[id].resize(m_nodes,0.0);
877}
878
884double RBFKernel::evalBasis( double dist )
885{
886 return (*m_fPtr)(dist);
887}
888
897double RBFKernel::evalBasisPair(const int i, const int j)
898{
899 double dist = calcDist(i, j) / getSupportRadius(j);
900 double value = evalBasis(dist);
901 return value;
902}
903
909{
910 if(m_mode == RBFMode::PARAM) {
911 return -1;
912 }
913
914 int i(0), index(-1);
915 double maxError(0.);
916
917 std::vector<int> active( getActiveSet() );
918
919 for( auto error : m_error ){
920
921 if(!m_activeNodes[i] ){
922
923 if( error > maxError ) {
924 maxError = error;
925 index = i;
926 }
927 }
928
929 ++i;
930 }
931
932 return index;
933}
934
941{
942 if(m_mode == RBFMode::PARAM) {
943 return -1.0;
944 }
945
946 int i(0), j(0);
947 //int index;
948 double maxError(0), relError, realValue;
949 std::vector<double> reconValues;
950
951 for( int iX=0; iX< m_nodes; ++iX ) {
952 reconValues = evalRBF( iX );
953
954 j=0;
955 relError = 0.;
956 for( auto &val : reconValues ) {
957 realValue = m_value[j][i];
958 relError += std::pow( (val - realValue), 2 );
959
960 ++j;
961 }
962
963 relError = sqrt(relError);
964 m_error[i] = relError;
965
966 if( relError > maxError ) {
967 maxError = relError;
968 }
969
970 ++i;
971 }
972
973 return maxError;
974}
975
983{
984 if(m_mode == RBFMode::PARAM) {
985 return -1;
986 }
987
988 if (m_polyEnabled) {
989 // Initialize polynomial
990 initializePolynomial();
991
992 // Check which parameter of the polynomial has to be activated
993 // in order to avoid undetermined system
994 initializePolynomialActiveBasis();
995 }
996
997 double dist;
998
999 std::vector<int> activeSet = getActiveSet();
1000 int nActive = activeSet.size();
1001
1002 int nPoly = m_polyEnabled ? getPolynomialWeightsCount() : 0;
1003 int nS = nActive + nPoly;
1004 int nP = m_nodes;
1005 int nrhs = getDataCount();
1006
1007 int n ,m, lda, ldb, info, rank;
1008 double rcond = -1.0;
1009
1010 m = nP;
1011 n = nS;
1012
1013 lda = m + nPoly;
1014 ldb = m + nPoly;
1015
1016 std::vector<double> A(lda * n);
1017 std::vector<double> b(ldb * nrhs, 0.0);
1018 std::vector<double> s(m);
1019
1020 for (int j = 0; j < nrhs; ++j) {
1021 for (int i = 0; i < m; ++i) {
1022 int k = j * ldb + i;
1023 b[k] = m_value[j][i];
1024 }
1025 }
1026
1027 int k = 0;
1028 for (const auto &i : activeSet) {
1029 for (int j = 0; j < nP; ++j) {
1030 dist = calcDist(j, i) / getSupportRadius(i); //order by column!
1031 int row = k % nP;
1032 int col = k / nP;
1033 A[(col * ldb) + row] = evalBasis(dist);
1034 k++;
1035 }
1036 }
1037
1038 // Filling column terms given by the polynomial block.
1039 if (m_polyEnabled) {
1040 // Loop on columns
1041 for (int i = 0; i < nActive; ++i) {
1042 std::vector<double> polynomialTerms = evalPolynomialBasis(activeSet[i]);
1043 int j = 0;
1044 for (const double &val : polynomialTerms) {
1045 A[lda * i + (nP + j)] = val;
1046 j++;
1047 }
1048 }
1049 }
1050
1051 // Filling row terms given by the polynomial block.
1052 if (m_polyEnabled) {
1053 // Loop on rows
1054 for (int i = 0; i < nP; ++i) {
1055 std::vector<double> polynomialTerms = evalPolynomialBasis(i);
1056 int j = 0;
1057 for (const double &val : polynomialTerms) {
1058 A[(lda * (nActive + j) + i)] = val;
1059 j++;
1060 }
1061 }
1062 }
1063
1064 info = LAPACKE_dgelsd(LAPACK_COL_MAJOR, lda, nS, nrhs, A.data(), lda, b.data(), ldb, s.data(), rcond, &rank);
1065
1066 if (info > 0) {
1067 return 1;
1068 }
1069
1070 m_weight.resize(nrhs);
1071
1072 for (int j = 0; j < nrhs; ++j) {
1073 m_weight[j].clear();
1074 m_weight[j].resize(m_nodes,0);
1075
1076 k=0;
1077 for( const auto &i : activeSet ) {
1078 m_weight[j][i] = b[j*ldb+k];
1079 ++k;
1080 }
1081 }
1082
1083 if (m_polyEnabled) {
1084 for (int j = 0; j < nrhs; ++j) {
1085 double *polynomialCoefficients = m_polynomial.getCoefficients(j);
1086 int i = 0;
1087 for (int iactive : m_polyActiveBasis) {
1088 polynomialCoefficients[iactive] = b[j * ldb + nActive + i];
1089 i++;
1090 }
1091 }
1092 }
1093 return 0;
1094 }
1095
1101{
1102 m_polyEnabled = enable;
1103}
1104
1109{
1110 int nTerms = m_polyActiveBasis.size();
1111 return nTerms;
1112}
1113
1118RBFKernel::LinearPolynomial::LinearPolynomial()
1119{
1120 m_dim = 0;
1121 m_fields = 0;
1122}
1123
1128void RBFKernel::LinearPolynomial::clear()
1129{
1131 m_dim = 0;
1132 m_fields = 0;
1133}
1134
1135
1143void RBFKernel::LinearPolynomial::initialize()
1144{
1145 std::array<double, 3> m_origin;
1146 m_origin.fill(0.);
1147 ReconstructionPolynomial::initialize(1, m_dim, m_origin, m_fields, true);
1148 double *coeffs = getCoefficients();
1149 for (auto i = 0; i < getCoefficientCount(); i++) {
1150 coeffs[i] = 0.;
1151 }
1152}
1153
1158void RBFKernel::LinearPolynomial::setDimension(int dim)
1159{
1160 m_dim = (dim > 0) ? (dim < 4 ? dim : 3) : 0;
1161}
1162
1167void RBFKernel::LinearPolynomial::setDataCount(int fields)
1168{
1169 m_fields = std::max(0, fields);
1170}
1171
1177void RBFKernel::LinearPolynomial::evalBasis(const double *x, double *basis)
1178{
1179 // Set 0-th degree coefficients
1180 basis[0] = 1.;
1181
1182 // Set 1-st degree coefficients
1183 for (int i = 0; i < m_dim; ++i) {
1184 basis[i + 1] = x[i];
1185 }
1186}
1187
1188// RBF derived class implementation
1189
1203{
1204}
1205
1206// /*!
1207// * Default constructor. RBFBasisFunction::WENDLANDC2 is default. RBFMode is
1208// * INTERP, by default. Use setMode for changing it.
1209// */
1210// RBF::RBF(): RBFKernel()
1211// {
1212// m_node.clear();
1213// }
1214
1220{
1221 m_node.clear();
1222 setFunction( bfunc );
1223}
1224
1228RBF::RBF(const RBF & other)
1229 : RBFKernel(other),
1230 m_node(other.m_node)
1231{
1232}
1233
1238{
1239 swap(other);
1240
1241 return *this;
1242}
1243
1249void RBF::swap(RBF &other) noexcept
1250{
1251 RBFKernel::swap(other);
1252
1253 std::swap(m_node, other.m_node);
1254}
1255
1261{
1262 return m_nodes;
1263}
1264
1271int RBF::addNode( const std::array<double,3> &node )
1272{
1273 m_node.push_back(node);
1274 m_activeNodes.push_back(true);
1275 m_nodes++;
1276
1277 return m_nodes;
1278}
1279
1286std::vector<int> RBF::addNode( const std::vector<std::array<double,3>> &node )
1287{
1288 int i( m_nodes );
1289 std::vector<int> ids;
1290
1291 ids.resize( node.size() );
1292
1293 for( auto & id:ids ) {
1294 id = i;
1295 ++i;
1296 }
1297
1298 m_node.insert( m_node.end(), node.begin(), node.end() );
1299 m_nodes += node.size();
1300
1301 m_activeNodes.resize( m_nodes, true );
1302
1303 return ids;
1304}
1305
1312{
1313 if(id < 0 || id >=m_nodes) {
1314 return false;
1315 }
1316
1317 m_nodes--;
1318 m_node.erase(m_node.begin()+id);
1319 m_activeNodes.erase(m_activeNodes.begin()+id);
1320
1321 return true;
1322}
1323
1329bool RBF::removeNode(std::vector<int> & list)
1330{
1331 // List should be processed in reversed order because nodes
1332 // are removed using their position in the storages.
1333 std::sort(list.begin(), list.end(), std::greater<int>());
1334
1335 int nInitialNodes = getTotalNodesCount();
1336 for(int id : list) {
1337 removeNode(id);
1338 }
1339 int nFinalNodes = getTotalNodesCount();
1340
1341 return ((nInitialNodes - nFinalNodes) == static_cast<int>(list.size()));
1342}
1343
1348{
1349 m_nodes = 0;
1350 m_node.clear();
1351 m_activeNodes.clear();
1352}
1353
1359double RBF::calcDist(int i, int j)
1360{
1361 return norm2(m_node[i]-m_node[j]);
1362}
1363
1369double RBF::calcDist(const std::array<double,3>& point, int j)
1370{
1371 return norm2(point - m_node[j]);
1372}
1373
1380void RBF::initializePolynomialActiveBasis()
1381{
1382 std::vector<int> activeSet(RBFKernel::getActiveSet());
1383
1384 // Initialize active terms for an only constant linear polynomial
1385 m_polyActiveBasis.clear();
1386 m_polyActiveBasis.push_back(0);
1387
1388 // Initialize reference coordinates with the first node
1389 std::array<double, 3> coord(m_node[0]);
1390
1391 // Check if at least one node has one of the coordinates
1392 // different from the reference ones and enable the related
1393 // polynomial term
1394 for (int d = 0; d < 2; ++d) {
1395 for (const auto &i : activeSet) {
1396 const std::array<double, 3> &point = m_node[i];
1397 if (!utils::DoubleFloatingEqual()(coord[d], point[d])) {
1398 utils::addToOrderedVector<int>(d + 1, m_polyActiveBasis);
1399 break;
1400 }
1401 }
1402 }
1403}
1404
1408void RBF::initializePolynomial()
1409{
1410 m_polynomial.clear();
1411 m_polynomial.setDimension(3);
1412 m_polynomial.setDataCount(getDataCount());
1413 m_polynomial.initialize();
1414}
1415
1421std::vector<double> RBF::evalPolynomialBasis(int i)
1422{
1423 int nPoly = m_polyActiveBasis.size();
1424 std::vector<double> result(nPoly);
1425
1426 if (nPoly < 1)
1427 return result;
1428
1429 const std::array<double, 3> &point = m_node[i];
1430
1431 std::vector<double> completeBasis(m_polynomial.getCoefficientCount());
1432 m_polynomial.evalBasis(point.data(), completeBasis.data());
1433
1434 int k = 0;
1435 for (int j : m_polyActiveBasis) {
1436 result[k] = completeBasis[j];
1437 k++;
1438 }
1439
1440 return result;
1441}
1442
1448std::vector<double> RBF::evalPolynomialBasis(const std::array<double,3> &point)
1449{
1450 int nPoly = m_polyActiveBasis.size();
1451 std::vector<double> result(nPoly);
1452
1453 if (nPoly < 1)
1454 return result;
1455
1456 std::vector<double> completeBasis(m_polynomial.getCoefficientCount());
1457 m_polynomial.evalBasis(point.data(), completeBasis.data());
1458
1459 int k = 0;
1460 for (int j : m_polyActiveBasis) {
1461 result[k] = completeBasis[j];
1462 k++;
1463 }
1464
1465 return result;
1466}
1467
1468// RBF NAMESPACE UTILITIES
1469
1475double rbf::wendlandc2( double dist )
1476{
1477 if( dist > 1) {
1478 return 0.;
1479 } else{
1480 return std::pow(1.-dist,4)*(4.*dist+1.);
1481 }
1482}
1483
1489double rbf::linear( double dist )
1490{
1491 if( dist > 1) {
1492 return 0.;
1493 } else{
1494 return (1-dist);
1495 }
1496}
1497
1503double rbf::gauss90( double dist )
1504{
1505 double eps = std::pow(-1.0*std::log(0.1),0.5);
1506
1507 return std::exp(-1.0*std::pow(dist*eps,2));
1508}
1509
1515double rbf::gauss95( double dist )
1516{
1517 double eps = std::pow(-1.0*std::log(0.05),0.5);
1518
1519 return std::exp(-1.0*std::pow(dist*eps,2));
1520}
1521
1527double rbf::gauss99( double dist )
1528{
1529 double eps = std::pow(-1.0*std::log(0.01),0.5);
1530
1531 return std::exp(-1.0*std::pow(dist*eps,2));
1532}
1533
1540double rbf::c1c0( double dist )
1541{
1542 if( dist > 1) {
1543 return 0.;
1544 } else{
1545 return (1.0-std::pow(dist,2));
1546 }
1547}
1548
1555double rbf::c2c0( double dist )
1556{
1557 if( dist > 1) {
1558 return 0.;
1559 } else{
1560 return (1.0-std::pow(dist,3));
1561 }
1562}
1563
1570double rbf::c0c1( double dist )
1571{
1572 if( dist > 1) {
1573 return 0.;
1574 } else{
1575 return (1.0- 2.0*dist + std::pow(dist,2));
1576 }
1577}
1578
1585double rbf::c1c1( double dist )
1586{
1587 if( dist > 1) {
1588 return 0.;
1589 } else{
1590 return (1.0-3.0*std::pow(dist,2)+2.0*std::pow(dist,3));
1591 }
1592}
1593
1600double rbf::c2c1( double dist )
1601{
1602 if( dist > 1) {
1603 return 0.;
1604 } else{
1605 return (1.0- 4.0*std::pow(dist,3) + 3.0*std::pow(dist,4));
1606 }
1607}
1608
1615double rbf::c0c2( double dist )
1616{
1617 if( dist > 1) {
1618 return 0.;
1619 } else{
1620 return (1.0 -3.0*dist +3.0*std::pow(dist,2) - std::pow(dist,3));
1621 }
1622}
1623
1630double rbf::c1c2( double dist )
1631{
1632 if( dist > 1) {
1633 return 0.;
1634 } else{
1635 return (1.0 -6.0*std::pow(dist,2) + 8.0*std::pow(dist,3) - 3.0*std::pow(dist,4));
1636 }
1637}
1638
1645double rbf::c2c2( double dist )
1646{
1647 if( dist > 1) {
1648 return 0.;
1649 } else{
1650 return (1.0 -10.0*std::pow(dist,3) +15.0*std::pow(dist,4) -6.0*std::pow(dist,5));
1651 }
1652}
1653
1660 double rbf::cosinus( double dist )
1661 {
1662 if( dist > 1) {
1663 return 0.;
1664 } else{
1665 return 0.5 + 0.5 * std::cos(dist*BITPIT_PI);
1666 }
1667 }
1668
1674double rbf::thinplate(double dist)
1675{
1676 if (utils::DoubleFloatingGreater()(dist, 0.)) {
1677 return dist * dist * std::log(dist);
1678 } else {
1679 return 0.;
1680 }
1681}
1682
1683} // namespace bitpit
Base class to handle Radial Basis Function with a large set of nodes.
Definition rbf.hpp:69
bool deactivateNode(int)
Definition rbf.cpp:335
std::vector< std::vector< double > > m_weight
Definition rbf.hpp:103
void enablePolynomial(bool enable=true)
Definition rbf.cpp:1100
void setMode(RBFMode mode)
Definition rbf.cpp:432
bool m_polyEnabled
Definition rbf.hpp:107
bool activateNode(int)
Definition rbf.cpp:294
void removeAllData()
Definition rbf.cpp:582
double evalError()
Definition rbf.cpp:940
std::vector< std::vector< double > > m_value
Definition rbf.hpp:102
void swap(RBFKernel &x) noexcept
Definition rbf.cpp:103
double getSupportRadius()
Definition rbf.cpp:397
int greedy(double)
Definition rbf.cpp:788
void setSupportRadius(double)
Definition rbf.cpp:375
void setFunction(RBFBasisFunction)
Definition rbf.cpp:125
int getDataCount()
Definition rbf.cpp:236
double evalBasis(double)
Definition rbf.cpp:884
const std::vector< std::vector< double > > & getWeights() const
Definition rbf.cpp:842
RBFBasisFunction getFunctionType()
Definition rbf.cpp:225
int addGreedyPoint()
Definition rbf.cpp:908
RBFMode getMode()
Definition rbf.cpp:423
int getActiveCount()
Definition rbf.cpp:245
std::vector< double > evalRBF(const std::array< double, 3 > &)
Definition rbf.cpp:597
void activateAllNodes()
Definition rbf.cpp:325
std::vector< int > m_polyActiveBasis
Definition rbf.hpp:108
double evalBasisPair(int i, int j)
Definition rbf.cpp:897
std::vector< int > getActiveSet()
Definition rbf.cpp:259
void setDataToNode(int, const std::vector< double > &)
Definition rbf.cpp:444
std::vector< bool > m_activeNodes
Definition rbf.hpp:104
void setDataToAllNodes(int, const std::vector< double > &)
Definition rbf.cpp:476
LinearPolynomial m_polynomial
Definition rbf.hpp:109
bool removeData(int)
Definition rbf.cpp:543
void fitDataToNodes()
Definition rbf.cpp:856
bool isActive(int)
Definition rbf.cpp:280
void deactivateAllNodes()
Definition rbf.cpp:366
int getPolynomialWeightsCount()
Definition rbf.cpp:1108
Class to handle Radial Basis Function with a large set of 3D points as nodes.
Definition rbf.hpp:184
bool removeNode(int)
Definition rbf.cpp:1311
void swap(RBF &x) noexcept
Definition rbf.cpp:1249
int getTotalNodesCount()
Definition rbf.cpp:1260
void removeAllNodes()
Definition rbf.cpp:1347
int addNode(const std::array< double, 3 > &)
Definition rbf.cpp:1271
std::vector< std::array< double, 3 > > m_node
Definition rbf.hpp:187
RBF(RBFBasisFunction=RBFBasisFunction::WENDLANDC2)
Definition rbf.cpp:1219
RBF & operator=(RBF other)
Definition rbf.cpp:1237
void initialize(uint8_t degree, uint8_t dimensions, const std::array< double, 3 > &origin, int nFields=1, bool release=true)
const double * getCoefficients() const
double norm2(const std::array< T, d > &x)
RBFBasisFunction
Enum class defining types of RBF kernel functions that could be used in bitpit::RBF class.
Definition rbf.hpp:40
RBFMode
Enum class defining behaviour of the bitpit::RBF class.
Definition rbf.hpp:64
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
Definition logger.cpp:1705
double gauss90(double)
Definition rbf.cpp:1503
double c2c2(double)
Definition rbf.cpp:1645
double c1c2(double)
Definition rbf.cpp:1630
double gauss95(double)
Definition rbf.cpp:1515
double c0c2(double)
Definition rbf.cpp:1615
double wendlandc2(double)
Definition rbf.cpp:1475
double gauss99(double)
Definition rbf.cpp:1527
double cosinus(double)
Definition rbf.cpp:1660
double c2c1(double)
Definition rbf.cpp:1600
double thinplate(double)
Definition rbf.cpp:1674
double linear(double)
Definition rbf.cpp:1489
double c1c0(double)
Definition rbf.cpp:1540
double c0c1(double)
Definition rbf.cpp:1570
double c1c1(double)
Definition rbf.cpp:1585
double c2c0(double)
Definition rbf.cpp:1555
--- layout: doxygen_footer ---