ATC version 2.0, date: Nov20

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@12757 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
jatempl
2014-11-20 18:59:03 +00:00
parent 2fecb0f4b8
commit ac5973073f
69 changed files with 5895 additions and 2159 deletions

View File

@ -4,6 +4,13 @@
#include "LammpsInterface.h"
#include "ATC_Error.h"
using std::vector;
using std::set;
using std::pair;
using std::map;
using std::stringstream;
using ATC_Utility::to_string;
namespace ATC {
//--------------------------------------------------------
@ -19,10 +26,7 @@ namespace ATC {
ghostModifier_(NULL),
atc_(atc),
boundaryDynamics_(NO_BOUNDARY_DYNAMICS),
needReset_(true),
kappa_(0.),
gamma_(0.),
mu_(0.)
needReset_(true)
{
// do nothing
}
@ -73,18 +77,30 @@ namespace ATC {
}
else if (strcmp(arg[argIndex],"damped_harmonic")==0) {
argIndex++;
kappa_ = atof(arg[argIndex++]);
gamma_ = atof(arg[argIndex++]);
mu_ = atof(arg[argIndex]);
kappa_.push_back(atof(arg[argIndex++]));
gamma_.push_back(atof(arg[argIndex++]));
mu_.push_back(atof(arg[argIndex]));
boundaryDynamics_ = DAMPED_HARMONIC;
needReset_ = true;
return true;
}
else if (strcmp(arg[argIndex],"damped_layers")==0) {
argIndex++;
while (argIndex < narg) {
kappa_.push_back(atof(arg[argIndex++]));
gamma_.push_back(atof(arg[argIndex++]));
mu_.push_back(atof(arg[argIndex++]));
}
boundaryDynamics_ = DAMPED_LAYERS;
needReset_ = true;
return true;
}
else if (strcmp(arg[argIndex],"coupled")==0) {
boundaryDynamics_ = COUPLED;
kappa_ = 0.;
gamma_ = 0.;
mu_ = 0.;
kappa_.push_back(0.);
gamma_.push_back(0.);
mu_.push_back(0.);
needReset_ = true;
return true;
}
@ -124,6 +140,11 @@ namespace ATC {
ghostModifier_->set_integrate_atoms(true);
break;
}
case DAMPED_LAYERS: {
ghostModifier_ = new GhostModifierDampedHarmonicLayers(this,kappa_,gamma_,mu_);
ghostModifier_->set_integrate_atoms(true);
break;
}
case SWAP: {
// if regions based on element sets, use verlet on ghosts and swap ghosts and internal when they move between regions
const std::string & internalElementSet(atc_->internal_element_set());
@ -357,8 +378,9 @@ namespace ATC {
// Constructor
//--------------------------------------------------------
GhostModifierDampedHarmonic::GhostModifierDampedHarmonic(GhostManager * ghostManager,
double kappa,
double gamma, double mu) :
const vector<double> & kappa,
const vector<double> & gamma,
const vector<double> & mu) :
GhostModifierPrescribed(ghostManager),
atomVelocities_(NULL),
atomFeVelocity_(NULL),
@ -396,13 +418,18 @@ namespace ATC {
k0_ = LammpsInterface::instance()->bond_stiffness(i,j,rsq);
}
#if true
//--------------------------------------------------------
// initial_integrate_velocity
// velocity update in first part of velocity-verlet
//--------------------------------------------------------
void GhostModifierDampedHarmonic::init_integrate_velocity(double dt)
{
atomTimeIntegrator_->init_integrate_velocity(mu_*dt);
#if true
atomTimeIntegrator_->init_integrate_velocity(mu_[0]*dt);
#else
atomTimeIntegrator_->init_integrate_velocity(dt);
#endif
}
//--------------------------------------------------------
@ -413,7 +440,7 @@ namespace ATC {
{
atomTimeIntegrator_->init_integrate_position(dt);
}
#endif
//--------------------------------------------------------
// final_integrate
// velocity update in second part of velocity-verlet
@ -430,11 +457,265 @@ namespace ATC {
_forces_ = atomFeDisplacement;
_forces_ += atomRefPositions;
_forces_ -= atomPositions;
_forces_ *= kappa_;
_forces_ += gamma_*(atomFeVelocity - atomVelocities);
_forces_ *= kappa_[0];
_forces_ += gamma_[0]*(atomFeVelocity - atomVelocities);
#if true
#else
_forces_ *= 1./mu_[0];
#endif
*atomForces_ = _forces_;
atomTimeIntegrator_->final_integrate(mu_*dt);
#if true
atomTimeIntegrator_->final_integrate(mu_[0]*dt);
#else
atomTimeIntegrator_->final_integrate(dt);
#endif
}
//--------------------------------------------------------
//--------------------------------------------------------
// Class GhostModifierDampedHarmonicLayers
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
GhostModifierDampedHarmonicLayers::GhostModifierDampedHarmonicLayers(GhostManager * ghostManager,
const vector<double> & kappa,
const vector<double> & gamma,
const vector<double> & mu) :
GhostModifierDampedHarmonic(ghostManager,kappa,gamma,mu),
ghostToBoundaryDistance_(NULL),
layerId_(NULL)
{
// do nothing
}
//--------------------------------------------------------
// construct_transfers
// sets/constructs all required dependency managed data
//--------------------------------------------------------
void GhostModifierDampedHarmonicLayers::construct_transfers()
{
GhostModifierDampedHarmonic::construct_transfers();
InterscaleManager & interscaleManager((ghostManager_->atc())->interscale_manager());
// transfer for distance to boundary
ghostToBoundaryDistance_ = new AtcAtomQuantity<double>(ghostManager_->atc(),
1,GHOST);
interscaleManager.add_per_atom_quantity(ghostToBoundaryDistance_,
"GhostToBoundaryDistance");
// transfer from ghost atom to its layer id
layerId_ = new AtcAtomQuantity<int>(ghostManager_->atc(),
1,GHOST);
interscaleManager.add_per_atom_int_quantity(layerId_,"GhostLayerId");
}
//--------------------------------------------------------
// initialize
// initialize all data and variables before a run
//--------------------------------------------------------
void GhostModifierDampedHarmonicLayers::initialize()
{
compute_distances();
int nlayers = find_layers();
if (nlayers > ((int)gamma_.size())) throw ATC_Error("GhostModifierDampedHarmonicLayers::initialize not enough damping factors specfied " + to_string(gamma_.size()));
}
//--------------------------------------------------------
// find atomic mononlayers
//--------------------------------------------------------
bool compare( pair<int,double> a, pair<int,double> b) {
return (a.second < b.second);
}
int GhostModifierDampedHarmonicLayers::find_layers()
{
DENS_MAT & d(ghostToBoundaryDistance_->set_quantity());
DenseMatrix<int> & ids = layerId_->set_quantity();
// get distances for every ghost atom for sorting
// size arrays of length number of processors
int commSize = LammpsInterface::instance()->comm_size();
int * procCounts = new int[commSize];
int * procOffsets = new int[commSize];
// get size information from all processors
int localGhosts = d.nRows();
LammpsInterface::instance()->int_allgather(localGhosts,procCounts);
procOffsets[0] = 0;
int totalGhosts = 0;
for (int i = 0; i < commSize-1; ++i) {
totalGhosts += procCounts[i];
procOffsets[i+1] = totalGhosts;
}
totalGhosts += procCounts[commSize-1];
double * globalDistances = new double[totalGhosts];
// allgather distances
LammpsInterface::instance()->allgatherv(d.ptr(), localGhosts,
globalDistances, procCounts, procOffsets);
// add to distances vector with -1 ids
// convert to STL for sort
vector< pair <int,double> > distances;
distances.resize(totalGhosts);
int myRank = LammpsInterface::instance()->comm_rank();
int j = 0;
for (int i = 0; i < totalGhosts; ++i) {
if (i >= procOffsets[myRank] && i < procOffsets[myRank] + procCounts[myRank]) {
distances[i] = pair <int,double> (j++,globalDistances[i]);
}
else {
distances[i] = pair <int,double> (-1,globalDistances[i]);
}
}
delete [] globalDistances;
delete [] procCounts;
delete [] procOffsets;
std::sort(distances.begin(),distances.end(),compare);
double min = (distances[0]).second;
double a = LammpsInterface::instance()->max_lattice_constant();
double tol = a/4;
double xlayer = min; // nominal position of layer
int ilayer =0;
vector<int> counts(1);
counts[0] = 0;
for (vector<pair<int,double> >::const_iterator itr = distances.begin();
itr != distances.end(); itr++) {
int id = (*itr).first;
double d = (*itr).second;
if (fabs(d-xlayer) > tol) {
counts.push_back(0);
ilayer++;
xlayer = d;
}
if (id > -1) {
ids(id,0) = ilayer;
}
counts[ilayer]++;
}
int nlayers = ilayer;
stringstream msg;
msg << nlayers << " boundary layers:\n";
for (int i = 0; i < nlayers; ++i) {
msg << i+1 << ": " << counts[i] << "\n";
}
ATC::LammpsInterface::instance()->print_msg_once(msg.str());
return nlayers;
}
//--------------------------------------------------------
// compute distances to boundary faces
//--------------------------------------------------------
void GhostModifierDampedHarmonicLayers::compute_distances()
{
// get fe mesh
const FE_Mesh * feMesh = ((ghostManager_->atc())->fe_engine())->fe_mesh();
InterscaleManager & interscaleManager((ghostManager_->atc())->interscale_manager());
// get elements in which ghosts reside
const DenseMatrix<int> & elementHasGhost((interscaleManager.dense_matrix_int("ElementHasGhost"))->quantity());
// get type of each node
const DenseMatrix<int> & nodeType((interscaleManager.dense_matrix_int("NodalGeometryType"))->quantity());
// create map from those elements to pair<DENS_VEC,DENS_VEC> (centroid, normal)
map<int, pair<DENS_VEC,DENS_VEC> > elementToFace;
int nsd = (ghostManager_->atc())->nsd();
int nfe = feMesh->num_faces_per_element();
DENS_MAT nodalCoords(nsd,nfe);
DENS_VEC centroid(nsd), normal(nsd);
Array<int> faceNodes;
bool isBoundaryFace;
for (int elt = 0; elt < elementHasGhost.nRows(); ++elt) {
if (elementHasGhost(elt,0)) {
// loop over all faces
int face;
for (face = 0; face < nfe; ++face) {
// get the nodes in a face
feMesh->face_connectivity_unique(PAIR(elt,face),faceNodes);
// identify the boundary face by the face which contains only boundary nodes
isBoundaryFace = true;
for (int i = 0; i < faceNodes.size(); ++i) {
if (nodeType(faceNodes(i),0) != BOUNDARY) {
isBoundaryFace = false;
break;
}
}
if (isBoundaryFace) {
break;
}
}
if (face == nfe) {
throw ATC_Error("GhostModifierDampedHarmonicLayers::initialize - Could not find boundary face for element " + to_string(elt));
}
// for each boundary face get the centroid by the average position of the nodes comprising it
feMesh->face_coordinates(PAIR(elt,face),nodalCoords);
centroid = 0.;
for (int i = 0; i < nodalCoords.nRows(); ++i) {
for (int j = 0; j < nodalCoords.nCols(); ++j) {
centroid(i) += nodalCoords(i,j);
}
}
centroid *= -1./double(nfe); // -1 gets outward normal from ATC region => all distances should be > 0
// for each boundary face get the normal
// ASSUMES all faces are planar
feMesh->face_normal(PAIR(elt,face),0,normal);
elementToFace[elt] = pair<DENS_VEC,DENS_VEC>(centroid,normal);
}
}
// for each atom compute (atom_pos - element->face_centroid) dot element_->face_normal
// get atom to element map for ghosts
PerAtomQuantity<int> * ghostToElementMap = interscaleManager.per_atom_int_quantity("AtomGhostElement");
const DenseMatrix<int> & ghostToElement(ghostToElementMap->quantity());
DENS_MAT & distance(ghostToBoundaryDistance_->set_quantity());
const DENS_MAT & atomPositions(atomPositions_->quantity());
DENS_VEC diff(nsd);
for (int i = 0; i < distance.nRows(); ++i) {
int elt = ghostToElement(i,0);
const DENS_VEC & c(elementToFace[elt].first);
const DENS_VEC & n(elementToFace[elt].second);
for (int j = 0; j < nsd; ++j) {
diff(j) = atomPositions(i,j) - c(j);
}
distance(i,0) = diff.dot(n); // should always be positive
}
}
//--------------------------------------------------------
// final_integrate
// velocity update in second part of velocity-verlet
//--------------------------------------------------------
void GhostModifierDampedHarmonicLayers::final_integrate(double dt)
{
const DENS_MAT & atomPositions(atomPositions_->quantity());
const DENS_MAT & atomVelocities(atomVelocities_->quantity());
const DENS_MAT & atomFeDisplacement(atomFeDisplacement_->quantity());
const DENS_MAT & atomFeVelocity(atomFeVelocity_->quantity());
const DENS_MAT & atomRefPositions(atomRefPositions_->quantity());
_forces_ = atomFeDisplacement;
_forces_ += atomRefPositions;
_forces_ -= atomPositions;
_forces_ *= kappa_[0];
_forces_ += gamma_[0]*(atomFeVelocity - atomVelocities);
_forces_ *= 1./mu_[0];
*atomForces_ = _forces_;
atomTimeIntegrator_->final_integrate(dt);
}
//--------------------------------------------------------