lammps/lib/atc/TransferLibrary.cpp

2009 lines
71 KiB
C++

// ATC headers
#include "TransferLibrary.h"
#include "ATC_Coupling.h"
#include "PrescribedDataManager.h"
#include "LinearSolver.h"
#include "PerAtomQuantityLibrary.h"
#include "KernelFunction.h"
#include "MoleculeSet.h"
//#include <typeinfo>
#include <set>
#include <sstream>
#include <utility>
#include <vector>
using std::set;
using std::map;
using std::string;
using std::stringstream;
using std::pair;
using std::vector;
namespace ATC {
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodalAtomVolume
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
NodalAtomVolume::NodalAtomVolume(ATC_Method * atc,
SPAR_MAN * shapeFunction) :
atc_(atc),
shapeFunction_(shapeFunction),
lammpsInterface_(atc->lammps_interface()),
feEngine_(atc->fe_engine()),
tol_(1.e-10)
{
shapeFunction_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void NodalAtomVolume::reset_quantity() const
{
// solve equation \sum_a N_Ia \sum_J N_Ja dV_J = \int_Omega N_I dV
// form left-hand side
int nNodes = shapeFunction_->nCols();
SPAR_MAT lhs(nNodes,nNodes);
atc_->compute_consistent_md_mass_matrix(shapeFunction_->quantity(),lhs);
// form right-hand side
_rhsMatrix_.resize(nNodes,nNodes);
feEngine_->compute_lumped_mass_matrix(_rhsMatrix_);
_rhs_.resize(nNodes);
_rhs_.copy(_rhsMatrix_.ptr(),_rhsMatrix_.size(),1);
// change entries for all entries if no atoms in shape function support
double totalVolume = _rhs_.sum();
double averageVolume = averaging_operation(totalVolume);
_scale_.resize(nNodes);
for (int i = 0; i < nNodes; i++) {
if ((abs(lhs(i,i)) > 0.))
_scale_(i) = 1.;
else
_scale_(i) = 0.;
}
lhs.row_scale(_scale_);
for (int i = 0; i < nNodes; i++) {
if (_scale_(i) < 0.5) {
lhs.set(i,i,1.);
_rhs_(i) = averageVolume;
}
}
lhs.compress();
// solve equation
LinearSolver solver(lhs, ATC::LinearSolver::ITERATIVE_SOLVE_SYMMETRIC, true);
solver.set_max_iterations(lhs.nRows());
solver.set_tolerance(tol_);
quantity_.reset(nNodes,1);
CLON_VEC tempQuantity(quantity_,CLONE_COL,0);
solver.solve(tempQuantity,_rhs_);
}
//--------------------------------------------------------
// averaging_operation
//--------------------------------------------------------
double NodalAtomVolume::averaging_operation(const double totalVolume) const
{
int nLocal[1] = {shapeFunction_->nRows()};
int nGlobal[1] = {0};
lammpsInterface_->int_allsum(nLocal,nGlobal,1);
return totalVolume/(double(nGlobal[0]));
}
//--------------------------------------------------------
// overloading operation to get number of rows
//--------------------------------------------------------
int NodalAtomVolume::nRows() const
{
return atc_->num_nodes();
}
//--------------------------------------------------------
// overloading operation to get number of columns
//--------------------------------------------------------
int NodalAtomVolume::nCols() const
{
return 1;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodalVolume
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// averaging_operation
//--------------------------------------------------------
double NodalVolume::averaging_operation(const double totalVolume) const
{
int nNodes = shapeFunction_->nCols();
return totalVolume/nNodes;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodalAtomVolumeElement
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
NodalAtomVolumeElement::NodalAtomVolumeElement(ATC_Method * atc,
SPAR_MAN * shapeFunction,
PerAtomQuantity<int> * atomElement) :
atc_(atc),
shapeFunction_(shapeFunction),
atomElement_(atomElement),
feEngine_(atc->fe_engine()),
tol_(1.e-10)
{
shapeFunction_->register_dependence(this);
if (!atomElement_) {
InterscaleManager & interscaleManager = atc_->interscale_manager();
atomElement_ = interscaleManager.per_atom_int_quantity("AtomElement");
}
atomElement_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void NodalAtomVolumeElement::reset_quantity() const
{
// Using analyses by G. Wagner and J. Templeton, weights ~ phi*M^{-1}*V
// where phi are the dimensionless shape/weighting functions,
// M is the "mass" matrix M_IJ,
// V is the vector of nodal and element volumes
//
//
// form atom-element shape functions and elemental volumes
const FE_Mesh * feMesh = feEngine_->fe_mesh();
int nElts = feMesh->num_elements();
int nNodes = shapeFunction_->nCols();
int nLocal = shapeFunction_->nRows();
// form "mass" matrix M_IJ (I,J = 0, 1, ..., nNodes+nElts-1)
int neSize = nNodes+nElts;
const INT_ARRAY & atomElement(atomElement_->quantity());
SPAR_MAT nodEltShpFcnMatrix(nLocal,neSize);
const SPAR_MAT & shapeFunction(shapeFunction_->quantity());
for(int a = 0; a < nLocal; a++) {
for(int I = 0; I < nNodes; I++) {
nodEltShpFcnMatrix.set(a,I,shapeFunction(a,I));
}
int thisCol = nNodes+atomElement(a,0);
nodEltShpFcnMatrix.set(a,thisCol,1);
}
SPAR_MAT neMassMatrix(neSize,neSize);
atc_->compute_consistent_md_mass_matrix(nodEltShpFcnMatrix,neMassMatrix);
// form vector of nodal and elemental volumes
_nodeVolumesMatrix_.resize(nNodes,nNodes);
feEngine_->compute_lumped_mass_matrix(_nodeVolumesMatrix_);
_nodeVolumes_.resize(nNodes);
_nodeVolumes_.copy(_nodeVolumesMatrix_.ptr(),_nodeVolumesMatrix_.size(),1);
DENS_VEC _nodeElementVolumes_(neSize);
for(int I = 0; I < nNodes; I++) {
_nodeElementVolumes_(I) = _nodeVolumes_(I);
}
double averageEltVolume = 0.0;
for(int E = 0; E < nElts; E++) {
double minx, maxx, miny, maxy, minz, maxz;
feMesh->element_coordinates(E,_nodalCoords_);
minx = _nodalCoords_(0,0); maxx = _nodalCoords_(0,0);
miny = _nodalCoords_(1,0); maxy = _nodalCoords_(1,0);
minz = _nodalCoords_(2,0); maxz = _nodalCoords_(2,0);
for (int j = 1; j < _nodalCoords_.nCols(); ++j) {
if (_nodalCoords_(0,j)<minx) minx = _nodalCoords_(0,j);
if (_nodalCoords_(0,j)>maxx) maxx = _nodalCoords_(0,j);
if (_nodalCoords_(1,j)<miny) miny = _nodalCoords_(1,j);
if (_nodalCoords_(1,j)>maxy) maxy = _nodalCoords_(1,j);
if (_nodalCoords_(2,j)<minz) minz = _nodalCoords_(2,j);
if (_nodalCoords_(2,j)>maxz) maxz = _nodalCoords_(2,j);
}
_nodeElementVolumes_(nNodes+E) = (maxx-minx)*(maxy-miny)*(maxz-minz);
averageEltVolume += (maxx-minx)*(maxy-miny)*(maxz-minz);
}
averageEltVolume /= nElts;
// correct entries of mass matrix if no atoms in shape function support
double totalNodalVolume = _nodeVolumes_.sum();
double averageNodalVolume = totalNodalVolume/nNodes;
_scale_.resize(neSize);
for (int i = 0; i < neSize; i++) {
if ((abs(neMassMatrix(i,i)) > 0.)) {
_scale_(i) = 1.;
} else {
printf("No atoms are in support of node/element %i\n",i);
_scale_(i) = 0.;
}
}
neMassMatrix.row_scale(_scale_);
for (int i = 0; i < neSize; i++) {
if (_scale_(i) < 0.5) {
neMassMatrix.set(i,i,1.);
if (i < nNodes) {
_nodeElementVolumes_(i) = averageNodalVolume;
} else {
_nodeElementVolumes_(i) = averageEltVolume;
}
}
}
neMassMatrix.compress();
// solve equation
LinearSolver solver(neMassMatrix, ATC::LinearSolver::ITERATIVE_SOLVE_SYMMETRIC, true);
solver.set_max_iterations(neMassMatrix.nRows());
double myTol = 1.e-10;
solver.set_tolerance(myTol);
quantity_.resize(neSize,0);
CLON_VEC tempQuantity(quantity_,CLONE_COL,0);
solver.solve(tempQuantity,_nodeElementVolumes_);
}
//--------------------------------------------------------
// overloading operation to get number of rows
//--------------------------------------------------------
int NodalAtomVolumeElement::nRows() const
{
return atc_->num_nodes();
}
//--------------------------------------------------------
// overloading operation to get number of columns
//--------------------------------------------------------
int NodalAtomVolumeElement::nCols() const
{
return 1;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class AtomTypeElement
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
AtomTypeElement::AtomTypeElement(ATC_Coupling * atc,
PerAtomQuantity<int> * atomElement) :
atomElement_(atomElement),
nElts_((atc->fe_engine())->num_elements())
{
if (!atomElement_) {
atomElement_ = (atc->interscale_manager()).per_atom_int_quantity("AtomElement");
}
atomElement_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void AtomTypeElement::reset_quantity() const
{
// determine which elements contain internal atoms
quantity_.resize(nElts_,1);
_quantityLocal_.resize(nElts_,1);
_quantityLocal_ = 0;
const INT_ARRAY & atomElement(atomElement_->quantity());
for (int i = 0; i < atomElement_->nRows(); ++i) {
_quantityLocal_(atomElement(i,0),0) = 1;
}
// swap contributions
lammpsInterface_->logical_or(_quantityLocal_.ptr(),
quantity_.ptr(),nElts_);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElementMask
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ElementMask::ElementMask(ATC_Coupling * atc,
MatrixDependencyManager<DenseMatrix, int> * hasInternal,
MatrixDependencyManager<DenseMatrix, int> * hasGhost) :
hasInternal_(hasInternal),
hasGhost_(hasGhost),
feEngine_(atc->fe_engine())
{
if (!hasInternal_) {
hasInternal_ = (atc->interscale_manager()).dense_matrix_int("ElementHasInternal");
}
if (!hasGhost_) {
hasGhost_ = (atc->interscale_manager()).dense_matrix_int("ElementHasGhost");
}
hasInternal_->register_dependence(this);
if (hasGhost_) hasGhost_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void ElementMask::reset_quantity() const
{
const INT_ARRAY & hasInternal(hasInternal_->quantity());
int nElts = hasInternal.size();
quantity_.resize(nElts,1);
if (hasGhost_) {
const INT_ARRAY & hasGhost(hasGhost_->quantity());
for (int i = 0; i < nElts; ++i) {
quantity_(i,0) = !hasInternal(i,0) || hasGhost(i,0);
}
}
else {
for (int i = 0; i < nElts; ++i) {
quantity_(i,0) = !hasInternal(i,0);
}
}
const set<int> & nullElements = feEngine_->null_elements();
set<int>::const_iterator iset;
for (iset = nullElements.begin(); iset != nullElements.end(); iset++) {
int ielem = *iset;
quantity_(ielem,0) = false;
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class AtomElementMask
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
AtomElementMask::AtomElementMask(ATC_Coupling * atc,
MatrixDependencyManager<DenseMatrix, int> * hasAtoms) :
hasAtoms_(hasAtoms),
feEngine_(atc->fe_engine())
{
if (!hasAtoms_) {
hasAtoms_ = (atc->interscale_manager()).dense_matrix_int("ElementHasInternal");
}
if (!hasAtoms_) {
throw ATC_Error("AtomElementMask::AtomElementMask - no element has atoms transfer provided");
}
hasAtoms_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void AtomElementMask::reset_quantity() const
{
const INT_ARRAY & hasAtoms(hasAtoms_->quantity());
int nElts = hasAtoms.size();
quantity_.resize(nElts,1);
for (int i = 0; i < nElts; ++i) {
quantity_(i,0) = hasAtoms(i,0);
}
// this seems to cause problems because many materials end up being null
const set<int> & nullElements = feEngine_->null_elements();
set<int>::const_iterator iset;
for (iset = nullElements.begin(); iset != nullElements.end(); iset++) {
int ielem = *iset;
quantity_(ielem,0) = false;
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ElementMaskNodeSet
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ElementMaskNodeSet::ElementMaskNodeSet(ATC_Coupling * atc,
SetDependencyManager<int> * nodeSet) :
nodeSet_(nodeSet),
feMesh_((atc->fe_engine())->fe_mesh())
{
nodeSet_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void ElementMaskNodeSet::reset_quantity() const
{
quantity_.resize(feMesh_->num_elements(),1);
quantity_ = false;
// get the maximal element set corresponding to those nodes
set<int> elementSet;
feMesh_->nodeset_to_maximal_elementset(nodeSet_->quantity(),elementSet);
set<int>::const_iterator iset;
for (iset = elementSet.begin(); iset != elementSet.end(); iset++) {
quantity_(*iset,0) = true;
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodalGeometryType
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
NodalGeometryType::NodalGeometryType(ATC_Coupling * atc,
MatrixDependencyManager<DenseMatrix, int> * hasInternal,
MatrixDependencyManager<DenseMatrix, int> * hasGhost) :
hasInternal_(hasInternal),
hasGhost_(hasGhost),
feEngine_(atc->fe_engine()),
nNodes_(atc->num_nodes()),
nElts_((atc->fe_engine())->num_elements())
{
if (!hasInternal_) {
hasInternal_ = (atc->interscale_manager()).dense_matrix_int("ElementHasInternal");
}
if (!hasGhost_) {
hasGhost_ = (atc->interscale_manager()).dense_matrix_int("ElementHasGhost");
}
hasInternal_->register_dependence(this);
if (hasGhost_) hasGhost_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void NodalGeometryType::reset_quantity() const
{
const INT_ARRAY & hasInternal(hasInternal_->quantity());
_nodesInternal_.resize(nNodes_);
_nodesInternal_ = 0;
_nodesGhost_.reset(nNodes_);
_nodesGhost_ = 0;
Array<int> nodes;
vector<int> myElems = feEngine_->fe_mesh()->owned_elts();
if (hasGhost_) {
const INT_ARRAY & hasGhost(hasGhost_->quantity()) ;
// iterate through all elements owned by this processor
for (vector<int>::iterator elemsIter = myElems.begin();
elemsIter != myElems.end();
++elemsIter)
{
int ielem = *elemsIter;
if (hasInternal(ielem,0) || hasGhost(ielem,0)) {
feEngine_->element_connectivity(ielem,nodes);
for (int j = 0; j < nodes.size(); j++) {
if (hasInternal(ielem,0)) {
_nodesInternal_(nodes(j)) = 1;
}
if (hasGhost(ielem,0)) {
_nodesGhost_(nodes(j)) = 1;
}
}
}
}
// sum up partial result arrays
lammpsInterface_->logical_or(MPI_IN_PLACE, _nodesInternal_.ptr(), _nodesInternal_.size());
lammpsInterface_->logical_or(MPI_IN_PLACE, _nodesGhost_.ptr(), _nodesGhost_.size());
}
else {
// iterate through all elements owned by this processor
for (vector<int>::iterator elemsIter = myElems.begin();
elemsIter != myElems.end();
++elemsIter)
{
int ielem = *elemsIter;
if (hasInternal(ielem,0)) {
feEngine_->element_connectivity(ielem,nodes);
for (int j = 0; j < nodes.size(); j++) {
_nodesInternal_(nodes(j)) = 1;
}
}
}
// sum up partial result arrays
lammpsInterface_->logical_or(MPI_IN_PLACE, _nodesInternal_.ptr(), _nodesInternal_.size());
}
quantity_.resize(nNodes_,1);
for (int i = 0; i < nNodes_; i++) {
if (_nodesInternal_(i) && _nodesGhost_(i)) {
quantity_(i,0) = BOUNDARY;
}
else if (_nodesInternal_(i)) {
quantity_(i,0) = MD_ONLY;
}
else {
quantity_(i,0) = FE_ONLY;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodalGeometryTypeElementSet
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
NodalGeometryTypeElementSet::NodalGeometryTypeElementSet(ATC_Coupling * atc,
MatrixDependencyManager<DenseMatrix, int> * hasInternal) :
hasInternal_(hasInternal),
feEngine_(atc->fe_engine()),
nNodes_(atc->num_nodes()),
nElts_((atc->fe_engine())->num_elements())
{
if (!hasInternal_) {
hasInternal_ = (atc->interscale_manager()).dense_matrix_int("ElementHasInternal");
}
if (!hasInternal_) {
throw ATC_Error("NodalGeometryTypeElementSet: No ElementHasInternal object provided or exists");
}
hasInternal_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void NodalGeometryTypeElementSet::reset_quantity() const
{
const INT_ARRAY & hasInternal(hasInternal_->quantity());
_nodesInternal_.resize(nNodes_);
_nodesInternal_ = 0;
_nodesGhost_.reset(nNodes_);
_nodesGhost_ = 0;
Array<int> nodes;
vector<int> myElems = feEngine_->fe_mesh()->owned_elts();
// iterate through all elements owned by this processor
for (vector<int>::iterator elemsIter = myElems.begin();
elemsIter != myElems.end();
++elemsIter)
{
int ielem = *elemsIter;
if (hasInternal(ielem,0)) {
feEngine_->element_connectivity(ielem,nodes);
for (int j = 0; j < nodes.size(); j++) {
_nodesInternal_(nodes(j)) = 1;
}
}
else {
feEngine_->element_connectivity(ielem,nodes);
for (int j = 0; j < nodes.size(); j++) {
_nodesGhost_(nodes(j)) = 1;
}
}
}
// sum up partial result arrays
lammpsInterface_->logical_or(MPI_IN_PLACE, _nodesInternal_.ptr(), _nodesInternal_.size());
lammpsInterface_->logical_or(MPI_IN_PLACE, _nodesGhost_.ptr(), _nodesGhost_.size());
quantity_.resize(nNodes_,1);
for (int i = 0; i < nNodes_; i++) {
if (_nodesInternal_(i) && _nodesGhost_(i)) {
quantity_(i,0) = BOUNDARY;
}
else if (_nodesInternal_(i)) {
quantity_(i,0) = MD_ONLY;
}
else {
quantity_(i,0) = FE_ONLY;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NodeToSubset
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
NodeToSubset::NodeToSubset(ATC_Method * atc,
SetDependencyManager<int> * subsetNodes) :
LargeToSmallMap(),
atc_(atc),
subsetNodes_(subsetNodes)
{
subsetNodes_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void NodeToSubset::reset_quantity() const
{
int nNodes = atc_->num_nodes();
const set<int> & subsetNodes(subsetNodes_->quantity());
quantity_.resize(nNodes,1);
size_ = 0;
for (int i = 0; i < nNodes; i++) {
if (subsetNodes.find(i) != subsetNodes.end()) {
quantity_(i,0) = size_;
size_++;
}
else {
quantity_(i,0) = -1;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class SubsetToNode
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
SubsetToNode::SubsetToNode(NodeToSubset * nodeToSubset) :
nodeToSubset_(nodeToSubset)
{
nodeToSubset_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void SubsetToNode::reset_quantity() const
{
const INT_ARRAY & nodeToSubset(nodeToSubset_->quantity());
int nNodes = nodeToSubset.nRows();
int count = 0;
quantity_.resize(nodeToSubset_->size(),1);
for (int i = 0; i < nNodes; i++) {
if (nodeToSubset(i,0) > -1) {
quantity_(count,0) = i;
count++;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class ReducedSparseMatrix
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ReducedSparseMatrix::ReducedSparseMatrix(ATC_Method * atc,
SPAR_MAN * source,
LargeToSmallAtomMap * map) :
SparseMatrixTransfer<double>(),
source_(source),
map_(map)
{
source_->register_dependence(this);
map_->register_dependence(this);
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
ReducedSparseMatrix::~ReducedSparseMatrix()
{
source_->remove_dependence(this);
map_->remove_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void ReducedSparseMatrix::reset_quantity() const
{
const SPAR_MAT & source(source_->quantity());
const INT_ARRAY & map(map_->quantity());
quantity_.reset(source.nRows(),source.nCols());
for (int i = 0; i < source.nRows(); i++) {
int idx = map(i,0);
if (idx > -1) {
source.row(i,_row_,_index_);
for (int j = 0; j < _row_.size(); j++) {
quantity_.set(i,_index_(j),_row_(j));
}
}
}
quantity_.compress();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class RowMappedSparseMatrix
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void RowMappedSparseMatrix::reset_quantity() const
{
const SPAR_MAT & source(source_->quantity());
const INT_ARRAY & map(map_->quantity());
quantity_.reset(map_->size(),source.nCols());
for (int i = 0; i < source.nRows(); i++) {
int idx = map(i,0);
if (idx > -1) {
source.row(i,_row_,_index_);
for (int j = 0; j < _row_.size(); j++) {
quantity_.set(idx,_index_(j),_row_(j));
}
}
}
quantity_.compress();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class RowMappedSparseMatrixVector
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
RowMappedSparseMatrixVector::RowMappedSparseMatrixVector(ATC_Method * atc,
VectorDependencyManager<SPAR_MAT * > * source,
LargeToSmallAtomMap * map) :
VectorTransfer<SPAR_MAT * >(),
source_(source),
map_(map)
{
source_->register_dependence(this);
map_->register_dependence(this);
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
RowMappedSparseMatrixVector::~RowMappedSparseMatrixVector()
{
source_->remove_dependence(this);
map_->remove_dependence(this);
for (unsigned i = 0; i < quantity_.size(); ++i) {
if (quantity_[i]) delete quantity_[i];
}
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void RowMappedSparseMatrixVector::reset_quantity() const
{
const vector<SPAR_MAT * > & source(source_->quantity());
const INT_ARRAY & map(map_->quantity());
for (unsigned i = 0; i < quantity_.size(); ++i) {
if (quantity_[i]) delete quantity_[i];
}
quantity_.resize(source.size(),NULL);
for (unsigned i = 0; i < source.size(); i++) {
quantity_[i] = new SPAR_MAT(map_->size(),source[i]->nCols());
}
for (unsigned i = 0; i < source.size(); i++) {
for (int j = 0; j < source[i]->nRows(); j++) {
int idx = map(j,0);
if (idx > -1) {
source[i]->row(j,_row_,_index_);
for (int k = 0; k < _row_.size(); k++) {
quantity_[i]->set(idx,_index_(k),_row_(k));
}
}
}
}
for (unsigned i = 0; i < source.size(); i++) {
quantity_[i]->compress();
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class MappedDiagonalMatrix
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
MappedDiagonalMatrix::MappedDiagonalMatrix(ATC_Method * atc,
DIAG_MAN * source,
LargeToSmallAtomMap * map) :
DiagonalMatrixTransfer<double>(),
source_(source),
map_(map)
{
source_->register_dependence(this);
map_->register_dependence(this);
}
//--------------------------------------------------------
// Destructor
//--------------------------------------------------------
MappedDiagonalMatrix::~MappedDiagonalMatrix()
{
source_->remove_dependence(this);
map_->remove_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void MappedDiagonalMatrix::reset_quantity() const
{
const DIAG_MAT & source(source_->quantity());
const INT_ARRAY & map(map_->quantity());
quantity_.resize(map_->size(),map_->size());
for (int i = 0; i < source.nRows(); i++) {
int idx = map(i,0);
if (idx > -1) {
quantity_(idx,idx) = source(i,i);
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class MappedQuantity
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
MappedQuantity::MappedQuantity(ATC_Method * atc,
DENS_MAN * source,
LargeToSmallMap * map) :
DenseMatrixTransfer<double>(),
source_(source),
map_(map)
{
source_->register_dependence(this);
map_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void MappedQuantity::reset_quantity() const
{
const DENS_MAT & source(source_->quantity());
const INT_ARRAY & map(map_->quantity());
quantity_.resize(map_->size(),source.nCols());
for (int i = 0; i < source.nRows(); i++) {
int idx = map(i,0);
if (idx > -1) {
for (int j = 0; j < source.nCols(); j++) {
quantity_(idx,j) = source(i,j);
}
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class RegulatedNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
RegulatedNodes::RegulatedNodes(ATC_Coupling * atc,
FieldName fieldName,
MatrixDependencyManager<DenseMatrix, int> * nodalGeometryType) :
SetTransfer<int>(),
nodalGeometryType_(nodalGeometryType),
atc_(atc),
feEngine_(atc->fe_engine()),
prescribedDataManager_(atc->prescribed_data_manager())
{
if (!nodalGeometryType_) {
nodalGeometryType_ = (atc_->interscale_manager()).dense_matrix_int("NodalGeometryType");
}
if (nodalGeometryType_) {
nodalGeometryType_->register_dependence(this);
}
else {
throw ATC_Error("TransferLibrary::RegulatedNodes - No Nodal Geometry Type provided");
}
const map<FieldName,int> & atcFieldSizes(atc_->field_sizes());
if (fieldName == NUM_TOTAL_FIELDS) {
fieldSizes_ = atcFieldSizes;
}
else {
map<FieldName,int>::const_iterator fs_iter = atcFieldSizes.find(fieldName);
fieldSizes_.insert(pair<FieldName,int>(fieldName,fs_iter->second));
}
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void RegulatedNodes::reset_quantity() const
{
const INT_ARRAY & nodeType(nodalGeometryType_->quantity());
quantity_.clear();
for (int i = 0; i < nodeType.size(); ++i) {
if (nodeType(i,0) != FE_ONLY) {
quantity_.insert(i);
}
}
}
//--------------------------------------------------------
// insert_boundary_nodes
//--------------------------------------------------------
void RegulatedNodes::insert_boundary_nodes() const
{
const INT_ARRAY & nodeType(nodalGeometryType_->quantity());
for (int i = 0; i < nodeType.size(); ++i) {
if (nodeType(i,0) == BOUNDARY) {
quantity_.insert(i);
}
}
}
//--------------------------------------------------------
// insert_boundary_faces
//--------------------------------------------------------
void RegulatedNodes::insert_boundary_faces() const
{
const set<string> & boundaryFaceNames(atc_->boundary_face_names());
set<string>::const_iterator iter;
set<int>::const_iterator nodeIter;
for (iter = boundaryFaceNames.begin(); iter != boundaryFaceNames.end(); iter++) {
set<int> nodeSet;
feEngine_->fe_mesh()->faceset_to_nodeset(*iter,nodeSet);
for (nodeIter = nodeSet.begin(); nodeIter != nodeSet.end(); nodeIter++) {
quantity_.insert(*nodeIter);
}
}
}
//--------------------------------------------------------
// insert_fixed_nodes
//--------------------------------------------------------
void RegulatedNodes::insert_fixed_nodes() const
{
const INT_ARRAY & nodeType(nodalGeometryType_->quantity());
map<FieldName,int>::const_iterator fs_iter;
for (int i = 0; i < nodeType.size(); ++i) {
bool isFixed = false;
for (fs_iter = fieldSizes_.begin(); fs_iter != fieldSizes_.end(); fs_iter++) {
for (int j = 0; j < fs_iter->second; j++) {
isFixed = prescribedDataManager_->is_fixed(i,fs_iter->first,j);
if (isFixed) break;
}
}
if (isFixed && ((nodeType(i,0)==MD_ONLY) || (nodeType(i,0)==BOUNDARY))) {
quantity_.insert(i);
}
}
}
//--------------------------------------------------------
// insert_face_fluxes
//--------------------------------------------------------
void RegulatedNodes::insert_face_fluxes() const
{
const INT_ARRAY & nodeType(nodalGeometryType_->quantity());
set<int>::const_iterator inode;
map<FieldName,int>::const_iterator fs_iter;
for (fs_iter = fieldSizes_.begin(); fs_iter != fieldSizes_.end(); fs_iter++) {
for (int j = 0; j < fs_iter->second; j++) {
set<int> faceFluxNodes = prescribedDataManager_->flux_face_nodes(fs_iter->first,j);
for (inode = faceFluxNodes.begin(); inode != faceFluxNodes.end(); inode++) {
if (((nodeType(*inode,0)==MD_ONLY) || (nodeType(*inode,0)==BOUNDARY))) {
quantity_.insert(*inode);
}
}
}
}
}
//--------------------------------------------------------
// insert_element_fluxes
//--------------------------------------------------------
void RegulatedNodes::insert_element_fluxes() const
{
const INT_ARRAY & nodeType(nodalGeometryType_->quantity());
set<int>::const_iterator inode;
map<FieldName,int>::const_iterator fs_iter;
for (fs_iter = fieldSizes_.begin(); fs_iter != fieldSizes_.end(); fs_iter++) {
for (int j = 0; j < fs_iter->second; j++) {
set<int> elementFluxNodes = prescribedDataManager_->flux_element_nodes(fs_iter->first,j);
for (inode = elementFluxNodes.begin(); inode != elementFluxNodes.end(); inode++) {
if (((nodeType(*inode,0)==MD_ONLY) || (nodeType(*inode,0)==BOUNDARY))) {
quantity_.insert(*inode);
}
}
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class BoundaryNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void BoundaryNodes::reset_quantity() const
{
quantity_.clear();
// a) they are a boundary node
RegulatedNodes::insert_boundary_nodes();
// b) they are in a specified boundary faceset
RegulatedNodes::insert_boundary_faces();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class FluxNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void FluxNodes::reset_quantity() const
{
quantity_.clear();
// a) they have a fixed face flux
RegulatedNodes::insert_face_fluxes();
// b) they have a fixed element flux
RegulatedNodes::insert_element_fluxes();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class FluxBoundaryNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void FluxBoundaryNodes::reset_quantity() const
{
FluxNodes::reset_quantity();
// a) they are a boundary node
RegulatedNodes::insert_boundary_nodes();
// b) they are in a specified boundary faceset
RegulatedNodes::insert_boundary_faces();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class AllRegulatedNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void AllRegulatedNodes::reset_quantity() const
{
FluxBoundaryNodes::reset_quantity();
// a) they are a fixed node
RegulatedNodes::insert_fixed_nodes();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class FixedNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void FixedNodes::reset_quantity() const
{
quantity_.clear();
// a) they are a fixed node
RegulatedNodes::insert_fixed_nodes();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class FixedBoundaryNodes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void FixedBoundaryNodes::reset_quantity() const
{
FixedNodes::reset_quantity();
// a) they are a boundary node
RegulatedNodes::insert_boundary_nodes();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class DenseMatrixQuotient
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
DenseMatrixQuotient::DenseMatrixQuotient(DENS_MAN* matrixNumerator,
DENS_MAN* matrixDenominator):
matrixNumerator_(matrixNumerator),
matrixDenominator_(matrixDenominator)
{
matrixNumerator_->register_dependence(this);
matrixDenominator_->register_dependence(this);
}
//--------------------------------------------------------
// Reset_quantity
//--------------------------------------------------------
void DenseMatrixQuotient::reset_quantity() const
{
quantity_ = matrixNumerator_->quantity();
quantity_.divide_zero_safe(matrixDenominator_->quantity());
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class DenseMatrixSum
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
DenseMatrixSum::DenseMatrixSum(DENS_MAN* matrixOne,
DENS_MAN* matrixTwo):
matrixOne_(matrixOne), matrixTwo_(matrixTwo)
{
matrixOne_->register_dependence(this);
matrixTwo_->register_dependence(this);
}
//--------------------------------------------------------
// Reset_quantity
//--------------------------------------------------------
void DenseMatrixSum::reset_quantity() const
{
quantity_ = matrixOne_->quantity();
quantity_ += (matrixTwo_->quantity());
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class DenseMatrixDelta
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
DenseMatrixDelta::DenseMatrixDelta(DENS_MAN* matrix,
DENS_MAT* reference):
matrix_(matrix), reference_(reference)
{
matrix_->register_dependence(this);
}
//--------------------------------------------------------
// Reset_quantity
//--------------------------------------------------------
void DenseMatrixDelta::reset_quantity() const
{
quantity_ = matrix_->quantity();
quantity_ -= *reference_;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class PointToElementMap
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
PointToElementMap::PointToElementMap(ATC_Method * atc,
MatrixDependencyManager<DenseMatrix, double> * pointPositions) :
DenseMatrixTransfer<int>(),
pointPositions_(pointPositions),
feMesh_((atc->fe_engine())->fe_mesh())
{
pointPositions_->register_dependence(this);
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
PointToElementMap::~PointToElementMap()
{
pointPositions_->remove_dependence(this);
}
//--------------------------------------------------------
// reset
//--------------------------------------------------------
void PointToElementMap::reset_quantity() const
{
const DENS_MAT & position(pointPositions_->quantity());
int nsd = position.nCols();
int nRows = position.nRows();
quantity_.resize(nRows,nsd);
DENS_VEC coords(nsd);
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nsd; j++) {
coords(j) = position(i,j);
}
quantity_(i,0) = feMesh_->map_to_element(coords);
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class Interpolant
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// constructor
//--------------------------------------------------------
Interpolant::Interpolant(ATC_Method * atc,
MatrixDependencyManager<DenseMatrix, int>* pointToElementMap,
DENS_MAN* pointPositions) :
SparseMatrixTransfer<double>(),
pointToElementMap_(pointToElementMap),
pointPositions_(pointPositions),
feEngine_(atc->fe_engine())
{
pointToElementMap_->register_dependence(this);
pointPositions_->register_dependence(this);
}
//--------------------------------------------------------
// reset
//--------------------------------------------------------
void Interpolant::reset_quantity() const
{
const DENS_MAT & positions(pointPositions_->quantity());
const INT_ARRAY & elements(pointToElementMap_->quantity());
if (positions.nRows() > 0) {
feEngine_->evaluate_shape_functions(positions,
elements,
this->quantity_);
}
else {
quantity_.resize(0,feEngine_->num_nodes());
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class InterpolantGradient
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// constructor
//--------------------------------------------------------
InterpolantGradient::InterpolantGradient(ATC_Method * atc,
MatrixDependencyManager<DenseMatrix, int>* pointToElementMap,
DENS_MAN* pointPositions) :
VectorTransfer<SPAR_MAT * >(),
pointToElementMap_(pointToElementMap),
pointPositions_(pointPositions),
feEngine_(atc->fe_engine())
{
pointToElementMap_->register_dependence(this);
pointPositions_->register_dependence(this);
quantity_.resize(atc->nsd(),NULL);
for (int i = 0; i < atc->nsd(); ++i) {
quantity_[i] = new SPAR_MAT();
}
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
InterpolantGradient::~InterpolantGradient() {
pointToElementMap_->remove_dependence(this);
pointPositions_->remove_dependence(this);
for (unsigned i = 0; i < quantity_.size(); ++i) {
if (quantity_[i]) delete quantity_[i];
}
}
//--------------------------------------------------------
// reset_quantity()
//--------------------------------------------------------
void InterpolantGradient::reset_quantity() const
{
const DENS_MAT & positions(pointPositions_->quantity());
const INT_ARRAY & elements(pointToElementMap_->quantity());
if (positions.nRows() > 0) {
feEngine_->evaluate_shape_function_derivatives(positions,
elements,
this->quantity_);
}
else {
for (unsigned i = 0; i < quantity_.size(); ++i) {
(this->quantity_)[i]->resize(0,feEngine_->num_nodes());
}
}
}
//--------------------------------------------------------
// Class PerAtomShapeFunctionGradient
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// constructor
//--------------------------------------------------------
PerAtomShapeFunctionGradient::PerAtomShapeFunctionGradient(ATC_Method * atc,
MatrixDependencyManager<DenseMatrix, int>* atomToElementMap,
DENS_MAN* atomPositions,
const string & tag,
AtomType atomType) :
VectorTransfer<SPAR_MAT * >(),
atomToElementMap_(atomToElementMap),
atomPositions_(atomPositions),
feEngine_(atc->fe_engine())
{
InterscaleManager & interscaleManager(atc->interscale_manager());
if (!atomToElementMap_) {
atomToElementMap_ = interscaleManager.per_atom_int_quantity("AtomElement");
}
if (!atomPositions_) {
atomPositions_ = interscaleManager.per_atom_quantity("AtomicCoarseGrainingPositions");
}
atomToElementMap_->register_dependence(this);
atomPositions_->register_dependence(this);
// storage container
matrices_.resize(atc->nsd(),NULL);
for (int i = 0; i < atc->nsd(); ++i) {
matrices_[i] = new AtcAtomSparseMatrix<double>(atc,feEngine_->num_nodes(),
feEngine_->num_nodes_per_element(),
atomType);
stringstream myint;
myint << i;
interscaleManager.add_per_atom_sparse_matrix(matrices_[i],
tag+myint.str());
matrices_[i]->register_dependence(this);
}
quantity_.resize(atc->nsd(),NULL);
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
PerAtomShapeFunctionGradient::~PerAtomShapeFunctionGradient() {
atomToElementMap_->remove_dependence(this);
atomPositions_->remove_dependence(this);
for (unsigned i = 0; i < matrices_.size(); ++i) {
matrices_[i]->remove_dependence(this);
}
}
//--------------------------------------------------------
// reset_quantity()
//--------------------------------------------------------
void PerAtomShapeFunctionGradient::reset_quantity() const
{
const DENS_MAT & positions(atomPositions_->quantity());
const INT_ARRAY & elements(atomToElementMap_->quantity());
for (unsigned i = 0; i < quantity_.size(); ++i) {
(this->quantity_)[i] = & matrices_[i]->set_quantity();
}
if (positions.nRows() > 0) {
feEngine_->evaluate_shape_function_derivatives(positions,
elements,
this->quantity_);
}
else {
for (unsigned i = 0; i < quantity_.size(); ++i) {
(this->quantity_)[i]->resize(0,feEngine_->num_nodes());
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class InterpolantSmallMolecule
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// constructor
//--------------------------------------------------------
InterpolantSmallMolecule::InterpolantSmallMolecule(ATC_Method * atc,
MatrixDependencyManager<DenseMatrix, int>* moleculeToElementMap,
DENS_MAN* moleculePositions,
MoleculeSet * moleculeSet) :
Interpolant(atc,moleculeToElementMap,moleculePositions),
moleculeSet_(moleculeSet)
{
moleculeSet_->register_dependence(this);
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
InterpolantSmallMolecule::~InterpolantSmallMolecule()
{
moleculeSet_->remove_dependence(this);
}
//--------------------------------------------------------
// reset
//--------------------------------------------------------
void InterpolantSmallMolecule::reset_quantity() const
{
Interpolant::reset_quantity();
// scale rows by fraction of molecules on this proc
_fractions_.resize((this->quantity_).nRows());
for (int i = 0; i < moleculeSet_->local_molecule_count(); i++)
_fractions_(i) = moleculeSet_->local_fraction(i);
(this->quantity_).row_scale(_fractions_);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyKernelAccumulation
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyKernelAccumulation::OnTheFlyKernelAccumulation(ATC_Method * atc,
PerAtomQuantity<double> * source,
KernelFunction* kernelFunction,
DENS_MAN* atomCoarseGrainingPositions):
atc_(atc),
source_(source),
kernelFunction_(kernelFunction),
atomCoarseGrainingPositions_(atomCoarseGrainingPositions),
feMesh_((atc_->fe_engine())->fe_mesh())
{
source_->register_dependence(this);
atomCoarseGrainingPositions_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyKernelAccumulation::reset_quantity() const
{
const DENS_MAT & positions(atomCoarseGrainingPositions_->quantity());
const DENS_MAT & source(source_->quantity());
int nNodes = feMesh_->num_nodes_unique();
quantity_.resize(nNodes,source.nCols());
_quantityLocal_.reset(nNodes,source.nCols());
if (source.nRows()>0) {
DENS_VEC xI(positions.nCols()),xa(positions.nCols()),xaI(positions.nCols());
double val;
for (int i = 0; i < nNodes; i++) {
xI = feMesh_->nodal_coordinates(i);
for (int j = 0; j < positions.nRows(); j++) {
for (int k = 0; k < positions.nCols(); ++k) {
xa(k) = positions(j,k);
}
xaI = xa - xI;
atc_->lammps_interface()->periodicity_correction(xaI.ptr());
val = kernelFunction_->value(xaI);
if (val > 0) {
for (int k=0; k < source.nCols(); k++) {
_quantityLocal_(i,k) += val*source(j,k);
}
}
}
}
}
// accumulate across processors
int count = quantity_.nRows()*quantity_.nCols();
lammpsInterface_->allsum(_quantityLocal_.ptr(),quantity_.ptr(),count);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyKernelAccumulationNormalized
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyKernelAccumulationNormalized::OnTheFlyKernelAccumulationNormalized(ATC_Method * atc,
PerAtomQuantity<double> * source,
KernelFunction* kernelFunction,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN * weights):
OnTheFlyKernelAccumulation(atc,source,kernelFunction,atomCoarseGrainingPositions),
weights_(weights)
{
weights_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyKernelAccumulationNormalized::reset_quantity() const
{
OnTheFlyKernelAccumulation::reset_quantity();
quantity_ *= weights_->quantity();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyKernelAccumulationNormalizedReferenced
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyKernelAccumulationNormalizedReferenced::OnTheFlyKernelAccumulationNormalizedReferenced(ATC_Method * atc,
PerAtomQuantity<double> * source,
KernelFunction* kernelFunction,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN* weights,
DENS_MAN * reference):
OnTheFlyKernelAccumulationNormalized(atc,source,kernelFunction,atomCoarseGrainingPositions,weights),
reference_(reference)
{
reference_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyKernelAccumulationNormalizedReferenced::reset_quantity() const
{
OnTheFlyKernelAccumulationNormalized::reset_quantity();
quantity_ -= reference_->quantity();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyKernelAccumulationNormalizedScaled
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyKernelAccumulationNormalizedScaled::OnTheFlyKernelAccumulationNormalizedScaled(ATC_Method * atc,
PerAtomQuantity<double> * source,
KernelFunction* kernelFunction,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN* weights,
const double scale):
OnTheFlyKernelAccumulationNormalized(atc,source,kernelFunction,atomCoarseGrainingPositions,weights),
scale_(scale)
{
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyKernelAccumulationNormalizedScaled::reset_quantity() const
{
OnTheFlyKernelAccumulationNormalized::reset_quantity();
quantity_ *= scale_;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class AccumulantWeights
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
AccumulantWeights::AccumulantWeights(SPAR_MAN* accumulant):
DiagonalMatrixTransfer<double>(),
accumulant_(accumulant)
{
accumulant_->register_dependence(this);
}
//--------------------------------------------------------
// Reset_quantity
//--------------------------------------------------------
void AccumulantWeights::reset_quantity() const
{
const SPAR_MAT accumulant(accumulant_->quantity());
int nNodes = accumulant.nCols();
// get summation of atoms per node
_localWeights_.reset(nNodes); _weights_.resize(nNodes);
if (accumulant.nRows()>0) {
_localWeights_ = (accumulant_->quantity()).col_sum();
}
lammpsInterface_->allsum(_localWeights_.ptr(),_weights_.ptr(),nNodes);
// assign weights
quantity_.resize(nNodes,nNodes);
for (int i = 0; i < nNodes; i++) {
if (_weights_(i) > 0.) {
quantity_(i,i) = 1./_weights_(i);
}
else {
quantity_(i,i) = 0.;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyKernelWeights
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyKernelWeights::OnTheFlyKernelWeights(DENS_MAN* weights):
DiagonalMatrixTransfer<double>(),
weights_(weights)
{
weights_->register_dependence(this);
}
//--------------------------------------------------------
// Reset_quantity
//--------------------------------------------------------
void OnTheFlyKernelWeights::reset_quantity() const
{
const DENS_MAT & weights(weights_->quantity());
int nNodes = weights.nRows();
// assign weights
quantity_.resize(nNodes,nNodes);
for (int i = 0; i < nNodes; i++) {
if (weights(i,0) > 0.) {
quantity_(i,i) = 1./weights(i,0);
}
else {
quantity_(i,i) = 0.;
}
}
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class KernelInverseVolumes
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
KernelInverseVolumes::KernelInverseVolumes(ATC_Method * atc,
KernelFunction* kernelFunction):
kernelFunction_(kernelFunction),
feMesh_((atc->fe_engine())->fe_mesh())
{
// do nothing
}
//--------------------------------------------------------
// multiplication by transpose
//--------------------------------------------------------
void KernelInverseVolumes::reset_quantity() const
{
int nNodes = feMesh_->num_nodes_unique();
quantity_.resize(nNodes,nNodes);
quantity_ = kernelFunction_->inv_vol();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyMeshAccumulation
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyMeshAccumulation::OnTheFlyMeshAccumulation(ATC_Method * atc,
PerAtomQuantity<double> * source,
DENS_MAN* atomCoarseGrainingPositions):
atc_(atc),
source_(source),
atomCoarseGrainingPositions_(atomCoarseGrainingPositions),
feMesh_((atc_->fe_engine())->fe_mesh())
{
source_->register_dependence(this);
atomCoarseGrainingPositions_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyMeshAccumulation::reset_quantity() const
{
const DENS_MAT & positions(atomCoarseGrainingPositions_->quantity());
const DENS_MAT & source(source_->quantity());
int nNodes = feMesh_->num_nodes_unique();
int nodesPerElement = feMesh_->num_nodes_per_element();
Array<int> node_list(nodesPerElement);
DENS_VEC shp(nodesPerElement);
quantity_.resize(nNodes,source.nCols());
_quantityLocal_.reset(nNodes,source.nCols());
DENS_VEC xj(atc_->nsd());
if (source.nRows()>0) {
for (int j = 0; j < source.nRows(); j++) {
for (int k = 0; k < atc_->nsd(); k++) {
xj(k) = positions(j,k);
}
feMesh_->shape_functions(xj,shp,node_list);
for (int I = 0; I < nodesPerElement; I++) {
int inode = node_list(I);
for (int k = 0; k < source.nCols(); k++) {
//quantity_(inode,k) += shp(I)*source(j,k);
_quantityLocal_(inode,k) += shp(I)*source(j,k);
}
}
}
}
// accumulate across processors
int count = quantity_.nRows()*quantity_.nCols();
lammpsInterface_->allsum(_quantityLocal_.ptr(),quantity_.ptr(),count);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyMeshAccumulationNormalized
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyMeshAccumulationNormalized::OnTheFlyMeshAccumulationNormalized(ATC_Method * atc,
PerAtomQuantity<double> * source,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN * weights):
OnTheFlyMeshAccumulation(atc,source,atomCoarseGrainingPositions),
weights_(weights)
{
weights_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyMeshAccumulationNormalized::reset_quantity() const
{
OnTheFlyMeshAccumulation::reset_quantity();
quantity_ *= weights_->quantity();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyMeshAccumulationNormalizedReferenced
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyMeshAccumulationNormalizedReferenced::OnTheFlyMeshAccumulationNormalizedReferenced(ATC_Method * atc,
PerAtomQuantity<double> * source,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN* weights,
DENS_MAN * reference):
OnTheFlyMeshAccumulationNormalized(atc,source,atomCoarseGrainingPositions,weights),
reference_(reference)
{
reference_->register_dependence(this);
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyMeshAccumulationNormalizedReferenced::reset_quantity() const
{
OnTheFlyMeshAccumulationNormalized::reset_quantity();
quantity_ -= reference_->quantity();
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyMeshAccumulationNormalizedScaled
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyMeshAccumulationNormalizedScaled::OnTheFlyMeshAccumulationNormalizedScaled(ATC_Method * atc,
PerAtomQuantity<double> * source,
DENS_MAN* atomCoarseGrainingPositions,
DIAG_MAN* weights,
const double scale):
OnTheFlyMeshAccumulationNormalized(atc,source,atomCoarseGrainingPositions,weights),
scale_(scale)
{
}
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyMeshAccumulationNormalizedScaled::reset_quantity() const
{
OnTheFlyMeshAccumulationNormalized::reset_quantity();
quantity_ *= scale_;
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class NativeShapeFunctionGradient
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// constructor
//--------------------------------------------------------
NativeShapeFunctionGradient::NativeShapeFunctionGradient(ATC_Method * atc) :
VectorTransfer<SPAR_MAT * >(),
feEngine_(atc->fe_engine())
{
quantity_.resize(atc->nsd(),NULL);
for (int i = 0; i < atc->nsd(); ++i) {
quantity_[i] = new SPAR_MAT();
}
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
NativeShapeFunctionGradient::~NativeShapeFunctionGradient() {
for (unsigned i = 0; i < quantity_.size(); ++i) {
if (quantity_[i]) delete quantity_[i];
}
}
//--------------------------------------------------------
// reset_quantity()
//--------------------------------------------------------
void NativeShapeFunctionGradient::reset_quantity() const
{
feEngine_->compute_gradient_matrix(quantity_);
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class OnTheFlyShapeFunctionProlongation
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
OnTheFlyShapeFunctionProlongation::OnTheFlyShapeFunctionProlongation(ATC_Method * atc,
DENS_MAN * source,
DENS_MAN * atomCoarseGrainingPositions):
FeToAtomTransfer(atc,source),
atomCoarseGrainingPositions_(atomCoarseGrainingPositions),
feMesh_((atc->fe_engine())->fe_mesh())
{
atomCoarseGrainingPositions_->register_dependence(this);
}
//--------------------------------------------------------
// destructor
//--------------------------------------------------------
OnTheFlyShapeFunctionProlongation::~OnTheFlyShapeFunctionProlongation()
{
atomCoarseGrainingPositions_->remove_dependence(this);
};
//--------------------------------------------------------
// reset_quantity
//--------------------------------------------------------
void OnTheFlyShapeFunctionProlongation::reset() const
{
if (need_reset()) {
PerAtomQuantity<double>::reset();
const DENS_MAT & positions(atomCoarseGrainingPositions_->quantity());
const DENS_MAT & source(source_->quantity());
int nodesPerElement = feMesh_->num_nodes_per_element();
Array<int> node_list(nodesPerElement);
DENS_VEC shp(nodesPerElement);
DENS_VEC xj(positions.nCols());
int nLocal = positions.nRows();
quantity_ = 0.;
for (int j = 0; j < nLocal; j++) {
for (int k = 0; k < source.nCols(); k++) {
xj(k) = positions(j,k);
}
feMesh_->shape_functions(xj,shp,node_list);
for (int I = 0; I < nodesPerElement; I++) {
int inode = node_list(I);
for (int k = 0; k < source.nCols(); k++) {
quantity_(j,k) += shp(I)*source(inode,k);
}
}
}
}
}
}