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