forked from lijiext/lammps
327 lines
11 KiB
C++
327 lines
11 KiB
C++
// A class for wrapping matrix operations with dependency information to speed up execution
|
|
|
|
#ifndef DEPENDENCY_MANAGER_H
|
|
#define DEPENDENCY_MANAGER_H
|
|
|
|
#include "ATC_TypeDefs.h"
|
|
#include "MatrixLibrary.h"
|
|
#include "ATC_Error.h"
|
|
#include "MPI_Wrappers.h"
|
|
|
|
namespace ATC {
|
|
|
|
class InterscaleManager;
|
|
|
|
/** memory type */
|
|
enum MemoryType
|
|
{
|
|
TEMPORARY = 0,
|
|
PERSISTENT
|
|
};
|
|
|
|
/**
|
|
* @class DependencyManager
|
|
* @brief Base class for defining objects that manage the dependencies of various objects
|
|
*/
|
|
|
|
class DependencyManager {
|
|
|
|
public:
|
|
|
|
// used as a friend so it can perform a depth-first search to have safe deletions of managed dependencies
|
|
friend class InterscaleManager;
|
|
|
|
// constructor
|
|
DependencyManager() : needReset_(true), isFixed_(false), memoryType_(TEMPORARY), dfsFound_(false) {};
|
|
|
|
// destructor
|
|
virtual ~DependencyManager() {};
|
|
|
|
/** registration by other PerAtomQuantity objects */
|
|
void register_dependence(DependencyManager * dependentQuantity)
|
|
{dependentQuantities_.insert(dependentQuantity);};
|
|
|
|
/** removes dependencies from the set */
|
|
void remove_dependence(DependencyManager * dependentQuantity)
|
|
{dependentQuantities_.erase(dependentQuantity);};
|
|
|
|
/** check if a reset is required */
|
|
bool need_reset() const {return needReset_ && !isFixed_;};
|
|
|
|
/** propagate need to reset to to dependencies */
|
|
void propagate_reset()
|
|
{
|
|
if (!isFixed_) {
|
|
std::set<DependencyManager *>::iterator it;
|
|
for (it = dependentQuantities_.begin(); it != dependentQuantities_.end(); it++)
|
|
(*it)->force_reset();
|
|
}
|
|
};
|
|
|
|
/** actions associated with indicating this quantity requires a reset */
|
|
void set_reset()
|
|
{
|
|
needReset_ = true;
|
|
}
|
|
|
|
/** flip this object to needing a reset, and get dependencies */
|
|
void force_reset()
|
|
{
|
|
set_reset();
|
|
propagate_reset();
|
|
}
|
|
|
|
/** force quantity to be held fixed, enables dependent quantity to be used as persistent storage */
|
|
void fix_quantity() {isFixed_ = true;};
|
|
|
|
/** unfix the quantity */
|
|
void unfix_quantity()
|
|
{
|
|
if (isFixed_) {
|
|
isFixed_ = false;
|
|
if (needReset_) propagate_reset();
|
|
}
|
|
};
|
|
|
|
/** check on the memory type of the quantity */
|
|
MemoryType memory_type() const {return memoryType_;};
|
|
|
|
/** set the memory type of the quantity */
|
|
void set_memory_type(MemoryType memoryType) {memoryType_ = memoryType;};
|
|
|
|
|
|
protected:
|
|
|
|
/** list of dependent atomic quantities */
|
|
std::set<DependencyManager * > dependentQuantities_;
|
|
|
|
/** flag for needing a recent */
|
|
// mutable is applied because there can be internal updates because we update when needed rather than when pushed
|
|
mutable bool needReset_;
|
|
|
|
/** flag for if quantity is being held fixed */
|
|
bool isFixed_;
|
|
|
|
/** flag for if the quantity is temporary (per-run) */
|
|
MemoryType memoryType_;
|
|
|
|
/** flag for if the node has been found in depth-first search */
|
|
bool dfsFound_;
|
|
|
|
};
|
|
|
|
/**
|
|
* @class MatrixDependencyManager
|
|
* @brief Class for defining objects that manage the dependencies of matrices
|
|
*/
|
|
|
|
// Matrix class T, underlying type U
|
|
template <template <typename> class T, typename U>
|
|
class MatrixDependencyManager : public DependencyManager {
|
|
|
|
public:
|
|
|
|
MatrixDependencyManager() {};
|
|
MatrixDependencyManager(int nRows, int nCols) : quantity_(nRows,nCols) {};
|
|
virtual ~MatrixDependencyManager() {};
|
|
|
|
/** returns a non-const version for manipulations and changes, resets dependent quantities */
|
|
virtual T<U> & set_quantity() {propagate_reset(); return get_quantity();};
|
|
|
|
/** access to a constant dense matrix of the quantity, indexed by AtC atom counts */
|
|
virtual const T<U> & quantity() const {return get_quantity();};
|
|
|
|
/** number of rows in quantity */
|
|
virtual int nRows() const {return (this->quantity()).nRows();};
|
|
|
|
/** number of columns in quantity */
|
|
virtual int nCols() const {return (this->quantity()).nCols();};
|
|
|
|
/** size of the matrix */
|
|
virtual int size() const {return (this->quantity()).size();};
|
|
|
|
/** reset the quantities size */
|
|
void reset(INDEX nRows, INDEX nCols) {get_quantity().reset(nRows,nCols); propagate_reset();};
|
|
|
|
/** resize the quantities size */
|
|
void resize(INDEX nRows, INDEX nCols) {get_quantity().resize(nRows,nCols); propagate_reset();};
|
|
|
|
/** sets the quantity to a given value */
|
|
virtual void operator=(const T<U> & target) {get_quantity()=target; propagate_reset();};
|
|
/** sets the quantity to a given constant value */
|
|
virtual void operator=(U target) {get_quantity()=target; propagate_reset();};
|
|
|
|
/** adds the given data to the Lammps quantity */
|
|
virtual void operator+=(const T<U> & addition) {get_quantity()+=addition; propagate_reset();};
|
|
/** adds the scalar data to the Lammps quantity for AtC atoms */
|
|
virtual void operator+=(U addition) {get_quantity()+=addition; propagate_reset();};
|
|
|
|
/** adds the given data to the Lammps quantity */
|
|
virtual void operator-=(const T<U> & subtraction) {get_quantity()-=subtraction; propagate_reset();};
|
|
/** adds the scalar data to the Lammps quantity for AtC atoms */
|
|
virtual void operator-=(U subtraction) {get_quantity()-=subtraction; propagate_reset();};
|
|
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator*=(const T<U> & multiplier) {get_quantity()*=multiplier; propagate_reset();};
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator*=(U multiplier) {get_quantity()*=multiplier; propagate_reset();};
|
|
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator/=(const T<U> & divisor) {get_quantity()/=divisor; propagate_reset();};
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator/=(U divisor) {get_quantity()/=divisor; propagate_reset();};
|
|
|
|
// I have no idea why these won't compile (JAT, 04/07/11)
|
|
/** adds the given data to the Lammps quantity */
|
|
virtual void operator+=(const MatrixDependencyManager<T,U> & addition) {get_quantity()+=addition.quantity(); propagate_reset();};
|
|
|
|
/** adds the given data to the Lammps quantity */
|
|
virtual void operator-=(const MatrixDependencyManager<T,U> & subtraction) {get_quantity()-=subtraction.quantity(); propagate_reset();};
|
|
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator*=(const MatrixDependencyManager<T,U> & multiplier) {get_quantity()*=multiplier.quantity(); propagate_reset();};
|
|
|
|
/** multiples the Lammps quantity by the given data, input is indexed in AtC atom counts */
|
|
virtual void operator/=(const MatrixDependencyManager<T,U> & divisor) {get_quantity()/=divisor.quantity(); propagate_reset();};
|
|
|
|
/** execute the matrix print command */
|
|
virtual void print(const std::string &name) const {get_quantity().print(name);};
|
|
|
|
protected:
|
|
|
|
// This getter can be overridden by derived classes if they need e.g. a
|
|
// differently-constructed quantity, but would like to use the same operators.
|
|
virtual T<U> &get_quantity() const { return quantity_; }
|
|
|
|
/** matrix */
|
|
// mutable is applied because there can be internal updates because we update when needed rather than when pushed
|
|
mutable T<U> quantity_;
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* @class MatrixDependencyManager<ParSparseMatrix, T>
|
|
* @brief Class for defining objects that manage the dependencies of parallelized sparse matrices
|
|
*/
|
|
template<typename T>
|
|
class MatrixDependencyManager<ParSparseMatrix, T> :
|
|
public MatrixDependencyManager<SparseMatrix, T>
|
|
{
|
|
public:
|
|
|
|
MatrixDependencyManager(MPI_Comm comm) :
|
|
MatrixDependencyManager<SparseMatrix, T>(), quantity_(comm) {};
|
|
|
|
MatrixDependencyManager(MPI_Comm comm, int nRows, int nCols) :
|
|
MatrixDependencyManager<SparseMatrix, T>(), quantity_(comm, nRows, nCols) {};
|
|
|
|
virtual ~MatrixDependencyManager() {};
|
|
|
|
protected:
|
|
|
|
// Let the superclass's operators work on our ParSparseMatrix.
|
|
virtual ParSparseMatrix<T> &get_quantity() const { return quantity_; }
|
|
|
|
mutable ParSparseMatrix<T> quantity_;
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* @class MatrixDependencyManager<ParDiagonalMatrix, T>
|
|
* @brief Class for defining objects that manage the dependencies of parallelized diagonal matrices
|
|
*/
|
|
template<typename T>
|
|
class MatrixDependencyManager<ParDiagonalMatrix, T> :
|
|
public MatrixDependencyManager<DiagonalMatrix, T>
|
|
{
|
|
public:
|
|
|
|
MatrixDependencyManager(MPI_Comm comm) :
|
|
MatrixDependencyManager<DiagonalMatrix, T>(), quantity_(comm) {};
|
|
|
|
MatrixDependencyManager(MPI_Comm comm, int nRows, int nCols) :
|
|
MatrixDependencyManager<DiagonalMatrix, T>(), quantity_(comm, nRows, nCols) {};
|
|
|
|
virtual ~MatrixDependencyManager() {};
|
|
|
|
protected:
|
|
|
|
// Let the superclass's operators work on our ParDiagonalMatrix.
|
|
virtual ParDiagonalMatrix<T> &get_quantity() const { return quantity_; }
|
|
|
|
mutable ParDiagonalMatrix<T> quantity_;
|
|
|
|
};
|
|
|
|
/**
|
|
* @class SetDependencyManager
|
|
* @brief Class for defining objects that manage the dependencies of standard library sets
|
|
*/
|
|
template <typename T>
|
|
class SetDependencyManager : public DependencyManager {
|
|
|
|
public:
|
|
|
|
// constructor
|
|
SetDependencyManager() :
|
|
DependencyManager(), quantity_() {};
|
|
|
|
// destructor
|
|
virtual ~SetDependencyManager() {};
|
|
|
|
/** returns a non-const version for manipulations and changes, resets dependent quantities */
|
|
virtual std::set<T> & set_quantity() {propagate_reset(); return quantity_;};
|
|
|
|
/** access to a constant dense matrix of the quantity, indexed by AtC atom counts */
|
|
virtual const std::set<T> & quantity() const {return quantity_;};
|
|
|
|
/** size of the set */
|
|
virtual int size() const {return (this->quantity()).size();};
|
|
|
|
protected:
|
|
|
|
/** underlying set */
|
|
// mutable is applied because there can be internal updates because we update when needed rather than when pushed
|
|
mutable std::set<T> quantity_;
|
|
|
|
};
|
|
|
|
/**
|
|
* @class VectorDependencyManager
|
|
* @brief Class for defining objects that manage the dependencies of standard library vectors
|
|
*/
|
|
template <typename T>
|
|
class VectorDependencyManager : public DependencyManager {
|
|
|
|
public:
|
|
|
|
// constructor
|
|
VectorDependencyManager() :
|
|
DependencyManager(), quantity_() {};
|
|
|
|
// destructor
|
|
virtual ~VectorDependencyManager() {};
|
|
|
|
/** returns a non-const version for manipulations and changes, resets dependent quantities */
|
|
virtual std::vector<T> & set_quantity() {propagate_reset(); return quantity_;};
|
|
|
|
/** access to a constant dense matrix of the quantity, indexed by AtC atom counts */
|
|
virtual const std::vector<T> & quantity() const {return quantity_;};
|
|
|
|
/** size of the set */
|
|
virtual int size() const {return (this->quantity()).size();};
|
|
|
|
protected:
|
|
|
|
/** underlying set */
|
|
// mutable is applied because there can be internal updates because we update when needed rather than when pushed
|
|
mutable std::vector<T> quantity_;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
#endif
|