// An interscale operator class for sharing definitions of atomic quantities, e.g., temperature // between different parts of the code #ifndef INTERSCALE_MANAGER_H #define INTERSCALE_MANAGER_H #include "MatrixLibrary.h" #include "ATC_TypeDefs.h" #include "ATC_Error.h" #include "LammpsInterface.h" #include "PerAtomQuantity.h" #include "PerPairQuantity.h" #include "FundamentalAtomicQuantity.h" #include #include #include #include #include namespace ATC { // forward declarations class ATC_Method; class SmallMoleculeSet; /** * @class InterscaleManager * @brief Handles definitions for atomistic quantities */ //-------------------------------------------------------- //-------------------------------------------------------- // Class InterscaleManager //-------------------------------------------------------- //-------------------------------------------------------- class InterscaleManager { public: // constructor InterscaleManager(ATC_Method * atc); // destructor ~InterscaleManager(); /** delete all allocated data */ void clear(); /** delete non-persistent data */ void clear_temporary_data(); /** set lammps data prefix */ void set_lammps_data_prefix(); /** parser/modifier */ bool modify(int narg, char **arg); /** pre time integration */ void initialize(); // access to per atom quantity objects /** access to fundamental atomic quantities */ FundamentalAtomQuantity * fundamental_atom_quantity(LammpsInterface::FundamentalAtomQuantity id, AtomType atomType = INTERNAL); /** access to double per atom quantities */ PerAtomQuantity * per_atom_quantity(const std::string & tag); /** access to integer per atom quantities */ PerAtomQuantity * per_atom_int_quantity(const std::string & tag); /** access to double per atom diagonal matrices */ PerAtomDiagonalMatrix * per_atom_diagonal_matrix(const std::string & tag); /** access to double per atom sparse matrices */ PerAtomSparseMatrix * per_atom_sparse_matrix(const std::string & tag); /** access to pair maps */ PairMap * pair_map(const std::string & tag); // addition of new atom quantities, note provider must allocate but the manager will clean-up /** addition of a double atomic quantity */ void add_per_atom_quantity(PerAtomQuantity * atomQuantity, const std::string & tag); /** addition of an integer atomic quantity */ void add_per_atom_int_quantity(PerAtomQuantity * atomQuantity, const std::string & tag); /** addition of a double atomic diagonal matrix */ void add_per_atom_diagonal_matrix(PerAtomDiagonalMatrix * atomQuantity, const std::string & tag); /** addition of a double atomic sparse matrix */ void add_per_atom_sparse_matrix(PerAtomSparseMatrix * atomQuantity, const std::string & tag); /** addition of an pair map */ void add_pair_map(PairMap * pairMap, const std::string & tag); /** access to dense matrices */ DENS_MAN * dense_matrix(const std::string & tag); /** addition of dense matrices */ void add_dense_matrix(DENS_MAN * denseMatrix, const std::string & tag); /** access integer dense matrices */ MatrixDependencyManager * dense_matrix_int(const std::string & tag); /** addition of integer dense matrices */ void add_dense_matrix_int(MatrixDependencyManager * denseMatrix, const std::string & tag); /** access boolean dense matrices */ MatrixDependencyManager * dense_matrix_bool(const std::string & tag); /** addition of boolean dense matrices */ void add_dense_matrix_bool(MatrixDependencyManager * denseMatrix, const std::string & tag); /** access to sparse matrices */ SPAR_MAN * sparse_matrix(const std::string & tag); /** addition of a sparse matrix */ void add_sparse_matrix(SPAR_MAN * sparseMatrix, const std::string & tag); /** access to diagonal matrices */ DIAG_MAN * diagonal_matrix(const std::string & tag); /** addition of a diagonal matrix */ void add_diagonal_matrix(DIAG_MAN * diagonalMatrix, const std::string & tag); /** access to vectors of sparse matrices */ VectorDependencyManager * vector_sparse_matrix(const std::string & tag); /** addition of a vector of sparse matrices */ void add_vector_sparse_matrix(VectorDependencyManager * sparseMatrix, const std::string & tag); /** access to sets of ints */ SetDependencyManager * set_int(const std::string & tag); /** addition of a set of ints */ void add_set_int(SetDependencyManager * sparseMatrix, const std::string & tag); /** access to molecule sets */ SmallMoleculeSet * small_molecule_set(const std::string & tag); /** addition of a transfer operator */ void add_small_molecule_set(SmallMoleculeSet * moleculeSet, const std::string & tag); /** addition of exchange list object */ void add_to_exchange_list(const std::string & tag); /** searches through all lists to see if a tag is registered */ DependencyManager * find(const std::string & tag); /** schedules a quantity for deletion, if it exists */ void remove(const std::string & tag); /** size communicated quantities initially */ void size_comm_quantities(); /** resets nlocal count of managed atomic quantities which do not perform parallel exchange */ void reset_nlocal(); /** resets specific lammps fundamental quantities data, as needed, to account for times when lammps can change quantities */ void fundamental_force_reset(unsigned quantity); /** resets all lammps data, as needed, to account for times when lammps can change quantities */ void lammps_force_reset(); /** syncs lammps data to managed objects for parallel communication */ void prepare_exchange(); /** syncs managed objects to lammps data after parallel communication */ void post_exchange(); /** returns how much lammps memory is used in this function */ int memory_usage() const; /** packs up data for parallel transfer, called from pack_exchange */ int pack_exchange(int i, double *buffer); /** unpacks data after parallel transfer, called from unpack_exchange */ int unpack_exchange(int i, double *buffer); /** packs up data for parallel transfer to ghost atoms on other processors */ int pack_comm(int index, double *buf, int pbc_flag, int *pbc); /** unpacks data after parallel transfer to ghost atoms on other processors */ int unpack_comm(int index, double *buf); /** changes size of temperary lammps storage data if transfer is being used */ void grow_arrays(int nmax); /** rearrange memory of temporary lammps storage data, called from copy_array */ void copy_arrays(int i, int j); protected: /** pointer to access ATC methods */ ATC_Method * atc_; /** flag for if first initialization has happened */ bool initialized_; /** containers for fundamental atom quantities, set on request */ std::vector > fundamentalAtomQuantities_; /** container for per-atom quantities using dense matrices of doubles */ std::map * > perAtomQuantities_; /** container for integer atom quantities, set by AtC classes */ std::map * > perAtomIntQuantities_; /** container for per-atom quantities using diagonal matrices of doubles */ std::map * > perAtomDiagonalMatrices_; /** container for per-atom quantities using sparse matrices of doubles */ std::map * > perAtomSparseMatrices_; /** container for pair maps */ std::map pairMaps_; /** container for dense matrices */ std::map denseMatrices_; /** container for dense matrices for integer quantities */ std::map * > denseMatricesInt_; /** container for dense matrces for boolean quantities */ std::map * > denseMatricesBool_; /** container for sparse matrices */ std::map sparseMatrices_; /** container for diagonal matrices */ std::map diagonalMatrices_; /** container for vectors of vectors of sparse matrices */ std::map * > vectorSparMat_; /** container for sets of integer quantities */ std::map * > setInt_; /** container for molecule sets */ std::map smallMoleculeSets_; /** container for atomic quantities which must be transfered when atoms cross processors */ std::set *> exchangeList_; /** container for atomic quantities which must be transfered to ghost atoms on other processors */ std::vector *> commList_; /** container for integer atomic quantities which must be transfered to ghost atoms on other processors */ std::vector *> commIntList_; /** container for atomic diagonal matrices which must be transfered to ghost atoms on other processors */ std::vector *> commDmList_; /** container for atomic sparse matrices which must be transfered to ghost atoms on other processors */ std::vector *> commSmList_; /** prefix for labeling associated lammps arrays */ std::string prefix_; /** order of deletion list of managed quantities */ std::vector deletionList_; /** creates a reverse sorted depth-first search list for deleting managed quantities */ void create_deletion_list(); /** executes a depth-first search visit on a managed quantity */ int dfs_visit(DependencyManager * quantity, const int index); /** helper function to access a data entry in a list */ template data * return_quantity(std::map & list, const std::string & tag) { typename std::map::iterator it = list.find(tag); if (it==list.end()) return NULL; return it->second; } /** helper function to add a data entry to a list */ template void add_quantity(std::map & list, data * quantity, const std::string & tag) { typename std::map::iterator it = list.find(tag); if (it!=list.end()) throw ATC_Error("Tried to add another Quantity with tag "+tag+" in InterscaleManager::add_quantity"); typename std::template pair myPair(tag,quantity); list.insert(myPair); } /** helper function to add a data entry to a list when it requires neighbor communication*/ template void add_comm_quantity(std::map & list, std::vector & commList, data * quantity, const std::string & tag) { add_quantity(list,quantity,tag); // allocate data for parallel communication quantity->grow_lammps_array(LammpsInterface::instance()->nmax(),prefix_+tag); if (quantity->atom_type() == PROC_GHOST) { commList.push_back(quantity); } } /** helper function to fina a data entry in a list */ template data * find_in_list(std::map & list, const std::string & tag) { typename std::map::iterator it = list.find(tag); if (it!=list.end()) return it->second; return NULL; } /** helper function to force the reset of all data in a list */ template void force_reset_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) (it->second)->force_reset(); } /** helper function to set the memory type to temporary of a list */ template void set_memory_temporary(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) (it->second)->set_memory_type(TEMPORARY); } /** helper function to perform intialization for dfs of a list */ template void dfs_prepare_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) { (it->second)->dfsFound_ = false; } } /** helper function to start the dfs visit for list */ template void dfs_visit_loop(std::map & list, int & index) { typename std::map::iterator it = list.begin(); while (it != list.end()) { if (!((it->second)->dfsFound_)) index = dfs_visit(it->second,index); if ((it->second)->memory_type()==TEMPORARY) list.erase(it++); else ++it; } } // PAQ helper functions /** 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 */ template void reset_nlocal_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) { (it->second)->reset_nlocal(); } } /** helper function to indicate lammps data is stale for all data in a list before exchange, only valid with PAQs */ template void lammps_reset_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) (it->second)->lammps_force_reset(); } /** helper function to size all data in a list, only valid with comm lists */ template void size_comm_loop(std::vector & list) { for (typename std::vector::iterator it = list.begin(); it != list.end(); ++it) (*it)->quantity(); } /** helper function to pack all data in a list before exchange, only valid with quantities that do work before parallel communication */ template void prepare_exchange_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) { (it->second)->prepare_exchange(); } } /** helper function to extract all data in a list after exchange, only valid with quantities that do work after parallel communication */ template void post_exchange_loop(std::map & list) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) { (it->second)->post_exchange(); } } /** helper function to determine memory usage of all data in a list, only valid with PAQs */ template void memory_usage_loop(const std::map & list, int & usage) const { for (typename std::map::const_iterator it = list.begin(); it != list.end(); ++it) usage += (it->second)->memory_usage(); } /** helper function to pack arrays of all data before exchange in a list, only valid with PAQs */ template void pack_exchange_loop(std::map & list, int & index, int i, double *buffer) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) { index += (it->second)->pack_exchange(i,&buffer[index]); } } /** helper function to unpack arrays of all data after exchange in a list, only valid with PAQs */ template void unpack_exchange_loop(std::map & list, int & index, int i, double *buffer) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) index += (it->second)->unpack_exchange(i,&buffer[index]); } /** helper function to pack arrays of all data in a list, only valid with comm lists */ template void pack_comm_loop(std::vector & list, int & size, int index, double *buf, int pbc_flag, int *pbc) { for (typename std::vector::iterator it = list.begin(); it != list.end(); ++it) size += (*it)->pack_comm(index,&buf[size],pbc_flag,pbc); } /** helper function to unpack arrays of all data in a list, only valid with comm lists */ template void unpack_comm_loop(std::vector & list, int & size, int index, double *buf) { for (typename std::vector::iterator it = list.begin(); it != list.end(); ++it) size += (*it)->unpack_comm(index,&buf[size]); } /** helper function to grow arrays of all data in a list, only valid with PAQs */ template void grow_arrays_loop(std::map & list, int nmax) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) (it->second)->grow_lammps_array(nmax,prefix_+it->first); } /** helper function to copy arrays of all data in a list, only valid with PAQs */ template void copy_arrays_loop(std::map & list, int i, int j) { for (typename std::map::iterator it = list.begin(); it != list.end(); ++it) (it->second)->copy_lammps_array(i,j); }; private: InterscaleManager(); }; } #endif