forked from lijiext/lammps
371 lines
12 KiB
C++
371 lines
12 KiB
C++
#include "PerPairQuantity.h"
|
|
#include "PerAtomQuantity.h"
|
|
#include "KernelFunction.h"
|
|
#include "FE_Mesh.h"
|
|
#include "Utility.h"
|
|
#include "Quadrature.h"
|
|
|
|
using ATC::HeartBeat;
|
|
using std::pair;
|
|
using std::map;
|
|
|
|
namespace ATC {
|
|
|
|
//==========================================================
|
|
PairMap::PairMap(LammpsInterface * lammpsInterface, int groupbit ):
|
|
lammpsInterface_(lammpsInterface),
|
|
groupbit_(groupbit),
|
|
nPairs_(0), nBonds_(0)
|
|
{
|
|
};
|
|
PairMap::~PairMap(void)
|
|
{
|
|
};
|
|
//==========================================================
|
|
PairMapNeighbor::PairMapNeighbor(LammpsInterface * lammpsInterface, int groupbit):
|
|
PairMap(lammpsInterface,groupbit)
|
|
{
|
|
};
|
|
|
|
void PairMapNeighbor::reset(void) const
|
|
{
|
|
int inum = lammpsInterface_->neighbor_list_inum();
|
|
int *ilist = lammpsInterface_->neighbor_list_ilist();
|
|
int *numneigh = lammpsInterface_->neighbor_list_numneigh();
|
|
int **firstneigh = lammpsInterface_->neighbor_list_firstneigh();
|
|
const int * mask = lammpsInterface_->atom_mask();
|
|
|
|
pairMap_.clear();
|
|
int pairIndex = nBonds_;
|
|
std::pair< int,int > pair_ij;
|
|
for (int i = 0; i < inum; i++) {
|
|
int lammps_i = ilist[i];
|
|
if (mask[lammps_i] & groupbit_) {
|
|
for (int j = 0; j < numneigh[lammps_i]; j++) {
|
|
int lammps_j = firstneigh[lammps_i][j];
|
|
lammpsInterface_->neighbor_remap(lammps_j);
|
|
pair_ij.first = lammps_i; // alpha
|
|
pair_ij.second = lammps_j; // beta
|
|
pairMap_[pair_ij] = pairIndex;
|
|
pairIndex++;
|
|
}
|
|
}
|
|
}
|
|
nPairs_ = pairIndex;
|
|
needReset_ = false;
|
|
}
|
|
|
|
//==========================================================
|
|
PairMapBond::PairMapBond(LammpsInterface * lammpsInterface, int groupbit):
|
|
PairMap(lammpsInterface,groupbit)
|
|
{
|
|
};
|
|
|
|
//==========================================================
|
|
PairMapBoth::PairMapBoth(LammpsInterface * lammpsInterface, int groupbit):
|
|
PairMapNeighbor(lammpsInterface,groupbit)
|
|
{
|
|
};
|
|
//==========================================================
|
|
DensePerPairMatrix::DensePerPairMatrix(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap,
|
|
int nCols):
|
|
lammpsInterface_(lammpsInterface),
|
|
pairMap_(pairMap),
|
|
nCols_(nCols)
|
|
{
|
|
};
|
|
|
|
//==========================================================
|
|
PairVirial::PairVirial(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap, int nCols):
|
|
DensePerPairMatrix(lammpsInterface,pairMap,nCols)
|
|
{
|
|
};
|
|
//==========================================================
|
|
PairVirialEulerian::PairVirialEulerian(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap):
|
|
PairVirial(lammpsInterface,pairMap,6)
|
|
{
|
|
};
|
|
|
|
|
|
void PairVirialEulerian::reset(void) const
|
|
{
|
|
int nPairs = pairMap_.size();
|
|
quantity_.reset(nPairs,nCols_);
|
|
|
|
double **xatom = lammpsInterface_->xatom();
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
int pairIndex = apair.second;
|
|
double * xa = xatom[lammps_a];
|
|
double * xb = xatom[lammps_b];
|
|
double delx = xa[0] - xb[0];
|
|
double dely = xa[1] - xb[1];
|
|
double delz = xa[2] - xb[2];
|
|
double rsq = delx*delx + dely*dely + delz*delz;
|
|
double fforce = 0;
|
|
lammpsInterface_->pair_force(apair,rsq,fforce);
|
|
quantity_(pairIndex,0)=-delx*delx*fforce;
|
|
quantity_(pairIndex,1)=-dely*dely*fforce;
|
|
quantity_(pairIndex,2)=-delz*delz*fforce;
|
|
quantity_(pairIndex,3)=-delx*dely*fforce;
|
|
quantity_(pairIndex,4)=-delx*delz*fforce;
|
|
quantity_(pairIndex,5)=-dely*delz*fforce;
|
|
}
|
|
}
|
|
//==========================================================
|
|
PairVirialLagrangian::PairVirialLagrangian(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap,
|
|
double ** xRef):
|
|
// const PerAtomQuantity<double> * xRef):
|
|
PairVirial(lammpsInterface,pairMap,9),
|
|
xRef_(xRef)
|
|
{
|
|
|
|
};
|
|
|
|
|
|
void PairVirialLagrangian::reset(void) const
|
|
{
|
|
int nPairs = pairMap_.size();
|
|
quantity_.reset(nPairs,nCols_);
|
|
|
|
double **xatom = lammpsInterface_->xatom();
|
|
|
|
double ** xref = xRef_;
|
|
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
int pairIndex = apair.second;
|
|
double * xa = xatom[lammps_a];
|
|
double * xb = xatom[lammps_b];
|
|
double delx = xa[0] - xb[0];
|
|
double dely = xa[1] - xb[1];
|
|
double delz = xa[2] - xb[2];
|
|
double * Xa = xref[lammps_a];
|
|
double * Xb = xref[lammps_b];
|
|
double delX = Xa[0] - Xb[0];
|
|
double delY = Xa[1] - Xb[1];
|
|
double delZ = Xa[2] - Xb[2];
|
|
double rsq = delx*delx + dely*dely + delz*delz;
|
|
double fforce = 0;
|
|
lammpsInterface_->pair_force(apair,rsq,fforce);
|
|
quantity_(pairIndex,0)=-delx*fforce*delX;
|
|
quantity_(pairIndex,1)=-delx*fforce*delY;
|
|
quantity_(pairIndex,2)=-delx*fforce*delZ;
|
|
quantity_(pairIndex,3)=-dely*fforce*delX;
|
|
quantity_(pairIndex,4)=-dely*fforce*delY;
|
|
quantity_(pairIndex,5)=-dely*fforce*delZ;
|
|
quantity_(pairIndex,6)=-delz*fforce*delX;
|
|
quantity_(pairIndex,7)=-delz*fforce*delY;
|
|
quantity_(pairIndex,8)=-delz*fforce*delZ;
|
|
}
|
|
}
|
|
//==========================================================
|
|
PairPotentialHeatFlux::PairPotentialHeatFlux(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap):
|
|
DensePerPairMatrix(lammpsInterface,pairMap,3)
|
|
{
|
|
};
|
|
//==========================================================
|
|
PairPotentialHeatFluxEulerian::PairPotentialHeatFluxEulerian(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap):
|
|
PairPotentialHeatFlux(lammpsInterface,pairMap)
|
|
{
|
|
|
|
};
|
|
|
|
void PairPotentialHeatFluxEulerian::reset(void) const
|
|
{
|
|
int nPairs = pairMap_.size();
|
|
quantity_.reset(nPairs,nCols_);
|
|
|
|
double **xatom = lammpsInterface_->xatom();
|
|
double **vatom = lammpsInterface_->vatom();
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
int pairIndex = apair.second;
|
|
double * xa = xatom[lammps_a];
|
|
double * xb = xatom[lammps_b];
|
|
double delx = xa[0] - xb[0];
|
|
double dely = xa[1] - xb[1];
|
|
double delz = xa[2] - xb[2];
|
|
double rsq = delx*delx + dely*dely + delz*delz;
|
|
double fforce = 0;
|
|
lammpsInterface_->pair_force(apair,rsq,fforce);
|
|
double* v = vatom[lammps_a];
|
|
fforce *=delx*v[0] + dely*v[1] + delz*v[2];
|
|
quantity_(pairIndex,0)=fforce*delx;
|
|
quantity_(pairIndex,1)=fforce*dely;
|
|
quantity_(pairIndex,2)=fforce*delz;
|
|
}
|
|
}
|
|
//==========================================================
|
|
PairPotentialHeatFluxLagrangian::PairPotentialHeatFluxLagrangian(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap, double ** xRef):
|
|
PairPotentialHeatFlux(lammpsInterface,pairMap),
|
|
xRef_(xRef)
|
|
{
|
|
|
|
};
|
|
|
|
void PairPotentialHeatFluxLagrangian::reset(void) const
|
|
{
|
|
int nPairs = pairMap_.size();
|
|
quantity_.reset(nPairs,nCols_);
|
|
|
|
double **xatom = lammpsInterface_->xatom();
|
|
double **vatom = lammpsInterface_->vatom();
|
|
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
int pairIndex = apair.second;
|
|
double * xa = xatom[lammps_a];
|
|
double * xb = xatom[lammps_b];
|
|
double delx = xa[0] - xb[0];
|
|
double dely = xa[1] - xb[1];
|
|
double delz = xa[2] - xb[2];
|
|
double * Xa = xRef_[lammps_a];
|
|
double * Xb = xRef_[lammps_b];
|
|
double delX = Xa[0] - Xb[0];
|
|
double delY = Xa[1] - Xb[1];
|
|
double delZ = Xa[2] - Xb[2];
|
|
double rsq = delx*delx + dely*dely + delz*delz;
|
|
double fforce = 0;
|
|
lammpsInterface_->pair_force(apair,rsq,fforce);
|
|
double* v = vatom[lammps_a];
|
|
fforce *=delx*v[0] + dely*v[1] + delz*v[2];
|
|
quantity_(pairIndex,0)=fforce*delX;
|
|
quantity_(pairIndex,1)=fforce*delY;
|
|
quantity_(pairIndex,2)=fforce*delZ;
|
|
}
|
|
}
|
|
//==========================================================
|
|
SparsePerPairMatrix::SparsePerPairMatrix(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap):
|
|
lammpsInterface_(lammpsInterface),
|
|
pairMap_(pairMap)
|
|
{
|
|
};
|
|
//==========================================================
|
|
BondMatrix::BondMatrix(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap, double ** x, const FE_Mesh * feMesh):
|
|
SparsePerPairMatrix(lammpsInterface,pairMap), x_(x), feMesh_(feMesh)
|
|
{
|
|
};
|
|
//==========================================================
|
|
BondMatrixKernel::BondMatrixKernel(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap,
|
|
double ** x,
|
|
const FE_Mesh * feMesh,
|
|
const KernelFunction * kernelFunction):
|
|
BondMatrix(lammpsInterface,pairMap,x,feMesh),
|
|
kernelFunction_(kernelFunction)
|
|
{
|
|
};
|
|
void BondMatrixKernel::reset(void) const
|
|
{
|
|
int nPairs = pairMap_.size(); // needs to come after quantity for reset
|
|
int nNodes = feMesh_->num_nodes_unique();
|
|
quantity_.reset(nNodes,nPairs);
|
|
double lam1,lam2;
|
|
std::pair< int,int > pair_jk;
|
|
int heartbeatFreq = (nNodes <= 10 ? 1 : (int) nNodes / 10);
|
|
HeartBeat beat("computing bond matrix ",heartbeatFreq);
|
|
beat.start();
|
|
DENS_VEC xa(3),xI(3),xaI(3),xb(3),xbI(3),xba(3);
|
|
double invVol = kernelFunction_->inv_vol();
|
|
for (int I = 0; I < nNodes; I++) {
|
|
beat.next();
|
|
xI = feMesh_->nodal_coordinates(I);
|
|
if (!kernelFunction_->node_contributes(xI)) { continue; }
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
xa.copy(x_[lammps_a],3);
|
|
xaI = xa - xI;
|
|
lammpsInterface_->periodicity_correction(xaI.ptr());
|
|
xb.copy(x_[lammps_b],3);
|
|
xba = xb - xa;
|
|
xbI = xba + xaI;
|
|
kernelFunction_->bond_intercepts(xaI,xbI,lam1,lam2);
|
|
if (lam1 < lam2) {
|
|
double bondValue = invVol*(kernelFunction_->bond(xaI,xbI,lam1,lam2));
|
|
int pairIndex = apair.second;
|
|
quantity_.add(I,pairIndex,bondValue);
|
|
} // if lam1 < lam2
|
|
} // pair map
|
|
} // end nodes loop
|
|
quantity_.compress();
|
|
beat.finish();
|
|
}
|
|
//==========================================================
|
|
BondMatrixPartitionOfUnity::BondMatrixPartitionOfUnity(LammpsInterface * lammpsInterface,
|
|
const PairMap & pairMap, double ** x, const FE_Mesh * feMesh,
|
|
const DIAG_MAN * invVols):
|
|
BondMatrix(lammpsInterface,pairMap,x,feMesh),
|
|
invVols_(invVols)
|
|
{
|
|
ATC::Quadrature::instance()->set_line_quadrature(lineNgauss_,lineXg_,lineWg_);
|
|
double lam1 = 0.0, lam2 = 1.0;
|
|
double del_lambda = 0.5*(lam2 - lam1);
|
|
double avg_lambda = 0.5*(lam2 + lam1);
|
|
for (int i = 0; i < lineNgauss_; i++) {
|
|
double lambda = del_lambda*lineXg_[i] +avg_lambda;
|
|
lineXg_[i] = lambda;
|
|
lineWg_[i] *= 0.5;
|
|
}
|
|
};
|
|
void BondMatrixPartitionOfUnity::reset(void) const
|
|
{
|
|
int nNodes = feMesh_->num_nodes_unique();
|
|
int nPairs = pairMap_.size();
|
|
quantity_.reset(nNodes,nPairs);
|
|
int nodes_per_element = feMesh_->num_nodes_per_element();
|
|
Array<int> node_list(nodes_per_element);
|
|
DENS_VEC shp(nodes_per_element);
|
|
std::pair< int,int > pair_jk;
|
|
int heartbeatFreq = (int) nPairs / 10;
|
|
HeartBeat beat("computing bond matrix ",heartbeatFreq);
|
|
beat.start();
|
|
DENS_VEC xa(3),xb(3),xab(3),xlambda(3);
|
|
for (ATOM_PAIR apair = pairMap_.start();
|
|
! pairMap_.finished(); apair=pairMap_++){
|
|
beat.next();
|
|
int lammps_a = (apair.first).first ;
|
|
int lammps_b = (apair.first).second;
|
|
int pairIndex = apair.second;
|
|
xa.copy(x_[lammps_a],3);
|
|
xb.copy(x_[lammps_b],3);
|
|
xab = xa - xb;
|
|
for (int i = 0; i < lineNgauss_; i++) {
|
|
double lambda = lineXg_[i];
|
|
xlambda = lambda*xab + xb;
|
|
lammpsInterface_->periodicity_correction(xlambda.ptr());
|
|
feMesh_->shape_functions(xlambda,shp,node_list);
|
|
// accumulate to nodes whose support overlaps the integration point
|
|
for (int I = 0; I < nodes_per_element; I++) {
|
|
int Inode = node_list(I);
|
|
double inv_vol = (invVols_->quantity())(Inode,Inode);
|
|
double val = inv_vol*shp(I)*lineWg_[i];
|
|
quantity_.add(Inode,pairIndex,val);
|
|
}
|
|
}
|
|
}
|
|
quantity_.compress();
|
|
beat.finish();
|
|
}
|
|
//==========================================================
|
|
}
|