mirror of https://github.com/lammps/lammps.git
398 lines
13 KiB
C++
398 lines
13 KiB
C++
|
#include "PerPairQuantity.h"
|
||
|
#include "PerAtomQuantity.h"
|
||
|
#include "KernelFunction.h"
|
||
|
#include "FE_Mesh.h"
|
||
|
#include "Utility.h"
|
||
|
#include "Quadrature.h"
|
||
|
|
||
|
using ATC::HeartBeat;
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
};
|
||
|
bool PairMapNeighbor::need_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();
|
||
|
|
||
|
pair< int,int > pair_ij;
|
||
|
map< pair< int,int >,int >::iterator pairMapIterator;
|
||
|
|
||
|
int npairs = 0;
|
||
|
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];
|
||
|
pair_ij.first = lammps_i;
|
||
|
pair_ij.second = lammps_j;
|
||
|
pairMapIterator = pairMap_.find(pair_ij);
|
||
|
if (pairMapIterator == pairMap_.end()) {
|
||
|
return true;
|
||
|
}
|
||
|
npairs++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (npairs != (int) pairMap_.size()) return true;
|
||
|
nPairs_ = npairs;
|
||
|
return false;
|
||
|
}
|
||
|
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_;
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
//==========================================================
|
||
|
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;
|
||
|
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);
|
||
|
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();
|
||
|
}
|
||
|
//==========================================================
|
||
|
}
|