1 /* ----------------------------------------------------------------------
2     This is the
3 
4     ██╗     ██╗ ██████╗  ██████╗  ██████╗ ██╗  ██╗████████╗███████╗
5     ██║     ██║██╔════╝ ██╔════╝ ██╔════╝ ██║  ██║╚══██╔══╝██╔════╝
6     ██║     ██║██║  ███╗██║  ███╗██║  ███╗███████║   ██║   ███████╗
7     ██║     ██║██║   ██║██║   ██║██║   ██║██╔══██║   ██║   ╚════██║
8     ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║  ██║   ██║   ███████║
9     ╚══════╝╚═╝ ╚═════╝  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝®
10 
11     DEM simulation engine, released by
12     DCS Computing Gmbh, Linz, Austria
13     http://www.dcs-computing.com, office@dcs-computing.com
14 
15     LIGGGHTS® is part of CFDEM®project:
16     http://www.liggghts.com | http://www.cfdem.com
17 
18     Core developer and main author:
19     Christoph Kloss, christoph.kloss@dcs-computing.com
20 
21     LIGGGHTS® is open-source, distributed under the terms of the GNU Public
22     License, version 2 or later. It is distributed in the hope that it will
23     be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have
25     received a copy of the GNU General Public License along with LIGGGHTS®.
26     If not, see http://www.gnu.org/licenses . See also top-level README
27     and LICENSE files.
28 
29     LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
30     the producer of the LIGGGHTS® software and the CFDEM®coupling software
31     See http://www.cfdem.com/terms-trademark-policy for details.
32 
33 -------------------------------------------------------------------------
34     Contributing author and copyright for this file:
35 
36     Christoph Kloss (DCS Computing GmbH, Linz)
37     Christoph Kloss (JKU Linz)
38     Philippe Seil (JKU Linz)
39 
40     Copyright 2012-     DCS Computing GmbH, Linz
41     Copyright 2009-2012 JKU Linz
42 ------------------------------------------------------------------------- */
43 
44 #ifndef LMP_TRACKING_MESH_I_H
45 #define LMP_TRACKING_MESH_I_H
46 
47   /* ----------------------------------------------------------------------
48    constructor
49   ------------------------------------------------------------------------- */
50 
51   template<int NUM_NODES>
TrackingMesh(LAMMPS * lmp)52   TrackingMesh<NUM_NODES>::TrackingMesh(LAMMPS *lmp)
53   : MultiNodeMeshParallel<NUM_NODES>(lmp),
54     customValues_(*(new CustomValueTracker(lmp,this))),
55     id_ (*this->prop().template addElementProperty< ScalarContainer<int> >("id","comm_exchange_borders"/*ID does never change*/,"frame_invariant","restart_yes")),
56     lineNo_(this->prop().template addElementProperty< ScalarContainer<int> >("lineNo","comm_none"/*so deleting after setup does not interefere*/,"frame_invariant","restart_no")),
57     mapTagMax_(0),
58     verbose_(false)
59   {
60   }
61 
62   /* ----------------------------------------------------------------------
63    destructor
64   ------------------------------------------------------------------------- */
65 
66   template<int NUM_NODES>
~TrackingMesh()67   TrackingMesh<NUM_NODES>::~TrackingMesh()
68   {
69      delete &customValues_;
70 
71      // deallocate map memory if exists
72      if(!mapArray_.empty()) clearMap();
73   }
74 
75   /* ----------------------------------------------------------------------
76    add / delete element
77   ------------------------------------------------------------------------- */
78 
79   template<int NUM_NODES>
addElement(double ** nodeToAdd,int lineNumb)80   bool TrackingMesh<NUM_NODES>::addElement(double **nodeToAdd,int lineNumb)
81   {
82     // this function is always called in serial mode
83 
84     if(MultiNodeMeshParallel<NUM_NODES>::addElement(nodeToAdd))
85     {
86         // tracking mesh add one element, grow memory if necessary
87         customValues_.addZeroElement();
88 
89         // set ID for element
90         // ID starts from 0
91         id_(this->sizeLocal()-1) = this->sizeLocal()-1;
92         if(lineNo_)
93             (*lineNo_)(this->sizeLocal()-1) = lineNumb;
94 
95         return true;
96     }
97     return false;
98   }
99 
100   template<int NUM_NODES>
deleteElement(int n)101   void TrackingMesh<NUM_NODES>::deleteElement(int n)
102   {
103     MultiNodeMeshParallel<NUM_NODES>::deleteElement(n);
104 
105     // tracking mesh delete code
106     customValues_.deleteElement(n);
107   }
108 
109   /* ----------------------------------------------------------------------
110    reset global properties to original value
111   ------------------------------------------------------------------------- */
112 
113   template<int NUM_NODES>
setVerbose()114   void TrackingMesh<NUM_NODES>::setVerbose()
115   {
116     verbose_ = true;
117   }
118 
119   /* ----------------------------------------------------------------------
120    reset global properties to original value
121   ------------------------------------------------------------------------- */
122 
123   template<int NUM_NODES>
resetToOrig()124   bool TrackingMesh<NUM_NODES>::resetToOrig()
125   {
126     if(MultiNodeMesh<NUM_NODES>::resetToOrig())
127     {
128         customValues_.resetToOrig();
129         return true;
130     }
131     return false;
132   }
133 
134   /* ----------------------------------------------------------------------
135    recalculate properties on setup (on start and during simulation)
136   ------------------------------------------------------------------------- */
137 
138   template<int NUM_NODES>
postInitialSetup()139   void TrackingMesh<NUM_NODES>::postInitialSetup()
140   {
141     this->prop().removeElementProperty("lineNo");
142     lineNo_ = 0;
143   }
144 
145   /* ----------------------------------------------------------------------
146    recalculate properties on setup (on start and during simulation)
147   ------------------------------------------------------------------------- */
148 
149   template<int NUM_NODES>
refreshOwned(int setupFlag)150   void TrackingMesh<NUM_NODES>::refreshOwned(int setupFlag)
151   {
152     MultiNodeMeshParallel<NUM_NODES>::refreshOwned(setupFlag);
153     if(setupFlag) customValues_.storeOrig();
154   }
155 
156   template<int NUM_NODES>
refreshGhosts(int setupFlag)157   void TrackingMesh<NUM_NODES>::refreshGhosts(int setupFlag)
158   {
159     MultiNodeMeshParallel<NUM_NODES>::refreshGhosts(setupFlag);
160   }
161 
162   /* ----------------------------------------------------------------------
163    clear and generate a global map for global-local lookup
164   ------------------------------------------------------------------------- */
165 
166   template<int NUM_NODES>
clearMap()167   void TrackingMesh<NUM_NODES>::clearMap()
168   {
169       // deallocate old memory
170       mapArray_.clear();
171   }
172 
173   template<int NUM_NODES>
generateMap()174   void TrackingMesh<NUM_NODES>::generateMap()
175   {
176       int nall = this->sizeLocal() + this->sizeGhost();
177 
178       // deallocate old memory if exists
179       if(!mapArray_.empty()) clearMap();
180 
181       // get max ID of all proc
182       int idmax = id_.max(nall);
183       MPI_Max_Scalar(idmax,mapTagMax_,this->world);
184 
185       // build map for owned and ghost particles
186       for (int i = 0; i < nall; i++)
187       {
188 
189           const int id = id_(i);
190           mapArray_[id].push_back(i);
191       }
192   }
193 
194   /* ----------------------------------------------------------------------
195    clear ghost data that is communicated via forward comm - called in forw comm
196   ------------------------------------------------------------------------- */
197 
198   template<int NUM_NODES>
clearGhostForward(bool scale,bool translate,bool rotate)199   void TrackingMesh<NUM_NODES>::clearGhostForward(bool scale,bool translate,bool rotate)
200   {
201       MultiNodeMeshParallel<NUM_NODES>::clearGhostForward(scale,translate,rotate);
202 
203       // delete ghost data from container classes
204       // delete only data that is communicated afterwards
205       for(int i = this->sizeLocal()+this->sizeGhost()-1; i >= this->sizeLocal(); i--)
206           customValues_.deleteForwardElement(i,scale,translate,rotate);
207 
208   }
209 
210   /* ----------------------------------------------------------------------
211    clear reverse properties, i.e. reset all of them to 0
212   ------------------------------------------------------------------------- */
213 
214   template<int NUM_NODES>
clearReverse()215   void TrackingMesh<NUM_NODES>::clearReverse()
216   {
217       MultiNodeMeshParallel<NUM_NODES>::clearReverse();
218       customValues_.clearReverse(this->isScaling(),this->isTranslating(),this->isRotating());
219   }
220 
221   /* ----------------------------------------------------------------------
222    push / pop functions for a list of elements
223   ------------------------------------------------------------------------- */
224 
225   template<int NUM_NODES>
elemListBufSize(int n,int operation,bool scale,bool translate,bool rotate)226   int TrackingMesh<NUM_NODES>::elemListBufSize(int n,int operation,bool scale,bool translate,bool rotate)
227   {
228     int buf_size = 0;
229     buf_size += MultiNodeMeshParallel<NUM_NODES>::elemListBufSize(n,operation,scale,translate,rotate);
230     buf_size += customValues_.elemListBufSize(n,operation,scale,translate,rotate);
231     return buf_size;
232   }
233 
234   template<int NUM_NODES>
pushElemListToBuffer(int n,int * list,int * wraplist,double * buf,int operation,std::list<std::string> * properties,double * dlo,double * dhi,bool scale,bool translate,bool rotate)235   int TrackingMesh<NUM_NODES>::pushElemListToBuffer(int n, int *list, int *wraplist, double *buf, int operation, std::list<std::string> * properties, double *dlo, double *dhi, bool scale,bool translate, bool rotate)
236   {
237     int nsend = 0;
238     nsend += MultiNodeMeshParallel<NUM_NODES>::pushElemListToBuffer(n,list, wraplist, &buf[nsend],operation, properties, dlo, dhi, scale,translate,rotate);
239     nsend += customValues_.pushElemListToBuffer(n,list, wraplist, &buf[nsend],operation, properties, dlo, dhi, scale,translate,rotate);
240     return nsend;
241   }
242 
243   template<int NUM_NODES>
popElemListFromBuffer(int first,int n,double * buf,int operation,std::list<std::string> * properties,bool scale,bool translate,bool rotate)244   int TrackingMesh<NUM_NODES>::popElemListFromBuffer(int first, int n,double *buf, int operation, std::list<std::string> * properties, bool scale,bool translate, bool rotate)
245   {
246     int nrecv = 0;
247     nrecv += MultiNodeMeshParallel<NUM_NODES>::popElemListFromBuffer(first,n,&buf[nrecv],operation, properties, scale,translate,rotate);
248     nrecv += customValues_.popElemListFromBuffer(first,n,&buf[nrecv],operation, properties, scale,translate,rotate);
249     return nrecv;
250   }
251 
252   template<int NUM_NODES>
pushElemListToBufferReverse(int first,int n,double * buf,int operation,std::list<std::string> * properties,bool scale,bool translate,bool rotate)253   int TrackingMesh<NUM_NODES>::pushElemListToBufferReverse(int first, int n,double *buf, int operation, std::list<std::string> * properties, bool scale,bool translate, bool rotate)
254   {
255     int nrecv = 0;
256     nrecv += MultiNodeMeshParallel<NUM_NODES>::pushElemListToBufferReverse(first,n,&buf[nrecv],operation, properties, scale,translate,rotate);
257     nrecv += customValues_.pushElemListToBufferReverse(first,n,&buf[nrecv],operation, properties, scale,translate,rotate);
258     return nrecv;
259   }
260 
261   template<int NUM_NODES>
popElemListFromBufferReverse(int n,int * list,double * buf,int operation,std::list<std::string> * properties,bool scale,bool translate,bool rotate)262   int TrackingMesh<NUM_NODES>::popElemListFromBufferReverse(int n, int *list, double *buf, int operation, std::list<std::string> * properties, bool scale,bool translate, bool rotate)
263   {
264     int nsend = 0;
265     nsend += MultiNodeMeshParallel<NUM_NODES>::popElemListFromBufferReverse(n,list,&buf[nsend],operation, properties, scale,translate,rotate);
266     nsend += customValues_.popElemListFromBufferReverse(n,list,&buf[nsend],operation, properties, scale,translate,rotate);
267     return nsend;
268   }
269 
270   /* ----------------------------------------------------------------------
271    push / pop functions for a single element
272   ------------------------------------------------------------------------- */
273 
274   template<int NUM_NODES>
elemBufSize(int operation,std::list<std::string> * properties,bool scale,bool translate,bool rotate)275   int TrackingMesh<NUM_NODES>::elemBufSize(int operation, std::list<std::string> * properties, bool scale,bool translate,bool rotate)
276   {
277     int buf_size = 0;
278     buf_size += MultiNodeMeshParallel<NUM_NODES>::elemBufSize(operation, properties, scale,translate,rotate);
279 
280     buf_size += customValues_.elemBufSize(operation, properties, scale,translate,rotate);
281 
282     return buf_size;
283   }
284 
285   template<int NUM_NODES>
pushElemToBuffer(int n,double * buf,int operation,bool scale,bool translate,bool rotate)286   int TrackingMesh<NUM_NODES>::pushElemToBuffer(int n, double *buf, int operation,bool scale,bool translate, bool rotate)
287   {
288     int nsend = 0;
289     nsend += MultiNodeMeshParallel<NUM_NODES>::pushElemToBuffer(n,&buf[nsend],operation,scale,translate,rotate);
290     nsend += customValues_.pushElemToBuffer(n,&buf[nsend],operation,scale,translate,rotate);
291     return nsend;
292   }
293 
294   template<int NUM_NODES>
popElemFromBuffer(double * buf,int operation,bool scale,bool translate,bool rotate)295   int TrackingMesh<NUM_NODES>::popElemFromBuffer(double *buf, int operation,bool scale,bool translate, bool rotate)
296   {
297     int nrecv = 0;
298     nrecv += MultiNodeMeshParallel<NUM_NODES>::popElemFromBuffer(&buf[nrecv],operation,scale,translate,rotate);
299 
300     nrecv += customValues_.popElemFromBuffer(&buf[nrecv],operation,scale,translate,rotate);
301     return nrecv;
302   }
303 
304   /* ----------------------------------------------------------------------
305    push / pop functions for mesh properties
306   ------------------------------------------------------------------------- */
307 
308   template<int NUM_NODES>
meshPropsBufSize(int operation,bool scale,bool translate,bool rotate)309   int TrackingMesh<NUM_NODES>::meshPropsBufSize(int operation,bool scale,bool translate,bool rotate)
310   {
311     int buf_size = 0;
312     buf_size += customValues_.globalPropsBufSize(operation,scale,translate,rotate);
313 
314     return buf_size;
315   }
316 
317   template<int NUM_NODES>
pushMeshPropsToBuffer(double * buf,int operation,bool scale,bool translate,bool rotate)318   int TrackingMesh<NUM_NODES>::pushMeshPropsToBuffer(double *buf, int operation,bool scale,bool translate, bool rotate)
319   {
320     int nsend = 0;
321     nsend += customValues_.pushGlobalPropsToBuffer(&buf[nsend],operation,scale,translate,rotate);
322     return nsend;
323   }
324 
325   template<int NUM_NODES>
popMeshPropsFromBuffer(double * buf,int operation,bool scale,bool translate,bool rotate)326   int TrackingMesh<NUM_NODES>::popMeshPropsFromBuffer(double *buf, int operation,bool scale,bool translate, bool rotate)
327   {
328     int nrecv = 0;
329     nrecv += customValues_.popGlobalPropsFromBuffer(&buf[nrecv],operation,scale,translate,rotate);
330     return nrecv;
331   }
332 
333   /* ----------------------------------------------------------------------
334    move / rotate  / scale
335   ------------------------------------------------------------------------- */
336 
337   template<int NUM_NODES>
move(const double * const vecTotal,const double * const vecIncremental)338   void TrackingMesh<NUM_NODES>::move(const double * const vecTotal, const double * const vecIncremental)
339   {
340 
341     MultiNodeMesh<NUM_NODES>::move(vecTotal, vecIncremental);
342     customValues_.move(vecTotal,vecIncremental);
343   }
344 
345   template<int NUM_NODES>
move(const double * const vecIncremental)346   void TrackingMesh<NUM_NODES>::move(const double * const vecIncremental)
347   {
348 
349     MultiNodeMesh<NUM_NODES>::move(vecIncremental);
350     customValues_.move(vecIncremental);
351   }
352 
353   template<int NUM_NODES>
moveElement(const int i,const double * const vecIncremental)354   void TrackingMesh<NUM_NODES>::moveElement(const int i, const double * const vecIncremental)
355   {
356     MultiNodeMesh<NUM_NODES>::moveElement(i,vecIncremental);
357     customValues_.moveElement(i,vecIncremental);
358   }
359 
360   template<int NUM_NODES>
rotate(const double * const totalQ,const double * const dQ,const double * const origin)361   void TrackingMesh<NUM_NODES>::rotate(const double * const totalQ, const double * const dQ, const double * const origin)
362   {
363     double negorigin[3];
364     bool trans = vectorMag3DSquared(origin) > 0.;
365     vectorNegate3D(origin,negorigin);
366 
367     MultiNodeMesh<NUM_NODES>::rotate(totalQ,dQ,origin);
368 
369     if(trans) customValues_.move(negorigin);
370     customValues_.rotate(totalQ,dQ);
371     if(trans) customValues_.move(origin);
372   }
373 
374   template<int NUM_NODES>
rotate(const double * const dQ,const double * const origin)375   void TrackingMesh<NUM_NODES>::rotate(const double * const dQ, const double * const origin)
376   {
377     double negorigin[3];
378     bool trans = vectorMag3DSquared(origin) > 0.;
379     vectorNegate3D(origin,negorigin);
380 
381     MultiNodeMesh<NUM_NODES>::rotate(dQ,origin);
382 
383     if(trans) customValues_.move(negorigin);
384     customValues_.rotate(dQ);
385     if(trans) customValues_.move(origin);
386   }
387 
388   template<int NUM_NODES>
scale(double factor)389   void TrackingMesh<NUM_NODES>::scale(double factor)
390   {
391 
392     MultiNodeMesh<NUM_NODES>::scale(factor);
393     customValues_.scale(factor);
394   }
395 
396   /* ----------------------------------------------------------------------
397    return container classes
398   ------------------------------------------------------------------------- */
399 /*
400   template <typename U>
401   containerTmp(
402 
403   template<int NUM_NODES> template<typename U>
404   U* TrackingMesh<NUM_NODES>::containerTmp(int len)
405   {
406       if(len ==1) return MultiVectorConainer
407   }
408 
409   template<int NUM_NODES>
410   void TrackingMesh<NUM_NODES>::move(double *vecTotal, double *vecIncremental)
411   {
412 
413     MultiNodeMesh<NUM_NODES>::move(vecTotal, vecIncremental);
414     customValues_.move(vecIncremental);
415   }*/
416 
417 #endif
418