OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
Dcpse.hpp
1//
2// DCPSE Created by tommaso on 29/03/19.
3// Modified, Updated and Maintained by Abhinav and Pietro
4//Surface Operators by Abhinav Singh on 07/10/2021
5#ifndef OPENFPM_PDATA_DCPSE_HPP
6#define OPENFPM_PDATA_DCPSE_HPP
7
8#ifdef HAVE_EIGEN
9
10#include "Vector/vector_dist.hpp"
11#include "MonomialBasis.hpp"
12#include "DMatrix/EMatrix.hpp"
13#include "SupportBuilder.hpp"
14#include "Support.hpp"
15#include "Vandermonde.hpp"
16#include "DcpseDiagonalScalingMatrix.hpp"
17#include "DcpseRhs.hpp"
18#include "hash_map/hopscotch_map.h"
19
20template<unsigned int N> struct value_t {};
21
22template<bool cond>
23struct is_scalar {
24 template<typename op_type>
25 static auto
26 analyze(const vect_dist_key_dx &key, op_type &o1) -> typename std::remove_reference<decltype(o1.value(
27 key))>::type {
28 return o1.value(key);
29 };
30};
31
32template<>
33struct is_scalar<false> {
34 template<typename op_type>
35 static auto
36 analyze(const vect_dist_key_dx &key, op_type &o1) -> typename std::remove_reference<decltype(o1.value(
37 key))>::type {
38 return o1.value(key);
39 };
40};
41
42template<unsigned int dim, typename vector_type,typename vector_type2=vector_type>
43class Dcpse {
44public:
45
46 typedef typename vector_type::stype T;
47 typedef typename vector_type::value_type part_type;
48 typedef vector_type vtype;
49
50 #ifdef SE_CLASS1
51 int update_ctr=0;
52 #endif
53
54 // This works in this way:
55 // 1) User constructs this by giving a domain of points (where one of the properties is the value of our f),
56 // the signature of the differential operator and the error order bound.
57 // 2) The machinery for assembling and solving the linear system for coefficients starts...
58 // 3) The user can then call an evaluate(point) method to get the evaluation of the differential operator
59 // on the given point.
61 double HOverEpsilon=0.9;
62private:
63 const Point<dim, unsigned int> differentialSignature;
64 const unsigned int differentialOrder;
65 const MonomialBasis<dim> monomialBasis;
66
67 bool isSharedLocalSupport = false;
68 openfpm::vector<Support> localSupports; // Each MPI rank has just access to the local ones
69 openfpm::vector<T> localEps; // Each MPI rank has just access to the local ones
70 openfpm::vector<T> localEpsInvPow; // Each MPI rank has just access to the local ones
71
72 openfpm::vector<size_t> kerOffsets,accKerOffsets;
73 openfpm::vector<T> calcKernels;
74 openfpm::vector<T> accCalcKernels;
75 openfpm::vector<T> nSpacings;
76 vector_type & particlesFrom;
77 vector_type2 & particlesTo;
78 double rCut,supportSizeFactor=1,nSpacing,AdapFac;
79 unsigned int convergenceOrder,nCount;
80
81 bool isSurfaceDerivative=false;
82 size_t initialParticleSize;
83
84
85 support_options opt;
86public:
87 template<unsigned int NORMAL_ID>
88 void createNormalParticles(vector_type &particles)
89 {
90 particles.template ghost_get<NORMAL_ID>(SKIP_LABELLING);
91 initialParticleSize=particles.size_local_with_ghost();
93 while(it.isNext()){
94 auto key=it.get();
95 Point<dim,T> xp=particles.getPos(key), Normals=particles.template getProp<NORMAL_ID>(key);
96 if(opt==support_options::ADAPTIVE)
97 {
98 nSpacing=nSpacings.get(key.getKey());
99 }
100 for(int i=1;i<=nCount;i++){
102 for(size_t j=0;j<dim;j++)
103 {particles.getLastPosEnd()[j]=xp[j]+i*nSpacing*Normals[j];}
105 for(size_t j=0;j<dim;j++)
106 {particles.getLastPosEnd()[j]=xp[j]-i*nSpacing*Normals[j];}
107 }
108 ++it;
109 }
110 }
111
112 void accumulateAndDeleteNormalParticles(vector_type &particles)
113 {
115 auto it = particles.getDomainIterator();
116 auto supportsIt = localSupports.begin();
117 openfpm::vector_std<size_t> supportBuffer;
118 accCalcKernels.clear();
119 accKerOffsets.clear();
120 accKerOffsets.resize(initialParticleSize);
121 accKerOffsets.fill(-1);
122 while(it.isNext()){
123 supportBuffer.clear();
124 nMap.clear();
125 auto key=it.get();
126 Support support = *supportsIt;
127 size_t xpK = support.getReferencePointKey();
128 size_t kerOff = kerOffsets.get(xpK);
129 auto &keys = support.getKeys();
130 accKerOffsets.get(xpK)=accCalcKernels.size();
131 for (int i = 0 ; i < keys.size() ; i++)
132 {
133 size_t xqK = keys.get(i);
134 int real_particle=(xqK-initialParticleSize)/(2.*nCount);
135 if(real_particle<0)
136 {
137 real_particle=xqK;
138 }
139 auto found=nMap.find(real_particle);
140 if(found!=nMap.end()){
141 accCalcKernels.get(found->second)+=calcKernels.get(kerOff+i);
142 }
143 else{
144 supportBuffer.add();
145 supportBuffer.get(supportBuffer.size()-1)=real_particle;
146 accCalcKernels.add();
147 accCalcKernels.get(accCalcKernels.size()-1)=calcKernels.get(kerOff+i);
148 nMap[real_particle]=accCalcKernels.size()-1;
149 }
150 }
151 keys.swap(supportBuffer);
152 localSupports.get(xpK) = support;
153 ++supportsIt;
154 ++it;
155 }
156 particles.resizeAtEnd(initialParticleSize);
157 localEps.resize(initialParticleSize);
158 localEpsInvPow.resize(initialParticleSize);
159 localSupports.resize(initialParticleSize);
160 calcKernels.swap(accCalcKernels);
161 kerOffsets.swap(accKerOffsets);
162 }
163
164#ifdef SE_CLASS1
165 int getUpdateCtr() const
166 {
167 return update_ctr;
168 }
169#endif
170
171 // Here we require the first element of the aggregate to be:
172 // 1) the value of the function f on the point
173 Dcpse(vector_type &particles,
174 Point<dim, unsigned int> differentialSignature,
175 unsigned int convergenceOrder,
176 T rCut,
177 T supportSizeFactor = 1, //Maybe change this to epsilon/h or h/epsilon = c 0.9. Benchmark
178 support_options opt = support_options::RADIUS)
179 :particlesFrom(particles),
180 particlesTo(particles),
181 differentialSignature(differentialSignature),
182 differentialOrder(Monomial<dim>(differentialSignature).order()),
183 monomialBasis(differentialSignature.asArray(), convergenceOrder),
184 opt(opt)
185 {
186 particles.ghost_get_subset(); // This communicates which ghost particles to be excluded from support
187 initializeStaticSize(particles, particles, convergenceOrder, rCut, supportSizeFactor);
188 }
189
190 //Surface DCPSE Constructor
191 template<unsigned int NORMAL_ID>
192 Dcpse(vector_type &particles,
193 Point<dim, unsigned int> differentialSignature,
194 unsigned int convergenceOrder,
195 T rCut,
196 T nSpacing,
197 value_t< NORMAL_ID >,
198 support_options opt = support_options::RADIUS)
199 :particlesFrom(particles),
200 particlesTo(particles),
201 differentialSignature(differentialSignature),
202 differentialOrder(Monomial<dim>(differentialSignature).order()),
203 monomialBasis(differentialSignature.asArray(), convergenceOrder),
204 opt(opt),isSurfaceDerivative(true),nSpacing(nSpacing),nCount(floor(rCut/nSpacing))
205 {
206 particles.ghost_get_subset(); // This communicates which ghost particles to be excluded from support
207
208 if(opt==support_options::ADAPTIVE) {
209 this->AdapFac=nSpacing;
210 if(dim==2){
211 nCount=3;
212 }
213 else{
214 nCount=2;
215 }
217 supportBuilder(particlesFrom,particlesTo, differentialSignature, rCut, differentialOrder == 0);
218 supportBuilder.setAdapFac(nSpacing);
219 auto it = particlesTo.getDomainAndGhostIterator();
220 while (it.isNext()) {
221 auto key_o = particlesTo.getOriginKey(it.get());
222 Support support = supportBuilder.getSupport(it,monomialBasis.size(),opt);
223 nSpacings.add(supportBuilder.getLastMinspacing());
224 ++it;
225 }
226
227 }
228 if(opt!=support_options::LOAD) {
229 createNormalParticles<NORMAL_ID>(particles);
230#ifdef SE_CLASS1
231 particles.write("WithNormalParticlesQC");
232#endif
233 }
234 initializeStaticSize(particles, particles, convergenceOrder, rCut, supportSizeFactor);
235 if(opt!=support_options::LOAD) {
236 accumulateAndDeleteNormalParticles(particles);
237 }
238 }
239
240 Dcpse(vector_type &particles,
241 const Dcpse<dim, vector_type>& other,
242 Point<dim, unsigned int> differentialSignature,
243 unsigned int convergenceOrder,
244 T rCut,
245 T supportSizeFactor = 1,
246 support_options opt = support_options::RADIUS)
247 :particlesFrom(particles), particlesTo(particles), opt(opt),
248 differentialSignature(differentialSignature),
249 differentialOrder(Monomial<dim>(differentialSignature).order()),
250 monomialBasis(differentialSignature.asArray(), convergenceOrder),
251 localSupports(other.localSupports),
252 isSharedLocalSupport(true)
253 {
255 initializeStaticSize(particles, particles, convergenceOrder, rCut, supportSizeFactor);
256 }
257
258 Dcpse(vector_type &particlesFrom,vector_type2 &particlesTo,
259 Point<dim, unsigned int> differentialSignature,
260 unsigned int convergenceOrder,
261 T rCut,
262 T supportSizeFactor = 1,
263 support_options opt = support_options::RADIUS)
264 :particlesFrom(particlesFrom),particlesTo(particlesTo),
265 differentialSignature(differentialSignature),
266 differentialOrder(Monomial<dim>(differentialSignature).order()),
267 monomialBasis(differentialSignature.asArray(), convergenceOrder),
268 opt(opt)
269 {
270 particlesFrom.ghost_get_subset();
271 initializeStaticSize(particlesFrom,particlesTo,convergenceOrder, rCut, supportSizeFactor);
272 }
273
274
275 template<unsigned int prp>
276 void DrawKernel(vector_type &particles, int k)
277 {
278 Support support = localSupports.get(k);
279 size_t xpK = k;
280 size_t kerOff = kerOffsets.get(k);
281 auto & keys = support.getKeys();
282 for (int i = 0 ; i < keys.size() ; i++)
283 {
284 size_t xqK = keys.get(i);
285 particles.template getProp<prp>(xqK) += calcKernels.get(kerOff+i);
286 }
287 }
288
289 template<unsigned int prp>
290 void DrawKernelNN(vector_type &particles, int k)
291 {
292 Support support = localSupports.get(k);
293 size_t xpK = k;
294 size_t kerOff = kerOffsets.get(k);
295 auto & keys = support.getKeys();
296 for (int i = 0 ; i < keys.size() ; i++)
297 {
298 size_t xqK = keys.get(i);
299 particles.template getProp<prp>(xqK) = 1.0;
300 }
301 }
302
303 template<unsigned int prp>
304 void DrawKernel(vector_type &particles, int k, int i)
305 {
306
307 Support support = localSupports.get(k);
308 size_t xpK = k;
309 size_t kerOff = kerOffsets.get(k);
310 auto & keys = support.getKeys();
311 for (int i = 0 ; i < keys.size() ; i++)
312 {
313 size_t xqK = keys.get(i);
314 particles.template getProp<prp>(xqK)[i] += calcKernels.get(kerOff+i);
315 }
316 }
317 /*
318 * breif Particle to Particle Interpolation Evaluation
319 */
320 template<unsigned int prp1,unsigned int prp2>
321 void p2p()
322 {
323 typedef typename std::remove_reference<decltype(particlesTo.template getProp<prp2>(0))>::type T2;
324
325 auto it = particlesTo.getDomainIterator();
326 auto supportsIt = localSupports.begin();
327 auto epsItInvPow = localEpsInvPow.begin();
328 while (it.isNext()){
329 double epsInvPow = *epsItInvPow;
330 T2 Dfxp = 0;
331 Support support = *supportsIt;
332 size_t xpK = support.getReferencePointKey();
333 //Point<dim, typename vector_type::stype> xp = particlesTo.getPos(xpK);
334 //T fxp = sign * particlesTo.template getProp<fValuePos>(xpK);
335 size_t kerOff = kerOffsets.get(xpK);
336 auto & keys = support.getKeys();
337 for (int i = 0 ; i < keys.size() ; i++)
338 {
339 size_t xqK = keys.get(i);
340 T2 fxq = particlesFrom.template getProp<prp1>(xqK);
341 Dfxp += fxq * calcKernels.get(kerOff+i);
342 }
343 Dfxp = epsInvPow*Dfxp;
344 //
345 //T trueDfxp = particles.template getProp<2>(xpK);
346 // Store Dfxp in the right position
347 particlesTo.template getProp<prp2>(xpK) = Dfxp;
348 //
349 ++it;
350 ++supportsIt;
351 ++epsItInvPow;
352 }
353 }
357 void save(const std::string &file){
358 auto & v_cl=create_vcluster();
359 size_t req = 0;
360
361 Packer<decltype(localSupports),HeapMemory>::packRequest(localSupports,req);
362 Packer<decltype(localEps),HeapMemory>::packRequest(localEps,req);
363 Packer<decltype(localEpsInvPow),HeapMemory>::packRequest(localEpsInvPow,req);
364 Packer<decltype(calcKernels),HeapMemory>::packRequest(calcKernels,req);
365 Packer<decltype(kerOffsets),HeapMemory>::packRequest(kerOffsets,req);
366
367 // allocate the memory
368 HeapMemory pmem;
369 //pmem.allocate(req);
370 ExtPreAlloc<HeapMemory> mem(req,pmem);
371
372 //Packing
373 Pack_stat sts;
374 Packer<decltype(localSupports),HeapMemory>::pack(mem,localSupports,sts);
375 Packer<decltype(localEps),HeapMemory>::pack(mem,localEps,sts);
376 Packer<decltype(localEpsInvPow),HeapMemory>::pack(mem,localEpsInvPow,sts);
377 Packer<decltype(calcKernels),HeapMemory>::pack(mem,calcKernels,sts);
378 Packer<decltype(kerOffsets),HeapMemory>::pack(mem,kerOffsets,sts);
379
380 // Save into a binary file
381 std::ofstream dump (file+"_"+std::to_string(v_cl.rank()), std::ios::out | std::ios::binary);
382 if (dump.is_open() == false)
383 { std::cerr << __FILE__ << ":" << __LINE__ <<" Unable to write since dump is open at rank "<<v_cl.rank()<<std::endl;
384 return;
385 }
386 dump.write ((const char *)pmem.getPointer(), pmem.size());
387 return;
388 }
393 void load(const std::string & file)
394 {
395 auto & v_cl=create_vcluster();
396 std::ifstream fs (file+"_"+std::to_string(v_cl.rank()), std::ios::in | std::ios::binary | std::ios::ate );
397 if (fs.is_open() == false)
398 {
399 std::cerr << __FILE__ << ":" << __LINE__ << " error, opening file: " << file << std::endl;
400 return;
401 }
402
403 // take the size of the file
404 size_t sz = fs.tellg();
405
406 fs.close();
407
408 // reopen the file without ios::ate to read
409 std::ifstream input (file+"_"+std::to_string(v_cl.rank()), std::ios::in | std::ios::binary );
410 if (input.is_open() == false)
411 {//some message here maybe
412 return;}
413
414 // Create the HeapMemory and the ExtPreAlloc memory
415 size_t req = 0;
416 req += sz;
417 HeapMemory pmem;
418 ExtPreAlloc<HeapMemory> mem(req,pmem);
419
420 mem.allocate(pmem.size());
421
422 // read
423 input.read((char *)pmem.getPointer(), sz);
424
425 //close the file
426 input.close();
427
428 //Unpacking
429 Unpack_stat ps;
430 Unpacker<decltype(localSupports),HeapMemory>::unpack(mem,localSupports,ps);
431 Unpacker<decltype(localEps),HeapMemory>::unpack(mem,localEps,ps);
432 Unpacker<decltype(localEpsInvPow),HeapMemory>::unpack(mem,localEpsInvPow,ps);
433 Unpacker<decltype(calcKernels),HeapMemory>::unpack(mem,calcKernels,ps);
434 Unpacker<decltype(kerOffsets),HeapMemory>::unpack(mem,kerOffsets,ps);
435 return;
436 }
437
438
439 void checkMomenta(vector_type &particles)
440 {
443
444 momenta.resize(monomialBasis.size());
445 momenta_accu.resize(monomialBasis.size());
446
447 for (int i = 0 ; i < momenta.size() ; i++)
448 {
449 momenta.template get<0>(i) = 3000000000.0;
450 momenta.template get<1>(i) = -3000000000.0;
451 }
452
453 auto it = particles.getDomainIterator();
454 auto supportsIt = localSupports.begin();
455 auto epsIt = localEps.begin();
456 while (it.isNext())
457 {
458 double eps = *epsIt;
459
460 for (int i = 0 ; i < momenta.size() ; i++)
461 {
462 momenta_accu.template get<0>(i) = 0.0;
463 }
464
465 Support support = *supportsIt;
466 size_t xpK = support.getReferencePointKey();
467 Point<dim, T> xp = particles.getPos(support.getReferencePointKey());
468 size_t kerOff = kerOffsets.get(xpK);
469 auto & keys = support.getKeys();
470 for (int i = 0 ; i < keys.size() ; i++)
471 {
472 size_t xqK = keys.get(i);
474 Point<dim, T> normalizedArg = (xp - xq) / eps;
475
476 auto ker = calcKernels.get(kerOff+i);
477
478 int counter = 0;
479 size_t N = monomialBasis.getElements().size();
480
481 for (size_t i = 0; i < N; ++i)
482 {
483 const Monomial<dim> &m = monomialBasis.getElement(i);
484
485 T mbValue = m.evaluate(normalizedArg);
486 momenta_accu.template get<0>(counter) += mbValue * ker;
487
488 ++counter;
489 }
490 }
491
492 for (int i = 0 ; i < momenta.size() ; i++)
493 {
494 if (momenta_accu.template get<0>(i) < momenta.template get<0>(i))
495 {
496 momenta.template get<0>(i) = momenta_accu.template get<0>(i);
497 }
498
499 if (momenta_accu.template get<1>(i) > momenta.template get<1>(i))
500 {
501 momenta.template get<1>(i) = momenta_accu.template get<0>(i);
502 }
503 }
504
505 //
506 ++it;
507 ++supportsIt;
508 ++epsIt;
509 }
510
511 for (size_t i = 0 ; i < momenta.size() ; i++)
512 {
513 std::cout << "MOMENTA: " << monomialBasis.getElement(i) << "Min: " << momenta.template get<0>(i) << " " << "Max: " << momenta.template get<1>(i) << std::endl;
514 }
515 }
516
525 template<unsigned int fValuePos, unsigned int DfValuePos>
526 void computeDifferentialOperator(vector_type &particles) {
527 char sign = 1;
528 if (differentialOrder % 2 == 0) {
529 sign = -1;
530 }
531
532 auto it = particles.getDomainIterator();
533 auto supportsIt = localSupports.begin();
534 auto epsItInvPow = localEpsInvPow.begin();
535 while (it.isNext()) {
536 double epsInvPow = *epsItInvPow;
537
538 T Dfxp = 0;
539 Support support = *supportsIt;
540 size_t xpK = support.getReferencePointKey();
541 //Point<dim, typename vector_type::stype> xp = particles.getPos(support.getReferencePointKey());
542 T fxp = sign * particles.template getProp<fValuePos>(xpK);
543 size_t kerOff = kerOffsets.get(xpK);
544 auto & keys = support.getKeys();
545 for (int i = 0 ; i < keys.size() ; i++)
546 {
547 size_t xqK = keys.get(i);
548 T fxq = particles.template getProp<fValuePos>(xqK);
549
550 Dfxp += (fxq + fxp) * calcKernels.get(kerOff+i);
551 }
552 Dfxp *= epsInvPow;
553 //
554 //T trueDfxp = particles.template getProp<2>(xpK);
555 // Store Dfxp in the right position
556 particles.template getProp<DfValuePos>(xpK) = Dfxp;
557 //
558 ++it;
559 ++supportsIt;
560 ++epsItInvPow;
561 }
562 }
563
564
570 inline int getNumNN(const vect_dist_key_dx &key)
571 {
572 return localSupports.get(key.getKey()).size();
573 }
574
583 inline T getCoeffNN(const vect_dist_key_dx &key, int j)
584 {
585 size_t base = kerOffsets.get(key.getKey());
586 return calcKernels.get(base + j);
587 }
588
594 inline size_t getIndexNN(const vect_dist_key_dx &key, int j)
595 {
596 return localSupports.get(key.getKey()).getKeys().get(j);
597 }
598
599
600 inline T getSign()
601 {
602 T sign = 1.0;
603 if (differentialOrder % 2 == 0 && differentialOrder!=0) {
604 sign = -1;
605 }
606
607 return sign;
608 }
609
610 T getEpsilonInvPrefactor(const vect_dist_key_dx &key)
611 {
612 return localEpsInvPow.get(key.getKey());
613 }
614
623 template<typename op_type>
624 auto computeDifferentialOperator(const vect_dist_key_dx &key,
625 op_type &o1) -> decltype(is_scalar<std::is_fundamental<decltype(o1.value(
626 key))>::value>::analyze(key, o1)) {
627
628 typedef decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1)) expr_type;
629
630 T sign = 1.0;
631 if (differentialOrder % 2 == 0) {
632 sign = -1;
633 }
634
635 double eps = localEps.get(key.getKey());
636 double epsInvPow = localEpsInvPow.get(key.getKey());
637
638 auto &particles = o1.getVector();
639
640#ifdef SE_CLASS1
641 if(particles.getMapCtr()!=this->getUpdateCtr())
642 {
643 std::cerr<<__FILE__<<":"<<__LINE__<<" Error: You forgot a DCPSE operator update after map."<<std::endl;
644 }
645#endif
646
647 expr_type Dfxp = 0;
648 Support support = localSupports.get(key.getKey());
649 size_t xpK = support.getReferencePointKey();
650 //Point<dim, T> xp = particles.getPos(xpK);
651 expr_type fxp = sign * o1.value(key);
652 size_t kerOff = kerOffsets.get(xpK);
653 auto & keys = support.getKeys();
654 for (int i = 0 ; i < keys.size() ; i++)
655 {
656 size_t xqK = keys.get(i);
657 expr_type fxq = o1.value(vect_dist_key_dx(xqK));
658 Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+i);
659 }
660 Dfxp = Dfxp * epsInvPow;
661 //
662 //T trueDfxp = particles.template getProp<2>(xpK);
663 // Store Dfxp in the right position
664 return Dfxp;
665 }
666
676 template<typename op_type>
677 auto computeDifferentialOperator(const vect_dist_key_dx &key,
678 op_type &o1,
679 int i) -> typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(
680 key))>::value>::analyze(key, o1))::coord_type {
681
682 typedef typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1))::coord_type expr_type;
683
684 //typedef typename decltype(o1.value(key))::blabla blabla;
685
686 T sign = 1.0;
687 if (differentialOrder % 2 == 0) {
688 sign = -1;
689 }
690
691 double eps = localEps.get(key.getKey());
692 double epsInvPow = localEpsInvPow.get(key.getKey());
693
694 auto &particles = o1.getVector();
695#ifdef SE_CLASS1
696 if(particles.getMapCtr()!=this->getUpdateCtr())
697 {
698 std::cerr<<__FILE__<<":"<<__LINE__<<" Error: You forgot a DCPSE operator update after map."<<std::endl;
699 }
700#endif
701
702 expr_type Dfxp = 0;
703 Support support = localSupports.get(key.getKey());
704 size_t xpK = support.getReferencePointKey();
705 //Point<dim, T> xp = particles.getPos(xpK);
706 expr_type fxp = sign * o1.value(key)[i];
707 size_t kerOff = kerOffsets.get(xpK);
708 auto & keys = support.getKeys();
709 for (int j = 0 ; j < keys.size() ; j++)
710 {
711 size_t xqK = keys.get(j);
712 expr_type fxq = o1.value(vect_dist_key_dx(xqK))[i];
713 Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+j);
714 }
715 Dfxp = Dfxp * epsInvPow;
716 //
717 //T trueDfxp = particles.template getProp<2>(xpK);
718 // Store Dfxp in the right position
719 return Dfxp;
720 }
721
722
723 void initializeUpdate(vector_type &particlesFrom,vector_type2 &particlesTo)
724 {
725#ifdef SE_CLASS1
726 update_ctr=particlesFrom.getMapCtr();
727#endif
728
729 localSupports.clear();
730 localEps.clear();
731 localEpsInvPow.clear();
732 calcKernels.clear();
733 kerOffsets.clear();
734 initializeStaticSize(particlesFrom,particlesTo, convergenceOrder, rCut, supportSizeFactor);
735 }
736
737 void initializeUpdate(vector_type &particles)
738 {
739#ifdef SE_CLASS1
740 update_ctr=particles.getMapCtr();
741#endif
742
743 localSupports.clear();
744 localEps.clear();
745 localEpsInvPow.clear();
746 calcKernels.clear();
747 kerOffsets.clear();
748
749 initializeStaticSize(particles,particles, convergenceOrder, rCut, supportSizeFactor);
750 }
751
752private:
753 void initializeStaticSize(vector_type &particlesFrom,vector_type2 &particlesTo,
754 unsigned int convergenceOrder,
755 T rCut,
756 T supportSizeFactor) {
757#ifdef SE_CLASS1
758 this->update_ctr=particlesFrom.getMapCtr();
759#endif
760 this->rCut=rCut;
761 this->supportSizeFactor=supportSizeFactor;
762 this->convergenceOrder=convergenceOrder;
763 auto & v_cl=create_vcluster();
764 if(this->opt==LOAD){
765 if(v_cl.rank()==0)
766 {std::cout<<"Warning: Creating empty DC-PSE operator! Please use update or load to get kernels."<<std::endl;}
767 return;
768 }
770 supportBuilder(particlesFrom,particlesTo, differentialSignature, rCut, differentialOrder == 0);
771 unsigned int requiredSupportSize = monomialBasis.size() * supportSizeFactor;
772 supportBuilder.setAdapFac(AdapFac);
773
774 if (!isSharedLocalSupport)
775 localSupports.resize(particlesTo.size_local_orig());
776 localEps.resize(particlesTo.size_local_orig());
777 localEpsInvPow.resize(particlesTo.size_local_orig());
778 kerOffsets.resize(particlesTo.size_local_orig());
779 kerOffsets.fill(-1);
780 T avgSpacingGlobal=0,avgSpacingGlobal2=0,maxSpacingGlobal=0,minSpacingGlobal=std::numeric_limits<T>::max();
781 size_t Counter=0;
782 auto it = particlesTo.getDomainIterator();
783 while (it.isNext()) {
784 // Get the points in the support of the DCPSE kernel and store the support for reuse
785 auto key_o = particlesTo.getOriginKey(it.get());
786
787 if (!isSharedLocalSupport)
788 localSupports.get(key_o.getKey()) = supportBuilder.getSupport(it, requiredSupportSize,opt);
789
790 Support& support = localSupports.get(key_o.getKey());
791
792 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
793
794 // Vandermonde matrix computation
796 vandermonde(support, monomialBasis,particlesFrom,particlesTo,HOverEpsilon);
797 vandermonde.getMatrix(V);
798
799 T eps = vandermonde.getEps();
800 avgSpacingGlobal+=eps;
801 T tSpacing = vandermonde.getMinSpacing();
802 avgSpacingGlobal2+=tSpacing;
803 if(tSpacing>maxSpacingGlobal)
804 {
805 maxSpacingGlobal=tSpacing;
806 }
807 if(tSpacing<minSpacingGlobal)
808 {
809 minSpacingGlobal=tSpacing;
810 }
811
812 localEps.get(key_o.getKey()) = eps;
813 localEpsInvPow.get(key_o.getKey()) = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
814 // Compute the diagonal matrix E
815 DcpseDiagonalScalingMatrix<dim> diagonalScalingMatrix(monomialBasis);
816 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
817 diagonalScalingMatrix.buildMatrix(E, support, eps, particlesFrom, particlesTo);
818 // Compute intermediate matrix B
819 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
820 // Compute matrix A
821 EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
822
823 // Compute RHS vector b
824 DcpseRhs<dim> rhs(monomialBasis, differentialSignature);
825 EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
826 rhs.template getVector<T>(b);
827 // Get the vector where to store the coefficients...
828 EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
829 // ...solve the linear system...
830 a = A.colPivHouseholderQr().solve(b);
831 // ...and store the solution for later reuse
832 kerOffsets.get(key_o.getKey()) = calcKernels.size();
833
834 Point<dim, T> xp = particlesTo.getPosOrig(key_o);
835
836 const auto& support_keys = support.getKeys();
837 size_t N = support_keys.size();
838 for (size_t i = 0; i < N; ++i)
839 {
840 const auto& xqK = support_keys.get(i);
841 Point<dim, T> xq = particlesFrom.getPosOrig(xqK);
842 Point<dim, T> normalizedArg = (xp - xq) / eps;
843 calcKernels.add(computeKernel(normalizedArg, a));
844 }
845 //
846 ++it;
847 ++Counter;
848 }
849
850 v_cl.sum(avgSpacingGlobal);
851 v_cl.sum(avgSpacingGlobal2);
852 v_cl.max(maxSpacingGlobal);
853 v_cl.min(minSpacingGlobal);
854 v_cl.sum(Counter);
855 v_cl.execute();
856 if(v_cl.rank()==0)
857 {std::cout<<"DCPSE Operator Construction Complete. The global avg spacing in the support <h> is: "<<HOverEpsilon*avgSpacingGlobal/(T(Counter))<<" (c="<<HOverEpsilon<<"). Avg:"<<avgSpacingGlobal2/(T(Counter))<<" Range:["<<minSpacingGlobal<<","<<maxSpacingGlobal<<"]."<<std::endl;}
858 }
859
860 T computeKernel(Point<dim, T> x, EMatrix<T, Eigen::Dynamic, 1> & a) const {
861 T res = 0;
862 unsigned int counter = 0;
863 T expFactor = exp(-norm2(x));
864
865 size_t N = monomialBasis.getElements().size();
866 for (size_t i = 0; i < N; ++i)
867 {
868 const Monomial<dim> &m = monomialBasis.getElement(i);
869
870 T coeff = a(counter);
871 T mbValue = m.evaluate(x);
872 res += coeff * mbValue * expFactor;
873 ++counter;
874 }
875 return res;
876 }
877
878
879 T conditionNumber(const EMatrix<T, -1, -1> &V, T condTOL) const {
880 Eigen::JacobiSVD<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> svd(V);
881 T cond = svd.singularValues()(0)
882 / svd.singularValues()(svd.singularValues().size() - 1);
883 if (cond > condTOL) {
884 std::cout
885 << "WARNING: cond(V) = " << cond
886 << " is greater than TOL = " << condTOL
887 << ", numPoints(V) = " << V.rows()
888 << std::endl; // debug
889 }
890 return cond;
891 }
892
893};
894
895#endif
896#endif //OPENFPM_PDATA_DCPSE_HPP
897
This class allocate, and destroy CPU memory.
virtual void * getPointer()
get a readable pointer with the data
virtual size_t size() const
the the size of the allocated memory
Packing status object.
Definition Pack_stat.hpp:61
Packing class.
Definition Packer.hpp:50
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
Unpacking status object.
Definition Pack_stat.hpp:16
Unpacker class.
Definition Unpacker.hpp:34
Implementation of 1-D std::vector like structure.
size_t size()
Stub size.
Grid key for a distributed grid.
__device__ __host__ size_t getKey() const
Get the key.
vect_dist_key_dx get()
Get the actual key.
auto getPosOrig(vect_dist_key_dx vec_key) -> decltype(vd.getPos(vec_key))
Get the position of an element.
vector_dist_iterator_subset getDomainIterator() const
Get an iterator that traverse the particles in the domain.
size_t size_local_orig() const
return the local size of the original vector
Distributed vector.
size_t size_local_with_ghost() const
return the local size of the vector
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
void addAtEnd()
Add at the END of local and ghost particle.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
auto getLastPosEnd() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element after ghost.
bool write(std::string out, int opt=VTK_WRITER)
Output particle position and properties.
auto getPosOrig(vect_dist_key_dx vec_key) const -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
vector_dist_iterator getDomainAndGhostIterator() const
Get an iterator that traverse the particles in the domain.
void ghost_get_subset()
Stub does not do anything.
void resizeAtEnd(size_t rs)
Resize the vector at the end of the ghost (locally)
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...