4 #ifndef OPENFPM_PDATA_DCPSE_HPP 5 #define OPENFPM_PDATA_DCPSE_HPP 9 #include "Vector/vector_dist.hpp" 10 #include "MonomialBasis.hpp" 11 #include "DMatrix/EMatrix.hpp" 12 #include "SupportBuilder.hpp" 13 #include "Support.hpp" 14 #include "Vandermonde.hpp" 15 #include "DcpseDiagonalScalingMatrix.hpp" 16 #include "DcpseRhs.hpp" 20 template<
typename op_type>
22 analyze(
const vect_dist_key_dx &key, op_type &o1) ->
typename std::remove_reference<decltype(o1.value(
29 struct is_scalar<false> {
30 template<
typename op_type>
32 analyze(
const vect_dist_key_dx &key, op_type &o1) ->
typename std::remove_reference<decltype(o1.value(
38 template<
unsigned int dim,
typename vector_type>
58 const unsigned int differentialOrder;
61 std::vector<Support> localSupports;
62 std::vector<T> localEps;
63 std::vector<T> localEpsInvPow;
64 std::vector<T> localSumA;
71 unsigned int convergenceOrder;
72 double supportSizeFactor;
78 int getUpdateCtr()
const 88 unsigned int convergenceOrder,
90 T supportSizeFactor = 1,
91 support_options opt = support_options::RADIUS)
93 differentialSignature(differentialSignature),
94 differentialOrder(
Monomial<dim>(differentialSignature).order()),
95 monomialBasis(differentialSignature.asArray(), convergenceOrder),
100 if (supportSizeFactor < 1)
102 initializeAdaptive(
particles, convergenceOrder, rCut);
106 initializeStaticSize(
particles, convergenceOrder, rCut, supportSizeFactor);
112 template<
unsigned int prp>
115 Support support = localSupports[k];
117 size_t kerOff = kerOffsets.get(k);
118 auto & keys = support.getKeys();
119 for (
int i = 0 ; i < keys.size() ; i++)
121 size_t xqK = keys[i];
122 particles.template getProp<prp>(xqK) += calcKernels.get(kerOff+i);
126 template<
unsigned int prp>
129 Support support = localSupports[k];
131 size_t kerOff = kerOffsets.get(k);
132 auto & keys = support.getKeys();
133 for (
int i = 0 ; i < keys.size() ; i++)
135 size_t xqK = keys[i];
136 particles.template getProp<prp>(xqK) = 1.0;
140 template<
unsigned int prp>
143 Support support = localSupports[k];
145 size_t kerOff = kerOffsets.get(k);
146 auto & keys = support.getKeys();
147 for (
int i = 0 ; i < keys.size() ; i++)
149 size_t xqK = keys[i];
150 particles.template getProp<prp>(xqK)[i] += calcKernels.get(kerOff+i);
159 momenta.resize(monomialBasis.size());
160 momenta_accu.resize(monomialBasis.size());
162 for (
int i = 0 ; i < momenta.
size() ; i++)
164 momenta.template get<0>(i) = 3000000000.0;
165 momenta.template get<1>(i) = -3000000000.0;
169 auto supportsIt = localSupports.begin();
170 auto epsIt = localEps.begin();
175 for (
int i = 0 ; i < momenta.
size() ; i++)
177 momenta_accu.template get<0>(i) = 0.0;
181 size_t xpK = support.getReferencePointKey();
183 size_t kerOff = kerOffsets.get(xpK);
184 auto & keys = support.getKeys();
185 for (
int i = 0 ; i < keys.size() ; i++)
187 size_t xqK = keys[i];
191 auto ker = calcKernels.get(kerOff+i);
196 T mbValue = m.evaluate(normalizedArg);
199 momenta_accu.template get<0>(counter) += mbValue * ker;
206 for (
int i = 0 ; i < momenta.
size() ; i++)
208 if (momenta_accu.template get<0>(i) < momenta.template get<0>(i))
210 momenta.template get<0>(i) = momenta_accu.template get<0>(i);
213 if (momenta_accu.template get<1>(i) > momenta.template get<1>(i))
215 momenta.template get<1>(i) = momenta_accu.template get<0>(i);
225 for (
int i = 0 ; i < momenta.
size() ; i++)
227 std::cout <<
"MOMENTA: " << monomialBasis.getElements()[i] <<
"Min: " << momenta.template get<0>(i) <<
" " <<
"Max: " << momenta.template get<1>(i) << std::endl;
239 template<
unsigned int fValuePos,
unsigned int DfValuePos>
242 if (differentialOrder % 2 == 0) {
247 auto supportsIt = localSupports.begin();
248 auto epsItInvPow = localEpsInvPow.begin();
249 while (it.isNext()) {
250 double epsInvPow = *epsItInvPow;
254 size_t xpK = support.getReferencePointKey();
256 T fxp = sign *
particles.template getProp<fValuePos>(xpK);
257 size_t kerOff = kerOffsets.get(xpK);
258 auto & keys = support.getKeys();
259 for (
int i = 0 ; i < keys.size() ; i++)
261 size_t xqK = keys[i];
262 T fxq =
particles.template getProp<fValuePos>(xqK);
264 Dfxp += (fxq + fxp) * calcKernels.get(kerOff+i);
270 particles.template getProp<DfValuePos>(xpK) = Dfxp;
286 return localSupports[key.
getKey()].size();
299 size_t base = kerOffsets.get(key.
getKey());
300 return calcKernels.get(base + j);
310 return localSupports[key.
getKey()].getKeys()[j];
317 if (differentialOrder % 2 == 0) {
326 return localEpsInvPow[key.
getKey()];
337 template<
typename op_type>
339 op_type &o1) -> decltype(is_scalar<std::is_fundamental<decltype(o1.value(
340 key))>::value>::analyze(key, o1)) {
342 typedef decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1)) expr_type;
345 if (differentialOrder % 2 == 0) {
349 double eps = localEps[key.
getKey()];
350 double epsInvPow = localEpsInvPow[key.
getKey()];
355 if(
particles.getMapCtr()!=this->getUpdateCtr())
357 std::cerr<<__FILE__<<
":"<<__LINE__<<
" Error: You forgot a DCPSE operator update after map."<<std::endl;
363 size_t xpK = support.getReferencePointKey();
365 expr_type fxp = sign * o1.value(key);
366 size_t kerOff = kerOffsets.get(xpK);
367 auto & keys = support.getKeys();
368 for (
int i = 0 ; i < keys.size() ; i++)
370 size_t xqK = keys[i];
372 Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+i);
374 Dfxp = Dfxp * epsInvPow;
390 template<
typename op_type>
393 int i) ->
typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(
394 key))>::value>::analyze(key, o1))::coord_type {
396 typedef typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1))::coord_type expr_type;
401 if (differentialOrder % 2 == 0) {
405 double eps = localEps[key.
getKey()];
406 double epsInvPow = localEpsInvPow[key.
getKey()];
411 if(
particles.getMapCtr()!=this->getUpdateCtr())
413 std::cerr<<__FILE__<<
":"<<__LINE__<<
" Error: You forgot a DCPSE operator update after map."<<std::endl;
419 size_t xpK = support.getReferencePointKey();
421 expr_type fxp = sign * o1.value(key)[i];
422 size_t kerOff = kerOffsets.get(xpK);
423 auto & keys = support.getKeys();
424 for (
int j = 0 ; j < keys.size() ; j++)
426 size_t xqK = keys[j];
428 Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+j);
430 Dfxp = Dfxp * epsInvPow;
443 localSupports.
clear();
447 localEpsInvPow.clear();
455 unsigned int requiredSupportSize = monomialBasis.size() * supportSizeFactor;
458 while (it.isNext()) {
461 Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
462 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
464 auto key_o =
particles.getOriginKey(it.get());
468 vandermonde(support, monomialBasis,
particles);
469 vandermonde.getMatrix(V);
471 T eps = vandermonde.getEps();
473 localSupports[key_o.getKey()] = support;
474 localEps[key_o.getKey()] = eps;
475 localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
478 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
479 diagonalScalingMatrix.buildMatrix(E, support, eps,
particles);
481 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
483 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
487 EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
488 rhs.template getVector<T>(b);
490 EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
492 a = A.colPivHouseholderQr().solve(b);
494 kerOffsets.get(key_o.getKey()) = calcKernels.
size();
498 for (
auto &xqK : support.getKeys())
503 calcKernels.add(computeKernel(normalizedArg, a));
513 unsigned int convergenceOrder,
516 supportBuilder(
particles, differentialSignature, rCut);
517 unsigned int requiredSupportSize = monomialBasis.size();
526 while (it.isNext()) {
527 const T condVTOL = 1e2;
530 Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
531 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
535 vandermonde(support, monomialBasis,
particles);
536 vandermonde.getMatrix(V);
538 T condV = conditionNumber(V, condVTOL);
539 T eps = vandermonde.getEps();
541 if (condV > condVTOL) {
542 requiredSupportSize *= 2;
544 <<
"INFO: Increasing, requiredSupportSize = " << requiredSupportSize
548 requiredSupportSize = monomialBasis.size();
551 auto key_o =
particles.getOriginKey(it.get());
552 localSupports[key_o.getKey()] = support;
553 localEps[key_o.getKey()] = eps;
554 localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
557 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
558 diagonalScalingMatrix.buildMatrix(E, support, eps,
particles);
560 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
562 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
565 EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
566 rhs.template getVector<T>(b);
568 EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
570 a = A.colPivHouseholderQr().solve(b);
572 kerOffsets.get(key_o.getKey()) = calcKernels.
size();
576 for (
auto &xqK : support.getKeys())
581 calcKernels.add(computeKernel(normalizedArg, a));
590 unsigned int convergenceOrder,
592 T supportSizeFactor) {
597 this->supportSizeFactor=supportSizeFactor;
598 this->convergenceOrder=convergenceOrder;
600 supportBuilder(
particles, differentialSignature, rCut);
601 unsigned int requiredSupportSize = monomialBasis.size() * supportSizeFactor;
609 while (it.isNext()) {
611 Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
612 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
614 auto key_o =
particles.getOriginKey(it.get());
618 vandermonde(support, monomialBasis,
particles);
619 vandermonde.getMatrix(V);
621 T eps = vandermonde.getEps();
623 localSupports[key_o.getKey()] = support;
624 localEps[key_o.getKey()] = eps;
625 localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
628 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
629 diagonalScalingMatrix.buildMatrix(E, support, eps,
particles);
631 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
633 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
637 EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
638 rhs.template getVector<T>(b);
640 EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
642 a = A.colPivHouseholderQr().solve(b);
644 kerOffsets.get(key_o.getKey()) = calcKernels.
size();
648 for (
auto &xqK : support.getKeys())
653 calcKernels.add(computeKernel(normalizedArg, a));
663 T computeKernel(
Point<dim, T> x, EMatrix<T, Eigen::Dynamic, 1> & a)
const {
665 unsigned int counter = 0;
666 T expFactor = exp(-norm2(x));
668 T coeff = a(counter);
669 T mbValue = m.evaluate(x);
670 res += coeff * mbValue * expFactor;
677 T conditionNumber(
const EMatrix<T, -1, -1> &V, T condTOL)
const {
678 Eigen::JacobiSVD<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> svd(V);
679 T cond = svd.singularValues()(0)
680 / svd.singularValues()(svd.singularValues().size() - 1);
681 if (cond > condTOL) {
683 <<
"WARNING: cond(V) = " << cond
684 <<
" is greater than TOL = " << condTOL
685 <<
", numPoints(V) = " << V.rows()
695 #endif //OPENFPM_PDATA_DCPSE_HPP
auto getPosOrig(vect_dist_key_dx vec_key) const -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
Grid key for a distributed grid.
prop value_type
property object
__device__ __host__ size_t getKey() const
Get the key.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
void clear()
remove all the elements
size_t size_local_orig() const
return the local size of the vector
void ghost_get_subset()
Stub does not do anything.