1 // An interscale operator class for sharing definitions of atomic quantities, e.g., temperature 2 // between different parts of the code 3 4 #ifndef INTERSCALE_MANAGER_H 5 #define INTERSCALE_MANAGER_H 6 7 #include "MatrixLibrary.h" 8 #include "ATC_TypeDefs.h" 9 #include "ATC_Error.h" 10 #include "LammpsInterface.h" 11 #include "PerAtomQuantity.h" 12 #include "PerPairQuantity.h" 13 #include "FundamentalAtomicQuantity.h" 14 #include <vector> 15 #include <map> 16 #include <set> 17 #include <string> 18 #include <utility> 19 20 namespace ATC { 21 22 // forward declarations 23 class ATC_Method; 24 class SmallMoleculeSet; 25 26 /** 27 * @class InterscaleManager 28 * @brief Handles definitions for atomistic quantities 29 */ 30 31 //-------------------------------------------------------- 32 //-------------------------------------------------------- 33 // Class InterscaleManager 34 //-------------------------------------------------------- 35 //-------------------------------------------------------- 36 37 class InterscaleManager { 38 39 public: 40 41 // constructor 42 InterscaleManager(ATC_Method * atc); 43 44 // destructor 45 ~InterscaleManager(); 46 47 /** delete all allocated data */ 48 void clear(); 49 50 /** delete non-persistent data */ 51 void clear_temporary_data(); 52 53 /** set lammps data prefix */ 54 void set_lammps_data_prefix(); 55 56 /** parser/modifier */ 57 bool modify(int narg, char **arg); 58 59 /** pre time integration */ 60 void initialize(); 61 62 // access to per atom quantity objects 63 /** access to fundamental atomic quantities */ 64 FundamentalAtomQuantity * fundamental_atom_quantity(LammpsInterface::FundamentalAtomQuantity id, 65 AtomType atomType = INTERNAL); 66 /** access to double per atom quantities */ 67 PerAtomQuantity<double> * per_atom_quantity(const std::string & tag); 68 /** access to integer per atom quantities */ 69 PerAtomQuantity<int> * per_atom_int_quantity(const std::string & tag); 70 /** access to double per atom diagonal matrices */ 71 PerAtomDiagonalMatrix<double> * per_atom_diagonal_matrix(const std::string & tag); 72 /** access to double per atom sparse matrices */ 73 PerAtomSparseMatrix<double> * per_atom_sparse_matrix(const std::string & tag); 74 /** access to pair maps */ 75 PairMap * pair_map(const std::string & tag); 76 77 // addition of new atom quantities, note provider must allocate but the manager will clean-up 78 /** addition of a double atomic quantity */ 79 void add_per_atom_quantity(PerAtomQuantity<double> * atomQuantity, 80 const std::string & tag); 81 /** addition of an integer atomic quantity */ 82 void add_per_atom_int_quantity(PerAtomQuantity<int> * atomQuantity, 83 const std::string & tag); 84 /** addition of a double atomic diagonal matrix */ 85 void add_per_atom_diagonal_matrix(PerAtomDiagonalMatrix<double> * atomQuantity, 86 const std::string & tag); 87 /** addition of a double atomic sparse matrix */ 88 void add_per_atom_sparse_matrix(PerAtomSparseMatrix<double> * atomQuantity, 89 const std::string & tag); 90 /** addition of an pair map */ 91 void add_pair_map(PairMap * pairMap, const std::string & tag); 92 93 /** access to dense matrices */ 94 DENS_MAN * dense_matrix(const std::string & tag); 95 96 /** addition of dense matrices */ 97 void add_dense_matrix(DENS_MAN * denseMatrix, 98 const std::string & tag); 99 100 /** access integer dense matrices */ 101 MatrixDependencyManager<DenseMatrix, int> * dense_matrix_int(const std::string & tag); 102 103 /** addition of integer dense matrices */ 104 void add_dense_matrix_int(MatrixDependencyManager<DenseMatrix, int> * denseMatrix, 105 const std::string & tag); 106 107 /** access boolean dense matrices */ 108 MatrixDependencyManager<DenseMatrix, bool> * dense_matrix_bool(const std::string & tag); 109 110 /** addition of boolean dense matrices */ 111 void add_dense_matrix_bool(MatrixDependencyManager<DenseMatrix, bool> * denseMatrix, 112 const std::string & tag); 113 114 /** access to sparse matrices */ 115 SPAR_MAN * sparse_matrix(const std::string & tag); 116 117 /** addition of a sparse matrix */ 118 void add_sparse_matrix(SPAR_MAN * sparseMatrix, 119 const std::string & tag); 120 121 /** access to diagonal matrices */ 122 DIAG_MAN * diagonal_matrix(const std::string & tag); 123 124 /** addition of a diagonal matrix */ 125 void add_diagonal_matrix(DIAG_MAN * diagonalMatrix, 126 const std::string & tag); 127 128 /** access to vectors of sparse matrices */ 129 VectorDependencyManager<SPAR_MAT * > * vector_sparse_matrix(const std::string & tag); 130 131 /** addition of a vector of sparse matrices */ 132 void add_vector_sparse_matrix(VectorDependencyManager<SPAR_MAT * > * sparseMatrix, 133 const std::string & tag); 134 135 /** access to sets of ints */ 136 SetDependencyManager<int> * set_int(const std::string & tag); 137 138 /** addition of a set of ints */ 139 void add_set_int(SetDependencyManager<int> * sparseMatrix, 140 const std::string & tag); 141 142 /** access to molecule sets */ 143 SmallMoleculeSet * small_molecule_set(const std::string & tag); 144 145 /** addition of a transfer operator */ 146 void add_small_molecule_set(SmallMoleculeSet * moleculeSet, 147 const std::string & tag); 148 149 /** addition of exchange list object */ 150 void add_to_exchange_list(const std::string & tag); 151 152 /** searches through all lists to see if a tag is registered */ 153 DependencyManager * find(const std::string & tag); 154 155 /** schedules a quantity for deletion, if it exists */ 156 void remove(const std::string & tag); 157 158 /** size communicated quantities initially */ 159 void size_comm_quantities(); 160 161 /** resets nlocal count of managed atomic quantities which do not perform parallel exchange */ 162 void reset_nlocal(); 163 164 /** resets specific lammps fundamental quantities data, as needed, to account for times when lammps can change quantities */ 165 void fundamental_force_reset(unsigned quantity); 166 167 /** resets all lammps data, as needed, to account for times when lammps can change quantities */ 168 void lammps_force_reset(); 169 170 /** syncs lammps data to managed objects for parallel communication */ 171 void prepare_exchange(); 172 173 /** syncs managed objects to lammps data after parallel communication */ 174 void post_exchange(); 175 176 /** returns how much lammps memory is used in this function */ 177 int memory_usage() const; 178 179 /** packs up data for parallel transfer, called from pack_exchange */ 180 int pack_exchange(int i, double *buffer); 181 182 /** unpacks data after parallel transfer, called from unpack_exchange */ 183 int unpack_exchange(int i, double *buffer); 184 185 /** packs up data for parallel transfer to ghost atoms on other processors */ 186 int pack_comm(int index, double *buf, 187 int pbc_flag, int *pbc); 188 189 /** unpacks data after parallel transfer to ghost atoms on other processors */ 190 int unpack_comm(int index, double *buf); 191 192 /** changes size of temperary lammps storage data if transfer is being used */ 193 void grow_arrays(int nmax); 194 195 /** rearrange memory of temporary lammps storage data, called from copy_array */ 196 void copy_arrays(int i, int j); 197 198 protected: 199 200 /** pointer to access ATC methods */ 201 ATC_Method * atc_; 202 203 /** flag for if first initialization has happened */ 204 bool initialized_; 205 206 /** containers for fundamental atom quantities, set on request */ 207 std::vector<std::vector<FundamentalAtomQuantity* > > fundamentalAtomQuantities_; 208 209 /** container for per-atom quantities using dense matrices of doubles */ 210 std::map<std::string, PerAtomQuantity<double> * > perAtomQuantities_; 211 212 /** container for integer atom quantities, set by AtC classes */ 213 std::map<std::string, PerAtomQuantity<int> * > perAtomIntQuantities_; 214 215 /** container for per-atom quantities using diagonal matrices of doubles */ 216 std::map<std::string, PerAtomDiagonalMatrix<double> * > perAtomDiagonalMatrices_; 217 218 /** container for per-atom quantities using sparse matrices of doubles */ 219 std::map<std::string, PerAtomSparseMatrix<double> * > perAtomSparseMatrices_; 220 221 /** container for pair maps */ 222 std::map<std::string, PairMap * > pairMaps_; 223 224 /** container for dense matrices */ 225 std::map<std::string, DENS_MAN * > denseMatrices_; 226 227 /** container for dense matrices for integer quantities */ 228 std::map<std::string, MatrixDependencyManager<DenseMatrix, int> * > denseMatricesInt_; 229 230 /** container for dense matrces for boolean quantities */ 231 std::map<std::string, MatrixDependencyManager<DenseMatrix, bool> * > denseMatricesBool_; 232 233 /** container for sparse matrices */ 234 std::map<std::string, SPAR_MAN * > sparseMatrices_; 235 236 /** container for diagonal matrices */ 237 std::map<std::string, DIAG_MAN * > diagonalMatrices_; 238 239 /** container for vectors of vectors of sparse matrices */ 240 std::map<std::string, VectorDependencyManager<SPAR_MAT * > * > vectorSparMat_; 241 242 /** container for sets of integer quantities */ 243 std::map<std::string, SetDependencyManager<int> * > setInt_; 244 245 /** container for molecule sets */ 246 std::map<std::string, SmallMoleculeSet * > smallMoleculeSets_; 247 248 /** container for atomic quantities which must be transfered when atoms cross processors */ 249 std::set<PerAtomQuantity<double> *> exchangeList_; 250 251 /** container for atomic quantities which must be transfered to ghost atoms on other processors */ 252 std::vector<PerAtomQuantity<double> *> commList_; 253 254 /** container for integer atomic quantities which must be transfered to ghost atoms on other processors */ 255 std::vector<PerAtomQuantity<int> *> commIntList_; 256 257 /** container for atomic diagonal matrices which must be transfered to ghost atoms on other processors */ 258 std::vector<PerAtomDiagonalMatrix<double> *> commDmList_; 259 260 /** container for atomic sparse matrices which must be transfered to ghost atoms on other processors */ 261 std::vector<PerAtomSparseMatrix<double> *> commSmList_; 262 263 /** prefix for labeling associated lammps arrays */ 264 std::string prefix_; 265 266 /** order of deletion list of managed quantities */ 267 std::vector<DependencyManager * > deletionList_; 268 269 /** creates a reverse sorted depth-first search list for deleting managed quantities */ 270 void create_deletion_list(); 271 272 /** executes a depth-first search visit on a managed quantity */ 273 int dfs_visit(DependencyManager * quantity, const int index); 274 275 /** helper function to access a data entry in a list */ 276 template <typename data> return_quantity(std::map<std::string,data * > & list,const std::string & tag)277 data * return_quantity(std::map<std::string,data * > & list, const std::string & tag) 278 { 279 typename std::map<std::string,data * >::iterator it = list.find(tag); 280 if (it==list.end()) return NULL; 281 return it->second; 282 }; 283 284 /** helper function to add a data entry to a list */ 285 template <typename data> add_quantity(std::map<std::string,data * > & list,data * quantity,const std::string & tag)286 void add_quantity(std::map<std::string,data * > & list, data * quantity, const std::string & tag) 287 { 288 typename std::map<std::string,data * >::iterator it = list.find(tag); 289 if (it!=list.end()) 290 throw ATC_Error("Tried to add another Quantity with tag "+tag+" in InterscaleManager::add_quantity"); 291 typename std::template pair<std::string,data * > myPair(tag,quantity); 292 list.insert(myPair); 293 }; 294 295 /** helper function to add a data entry to a list when it requires neighbor communication*/ 296 template <typename data> add_comm_quantity(std::map<std::string,data * > & list,std::vector<data * > & commList,data * quantity,const std::string & tag)297 void add_comm_quantity(std::map<std::string,data * > & list, std::vector<data * > & commList, data * quantity, const std::string & tag) 298 { 299 add_quantity(list,quantity,tag); 300 // allocate data for parallel communication 301 quantity->grow_lammps_array(LammpsInterface::instance()->nmax(),prefix_+tag); 302 if (quantity->atom_type() == PROC_GHOST) { 303 commList.push_back(quantity); 304 } 305 }; 306 307 /** helper function to fina a data entry in a list */ 308 template <typename data> find_in_list(std::map<std::string,data * > & list,const std::string & tag)309 data * find_in_list(std::map<std::string,data * > & list, const std::string & tag) 310 { 311 typename std::map<std::string,data * >::iterator it = list.find(tag); 312 if (it!=list.end()) return it->second; 313 return NULL; 314 }; 315 316 /** helper function to force the reset of all data in a list */ 317 template <typename data> force_reset_loop(std::map<std::string,data * > & list)318 void force_reset_loop(std::map<std::string,data * > & list) 319 { 320 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 321 (it->second)->force_reset(); 322 }; 323 324 /** helper function to set the memory type to temporary of a list */ 325 template <typename data> set_memory_temporary(std::map<std::string,data * > & list)326 void set_memory_temporary(std::map<std::string,data * > & list) 327 { 328 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 329 (it->second)->set_memory_type(TEMPORARY); 330 }; 331 332 /** helper function to perform intialization for dfs of a list */ 333 template <typename data> dfs_prepare_loop(std::map<std::string,data * > & list)334 void dfs_prepare_loop(std::map<std::string,data * > & list) 335 { 336 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) { 337 (it->second)->dfsFound_ = false; 338 } 339 }; 340 341 /** helper function to start the dfs visit for list */ 342 template <typename data> dfs_visit_loop(std::map<std::string,data * > & list,int & index)343 void dfs_visit_loop(std::map<std::string,data * > & list, 344 int & index) 345 { 346 typename std::map<std::string,data* >::iterator it = list.begin(); 347 while (it != list.end()) { 348 if (!((it->second)->dfsFound_)) index = dfs_visit(it->second,index); 349 if ((it->second)->memory_type()==TEMPORARY) list.erase(it++); 350 else ++it; 351 } 352 }; 353 354 // PAQ helper functions 355 /** helper function to adjust local atom count for all data in a list before exchange, only valid with quantities that do that are aware of atom counts */ 356 template <typename data> reset_nlocal_loop(std::map<std::string,data * > & list)357 void reset_nlocal_loop(std::map<std::string,data * > & list) 358 { 359 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) { 360 (it->second)->reset_nlocal(); 361 } 362 }; 363 364 /** helper function to indicate lammps data is stale for all data in a list before exchange, only valid with PAQs */ 365 template <typename data> lammps_reset_loop(std::map<std::string,data * > & list)366 void lammps_reset_loop(std::map<std::string,data * > & list) 367 { 368 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 369 (it->second)->lammps_force_reset(); 370 }; 371 372 /** helper function to size all data in a list, only valid with comm lists */ 373 template <typename data> size_comm_loop(std::vector<data * > & list)374 void size_comm_loop(std::vector<data * > & list) 375 { 376 for (typename std::vector<data* >::iterator it = list.begin(); it != list.end(); ++it) 377 (*it)->quantity(); 378 }; 379 380 /** helper function to pack all data in a list before exchange, only valid with quantities that do work before parallel communication */ 381 template <typename data> prepare_exchange_loop(std::map<std::string,data * > & list)382 void prepare_exchange_loop(std::map<std::string,data * > & list) 383 { 384 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) { 385 (it->second)->prepare_exchange(); 386 } 387 }; 388 389 /** helper function to extract all data in a list after exchange, only valid with quantities that do work after parallel communication */ 390 template <typename data> post_exchange_loop(std::map<std::string,data * > & list)391 void post_exchange_loop(std::map<std::string,data * > & list) 392 { 393 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) { 394 (it->second)->post_exchange(); 395 } 396 }; 397 398 /** helper function to determine memory usage of all data in a list, only valid with PAQs */ 399 template <typename data> memory_usage_loop(const std::map<std::string,data * > & list,int & usage)400 void memory_usage_loop(const std::map<std::string,data * > & list, int & usage) const 401 { 402 for (typename std::map<std::string,data* >::const_iterator it = list.begin(); it != list.end(); ++it) 403 usage += (it->second)->memory_usage(); 404 }; 405 406 /** helper function to pack arrays of all data before exchange in a list, only valid with PAQs */ 407 template <typename data> pack_exchange_loop(std::map<std::string,data * > & list,int & index,int i,double * buffer)408 void pack_exchange_loop(std::map<std::string,data * > & list, int & index, int i, double *buffer) 409 { 410 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) { 411 index += (it->second)->pack_exchange(i,&buffer[index]); 412 } 413 }; 414 415 /** helper function to unpack arrays of all data after exchange in a list, only valid with PAQs */ 416 template <typename data> unpack_exchange_loop(std::map<std::string,data * > & list,int & index,int i,double * buffer)417 void unpack_exchange_loop(std::map<std::string,data * > & list, int & index, int i, double *buffer) 418 { 419 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 420 index += (it->second)->unpack_exchange(i,&buffer[index]); 421 }; 422 423 /** helper function to pack arrays of all data in a list, only valid with comm lists */ 424 template <typename data> pack_comm_loop(std::vector<data * > & list,int & size,int index,double * buf,int pbc_flag,int * pbc)425 void pack_comm_loop(std::vector<data * > & list, int & size, int index, double *buf, 426 int pbc_flag, int *pbc) 427 { 428 for (typename std::vector<data* >::iterator it = list.begin(); it != list.end(); ++it) 429 size += (*it)->pack_comm(index,&buf[size],pbc_flag,pbc); 430 }; 431 432 /** helper function to unpack arrays of all data in a list, only valid with comm lists */ 433 template <typename data> unpack_comm_loop(std::vector<data * > & list,int & size,int index,double * buf)434 void unpack_comm_loop(std::vector<data * > & list, int & size, int index, double *buf) 435 { 436 for (typename std::vector<data* >::iterator it = list.begin(); it != list.end(); ++it) 437 size += (*it)->unpack_comm(index,&buf[size]); 438 }; 439 440 /** helper function to grow arrays of all data in a list, only valid with PAQs */ 441 template <typename data> grow_arrays_loop(std::map<std::string,data * > & list,int nmax)442 void grow_arrays_loop(std::map<std::string,data * > & list, int nmax) 443 { 444 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 445 (it->second)->grow_lammps_array(nmax,prefix_+it->first); 446 }; 447 448 /** helper function to copy arrays of all data in a list, only valid with PAQs */ 449 template <typename data> copy_arrays_loop(std::map<std::string,data * > & list,int i,int j)450 void copy_arrays_loop(std::map<std::string,data * > & list, int i, int j) 451 { 452 for (typename std::map<std::string,data* >::iterator it = list.begin(); it != list.end(); ++it) 453 (it->second)->copy_lammps_array(i,j); 454 }; 455 456 private: 457 458 459 InterscaleManager(); 460 461 }; 462 463 } 464 465 #endif 466